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
19 #include "inseng_private.h"
21 #define DEFAULT_INSTALLER_DESC "Active Setup Installation"
25 ICifGroup ICifGroup_iface
;
36 struct ciffenum_components
38 IEnumCifComponents IEnumCifComponents_iface
;
43 struct list
*position
;
48 struct ciffenum_groups
50 IEnumCifGroups IEnumCifGroups_iface
;
55 struct list
*position
;
66 struct dependency_info
75 ICifComponent ICifComponent_iface
;
112 struct list dependencies
;
120 /* in memory state */
122 DWORD current_priority
;
123 DWORD size_actual_download
;
130 ICifFile ICifFile_iface
;
133 struct list components
;
139 static inline struct ciffile
*impl_from_ICiffile(ICifFile
*iface
)
141 return CONTAINING_RECORD(iface
, struct ciffile
, ICifFile_iface
);
144 static inline struct cifcomponent
*impl_from_ICifComponent(ICifComponent
*iface
)
146 return CONTAINING_RECORD(iface
, struct cifcomponent
, ICifComponent_iface
);
149 static inline struct cifgroup
*impl_from_ICifGroup(ICifGroup
*iface
)
151 return CONTAINING_RECORD(iface
, struct cifgroup
, ICifGroup_iface
);
154 static inline struct ciffenum_components
*impl_from_IEnumCifComponents(IEnumCifComponents
*iface
)
156 return CONTAINING_RECORD(iface
, struct ciffenum_components
, IEnumCifComponents_iface
);
159 static inline struct ciffenum_groups
*impl_from_IEnumCifGroups(IEnumCifGroups
*iface
)
161 return CONTAINING_RECORD(iface
, struct ciffenum_groups
, IEnumCifGroups_iface
);
164 static HRESULT
enum_components_create(ICifFile
*file
, struct list
*start
, char *group_id
, IEnumCifComponents
**iface
);
166 static HRESULT
copy_substring_null(char *dest
, int max_len
, char *src
)
177 while (*src
&& max_len
-- > 1)
184 static void url_entry_free(struct url_info
*url
)
190 static void dependency_entry_free(struct dependency_info
*dependency
)
192 heap_free(dependency
->id
);
193 heap_free(dependency
);
196 static void component_free(struct cifcomponent
*comp
)
198 struct dependency_info
*dependency
, *dependency_next
;
199 struct url_info
*url
, *url_next
;
202 heap_free(comp
->guid
);
203 heap_free(comp
->description
);
204 heap_free(comp
->details
);
205 heap_free(comp
->group
);
207 heap_free(comp
->patchid
);
209 heap_free(comp
->locale
);
210 heap_free(comp
->key_uninstall
);
212 heap_free(comp
->key_success
);
213 heap_free(comp
->key_progress
);
214 heap_free(comp
->key_cancel
);
216 LIST_FOR_EACH_ENTRY_SAFE(dependency
, dependency_next
, &comp
->dependencies
, struct dependency_info
, entry
)
218 list_remove(&dependency
->entry
);
219 dependency_entry_free(dependency
);
222 LIST_FOR_EACH_ENTRY_SAFE(url
, url_next
, &comp
->urls
, struct url_info
, entry
)
224 list_remove(&url
->entry
);
231 static void group_free(struct cifgroup
*group
)
233 heap_free(group
->id
);
234 heap_free(group
->description
);
238 static HRESULT WINAPI
group_GetID(ICifGroup
*iface
, char *id
, DWORD size
)
240 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
242 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
244 return copy_substring_null(id
, size
, This
->id
);
247 static HRESULT WINAPI
group_GetDescription(ICifGroup
*iface
, char *desc
, DWORD size
)
249 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
251 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
253 return copy_substring_null(desc
, size
, This
->description
);
256 static DWORD WINAPI
group_GetPriority(ICifGroup
*iface
)
258 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
260 TRACE("(%p)\n", This
);
262 return This
->priority
;
265 static HRESULT WINAPI
group_EnumComponents(ICifGroup
*iface
, IEnumCifComponents
**enum_components
, DWORD filter
, LPVOID pv
)
267 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
268 struct ciffile
*file
;
270 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_components
, filter
, pv
);
273 FIXME("filter (%x) not supported\n", filter
);
275 FIXME("how to handle pv (%p)?\n", pv
);
277 file
= impl_from_ICiffile(This
->parent
);
278 return enum_components_create(This
->parent
, &file
->components
, This
->id
, enum_components
);
281 static DWORD WINAPI
group_GetCurrentPriority(ICifGroup
*iface
)
283 struct cifgroup
*This
= impl_from_ICifGroup(iface
);
285 FIXME("(%p): stub\n", This
);
290 static const ICifGroupVtbl cifgroupVtbl
=
293 group_GetDescription
,
295 group_EnumComponents
,
296 group_GetCurrentPriority
,
299 void component_set_actual_download_size(ICifComponent
*iface
, DWORD size
)
301 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
303 This
->size_actual_download
= size
;
306 void component_set_downloaded(ICifComponent
*iface
, BOOL value
)
308 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
310 This
->downloaded
= value
;
313 void component_set_installed(ICifComponent
*iface
, BOOL value
)
315 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
317 This
->installed
= value
;
320 char *component_get_id(ICifComponent
*iface
)
322 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
327 static HRESULT WINAPI
component_GetID(ICifComponent
*iface
, char *id
, DWORD size
)
329 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
331 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
333 return copy_substring_null(id
, size
, This
->id
);
336 static HRESULT WINAPI
component_GetGUID(ICifComponent
*iface
, char *guid
, DWORD size
)
338 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
340 TRACE("(%p)->(%p, %u)\n", This
, guid
, size
);
342 return copy_substring_null(guid
, size
, This
->guid
);
345 static HRESULT WINAPI
component_GetDescription(ICifComponent
*iface
, char *desc
, DWORD size
)
347 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
349 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
351 return copy_substring_null(desc
, size
, This
->description
);
354 static HRESULT WINAPI
component_GetDetails(ICifComponent
*iface
, char *details
, DWORD size
)
356 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
358 TRACE("(%p)->(%p, %u)\n", This
, details
, size
);
360 return copy_substring_null(details
, size
, This
->details
);
363 static HRESULT WINAPI
component_GetUrl(ICifComponent
*iface
, UINT index
, char *url
, DWORD size
, DWORD
*flags
)
365 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
366 struct url_info
*entry
;
368 TRACE("(%p)->(%u, %p, %u, %p)\n", This
, index
, url
, size
, flags
);
370 /* FIXME: check how functions behaves for url == NULL */
375 LIST_FOR_EACH_ENTRY(entry
, &This
->urls
, struct url_info
, entry
)
377 if (entry
->index
!= index
)
380 *flags
= entry
->flags
;
381 return copy_substring_null(url
, size
, entry
->url
);
387 static HRESULT WINAPI
component_GetFileExtractList(ICifComponent
*iface
, UINT index
, char *list
, DWORD size
)
389 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
391 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, list
, size
);
396 static HRESULT WINAPI
component_GetUrlCheckRange(ICifComponent
*iface
, UINT index
, DWORD
*min
, DWORD
*max
)
398 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
400 FIXME("(%p)->(%u, %p, %p): stub\n", This
, index
, min
, max
);
405 static HRESULT WINAPI
component_GetCommand(ICifComponent
*iface
, UINT index
, char *cmd
, DWORD cmd_size
, char *switches
, DWORD switch_size
, DWORD
*type
)
407 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
409 FIXME("(%p)->(%u, %p, %u, %p, %u, %p): stub\n", This
, index
, cmd
, cmd_size
, switches
, switch_size
, type
);
414 static HRESULT WINAPI
component_GetVersion(ICifComponent
*iface
, DWORD
*version
, DWORD
*build
)
416 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
418 TRACE("(%p)->(%p, %p)\n", This
, version
, build
);
420 if (!version
|| !build
)
423 *version
= This
->version
;
424 *build
= This
->build
;
429 static HRESULT WINAPI
component_GetLocale(ICifComponent
*iface
, char *locale
, DWORD size
)
431 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
433 TRACE("(%p)->(%p, %u)\n", This
, locale
, size
);
435 return copy_substring_null(locale
, size
, This
->locale
);
438 static HRESULT WINAPI
component_GetUninstallKey(ICifComponent
*iface
, char *key
, DWORD size
)
440 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
442 TRACE("(%p)->(%p, %u)\n", This
, key
, size
);
444 return copy_substring_null(key
, size
, This
->key_uninstall
);
447 static HRESULT WINAPI
component_GetInstalledSize(ICifComponent
*iface
, DWORD
*win
, DWORD
*app
)
449 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
451 TRACE("(%p)->(%p, %p)\n", This
, win
, app
);
456 *win
= This
->size_win
;
457 *app
= This
->size_app
;
462 static DWORD WINAPI
component_GetDownloadSize(ICifComponent
*iface
)
464 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
466 TRACE("(%p)\n", This
);
468 return This
->size_download
;
471 static DWORD WINAPI
component_GetExtractSize(ICifComponent
*iface
)
473 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
475 TRACE("(%p)\n", This
);
477 return This
->size_extracted
;
480 static HRESULT WINAPI
component_GetSuccessKey(ICifComponent
*iface
, char *key
, DWORD size
)
482 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
484 TRACE("(%p)->(%p, %u)\n", This
, key
, size
);
486 return copy_substring_null(key
, size
, This
->key_success
);
489 static HRESULT WINAPI
component_GetProgressKeys(ICifComponent
*iface
, char *progress
, DWORD progress_size
,
490 char *cancel
, DWORD cancel_size
)
492 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
495 TRACE("(%p)->(%p, %u, %p, %u): semi-stub\n", This
, progress
, progress_size
, cancel
, cancel_size
);
497 hr
= copy_substring_null(progress
, progress_size
, This
->key_progress
);
498 if (hr
!= S_OK
) return hr
;
500 if (cancel_size
> 0 && cancel
)
506 static HRESULT WINAPI
component_IsActiveSetupAware(ICifComponent
*iface
)
508 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
510 TRACE("(%p)\n", This
);
512 return This
->as_aware
? S_OK
: S_FALSE
;
515 static HRESULT WINAPI
component_IsRebootRequired(ICifComponent
*iface
)
517 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
519 TRACE("(%p)\n", This
);
521 return This
->reboot
? S_OK
: S_FALSE
;
524 static HRESULT WINAPI
component_RequiresAdminRights(ICifComponent
*iface
)
526 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
528 TRACE("(%p)\n", This
);
530 return This
->admin
? S_OK
: S_FALSE
;
533 static DWORD WINAPI
component_GetPriority(ICifComponent
*iface
)
535 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
537 TRACE("(%p)\n", This
);
539 return This
->priority
;
542 static HRESULT WINAPI
component_GetDependency(ICifComponent
*iface
, UINT index
, char *id
, DWORD id_size
, char *type
, DWORD
*ver
, DWORD
*build
)
544 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
545 struct dependency_info
*entry
;
546 ICifComponent
*dependency
;
549 TRACE("(%p)->(%u, %p, %u, %p, %p, %p)\n", This
, index
, id
, id_size
, type
, ver
, build
);
551 if (!id
|| !ver
|| !build
)
554 LIST_FOR_EACH_ENTRY(entry
, &This
->dependencies
, struct dependency_info
, entry
)
559 if (ICifFile_FindComponent(This
->parent
, entry
->id
, &dependency
) == S_OK
)
561 ICifComponent_GetVersion(dependency
, ver
, build
);
570 *type
= *entry
->type
;
574 return copy_substring_null(id
, id_size
, entry
->id
);
580 static DWORD WINAPI
component_GetPlatform(ICifComponent
*iface
)
582 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
584 TRACE("(%p)\n", This
);
586 return This
->platform
;
589 static HRESULT WINAPI
component_GetMode(ICifComponent
*iface
, UINT index
, char *mode
, DWORD size
)
591 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
593 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, mode
, size
);
598 static HRESULT WINAPI
component_GetGroup(ICifComponent
*iface
, char *id
, DWORD size
)
600 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
602 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
604 return copy_substring_null(id
, size
, This
->group
);
607 static HRESULT WINAPI
component_IsUIVisible(ICifComponent
*iface
)
609 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
611 TRACE("(%p)\n", This
);
613 return This
->visibleui
? S_OK
: S_FALSE
;
616 static HRESULT WINAPI
component_GetPatchID(ICifComponent
*iface
, char *id
, DWORD size
)
618 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
620 TRACE("(%p)->(%p, %u)\n", This
, id
, size
);
622 return copy_substring_null(id
, size
, This
->patchid
);
625 static HRESULT WINAPI
component_GetDetVersion(ICifComponent
*iface
, char *dll
, DWORD dll_size
, char *entry
, DWORD entry_size
)
627 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
629 FIXME("(%p)->(%p, %u, %p, %u): stub\n", This
, dll
, dll_size
, entry
, entry_size
);
634 static HRESULT WINAPI
component_GetTreatAsOneComponents(ICifComponent
*iface
, UINT index
, char *id
, DWORD size
)
636 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
638 FIXME("(%p)->(%u, %p, %u): stub\n", This
, index
, id
, size
);
643 static HRESULT WINAPI
component_GetCustomData(ICifComponent
*iface
, char *key
, char *data
, DWORD size
)
645 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
647 FIXME("(%p)->(%s, %p, %u): stub\n", This
, debugstr_a(key
), data
, size
);
652 static DWORD WINAPI
component_IsComponentInstalled(ICifComponent
*iface
)
654 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
656 TRACE("(%p)\n", This
);
658 return This
->installed
;
661 static HRESULT WINAPI
component_IsComponentDownloaded(ICifComponent
*iface
)
663 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
665 TRACE("(%p)\n", This
);
667 return This
->downloaded
? S_OK
: S_FALSE
;
670 static DWORD WINAPI
component_IsThisVersionInstalled(ICifComponent
*iface
, DWORD version
, DWORD build
, DWORD
*ret_version
, DWORD
*ret_build
)
672 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
674 FIXME("(%p)->(%u, %u, %p, %p): stub\n", This
, version
, build
, ret_version
, ret_build
);
679 static DWORD WINAPI
component_GetInstallQueueState(ICifComponent
*iface
)
681 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
683 TRACE("(%p)\n", This
);
685 return This
->queue_state
;
688 static HRESULT WINAPI
component_SetInstallQueueState(ICifComponent
*iface
, DWORD state
)
690 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
692 TRACE("(%p)->(%u)\n", This
, state
);
694 This
->queue_state
= state
;
698 static DWORD WINAPI
component_GetActualDownloadSize(ICifComponent
*iface
)
700 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
702 TRACE("(%p)\n", This
);
704 return This
->size_download
;
707 static DWORD WINAPI
component_GetCurrentPriority(ICifComponent
*iface
)
709 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
711 TRACE("(%p)\n", This
);
713 return This
->current_priority
;
717 static HRESULT WINAPI
component_SetCurrentPriority(ICifComponent
*iface
, DWORD priority
)
719 struct cifcomponent
*This
= impl_from_ICifComponent(iface
);
721 TRACE("(%p)->(%u)\n", This
, priority
);
723 This
->current_priority
= priority
;
727 static const ICifComponentVtbl cifcomponentVtbl
=
731 component_GetDescription
,
732 component_GetDetails
,
734 component_GetFileExtractList
,
735 component_GetUrlCheckRange
,
736 component_GetCommand
,
737 component_GetVersion
,
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
,
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
,
768 static HRESULT WINAPI
enum_components_QueryInterface(IEnumCifComponents
*iface
, REFIID riid
, void **ppv
)
770 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
772 if (IsEqualGUID(&IID_IUnknown
, riid
))
774 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
775 *ppv
= &This
->IEnumCifComponents_iface
;
778 else if (IsEqualGUID(&IID_IEnumCifComponents, riid))
780 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
781 *ppv = &This->IEnumCifComponents_iface;
786 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
788 return E_NOINTERFACE
;
791 IUnknown_AddRef((IUnknown
*)*ppv
);
795 static ULONG WINAPI
enum_components_AddRef(IEnumCifComponents
*iface
)
797 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
798 LONG ref
= InterlockedIncrement(&This
->ref
);
800 TRACE("(%p) ref=%d\n", This
, ref
);
805 static ULONG WINAPI
enum_components_Release(IEnumCifComponents
*iface
)
807 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
808 LONG ref
= InterlockedDecrement(&This
->ref
);
810 TRACE("(%p) ref=%d\n", This
, ref
);
814 ICifFile_Release(This
->file
);
821 static HRESULT WINAPI
enum_components_Next(IEnumCifComponents
*iface
, ICifComponent
**component
)
823 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
824 struct cifcomponent
*comp
;
826 TRACE("(%p)->(%p)\n", This
, component
);
839 This
->position
= list_next(This
->start
, This
->position
);
846 comp
= CONTAINING_RECORD(This
->position
, struct cifcomponent
, entry
);
847 } while (This
->group_id
&& (!comp
->group
|| strcmp(This
->group_id
, comp
->group
)));
849 *component
= &comp
->ICifComponent_iface
;
853 static HRESULT WINAPI
enum_components_Reset(IEnumCifComponents
*iface
)
855 struct ciffenum_components
*This
= impl_from_IEnumCifComponents(iface
);
857 TRACE("(%p)\n", This
);
859 This
->position
= This
->start
;
863 static const IEnumCifComponentsVtbl enum_componentsVtbl
=
865 enum_components_QueryInterface
,
866 enum_components_AddRef
,
867 enum_components_Release
,
868 enum_components_Next
,
869 enum_components_Reset
,
872 static HRESULT
enum_components_create(ICifFile
*file
, struct list
*start
, char *group_id
, IEnumCifComponents
**iface
)
874 struct ciffenum_components
*enumerator
;
876 enumerator
= heap_zero_alloc(sizeof(*enumerator
));
877 if (!enumerator
) return E_OUTOFMEMORY
;
879 enumerator
->IEnumCifComponents_iface
.lpVtbl
= &enum_componentsVtbl
;
881 enumerator
->file
= file
;
882 enumerator
->start
= start
;
883 enumerator
->position
= start
;
884 enumerator
->group_id
= group_id
;
886 ICifFile_AddRef(file
);
888 *iface
= &enumerator
->IEnumCifComponents_iface
;
892 static HRESULT WINAPI
enum_groups_QueryInterface(IEnumCifGroups
*iface
, REFIID riid
, void **ppv
)
894 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
896 if (IsEqualGUID(&IID_IUnknown
, riid
))
898 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
899 *ppv
= &This
->IEnumCifGroups_iface
;
902 else if (IsEqualGUID(&IID_IEnumCifGroups, riid))
904 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv);
905 *ppv = &This->IEnumCifGroups_iface;
910 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
912 return E_NOINTERFACE
;
915 IUnknown_AddRef((IUnknown
*)*ppv
);
919 static ULONG WINAPI
enum_groups_AddRef(IEnumCifGroups
*iface
)
921 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
922 LONG ref
= InterlockedIncrement(&This
->ref
);
924 TRACE("(%p) ref=%d\n", This
, ref
);
929 static ULONG WINAPI
enum_groups_Release(IEnumCifGroups
*iface
)
931 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
932 LONG ref
= InterlockedDecrement(&This
->ref
);
934 TRACE("(%p) ref=%d\n", This
, ref
);
938 ICifFile_Release(This
->file
);
945 static HRESULT WINAPI
enum_groups_Next(IEnumCifGroups
*iface
, ICifGroup
**group
)
947 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
950 TRACE("(%p)->(%p)\n", This
, group
);
952 if (!This
->position
|| !group
)
955 This
->position
= list_next(This
->start
, This
->position
);
960 gp
= CONTAINING_RECORD(This
->position
, struct cifgroup
, entry
);
961 *group
= &gp
->ICifGroup_iface
;
965 static HRESULT WINAPI
enum_groups_Reset(IEnumCifGroups
*iface
)
967 struct ciffenum_groups
*This
= impl_from_IEnumCifGroups(iface
);
969 TRACE("(%p)\n", This
);
971 This
->position
= This
->start
;
975 static const IEnumCifGroupsVtbl enum_groupsVtbl
=
977 enum_groups_QueryInterface
,
984 static HRESULT
enum_groups_create(ICifFile
*file
, struct list
*start
, IEnumCifGroups
**iface
)
986 struct ciffenum_groups
*enumerator
;
988 enumerator
= heap_zero_alloc(sizeof(*enumerator
));
989 if (!enumerator
) return E_OUTOFMEMORY
;
991 enumerator
->IEnumCifGroups_iface
.lpVtbl
= &enum_groupsVtbl
;
993 enumerator
->file
= file
;
994 enumerator
->start
= start
;
995 enumerator
->position
= start
;
997 ICifFile_AddRef(file
);
999 *iface
= &enumerator
->IEnumCifGroups_iface
;
1003 static HRESULT WINAPI
ciffile_QueryInterface(ICifFile
*iface
, REFIID riid
, void **ppv
)
1005 struct ciffile
*This
= impl_from_ICiffile(iface
);
1007 if (IsEqualGUID(&IID_IUnknown
, riid
))
1009 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1010 *ppv
= &This
->ICifFile_iface
;
1012 else if (IsEqualGUID(&IID_ICifFile
, riid
))
1014 TRACE("(%p)->(IID_ICifFile %p)\n", This
, ppv
);
1015 *ppv
= &This
->ICifFile_iface
;
1019 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
1021 return E_NOINTERFACE
;
1024 IUnknown_AddRef((IUnknown
*)*ppv
);
1028 static ULONG WINAPI
ciffile_AddRef(ICifFile
*iface
)
1030 struct ciffile
*This
= impl_from_ICiffile(iface
);
1031 LONG ref
= InterlockedIncrement(&This
->ref
);
1033 TRACE("(%p) ref=%d\n", This
, ref
);
1038 static ULONG WINAPI
ciffile_Release(ICifFile
*iface
)
1040 struct ciffile
*This
= impl_from_ICiffile(iface
);
1041 LONG ref
= InterlockedDecrement(&This
->ref
);
1043 TRACE("(%p) ref=%d\n", This
, ref
);
1047 struct cifcomponent
*comp
, *comp_next
;
1048 struct cifgroup
*group
, *group_next
;
1050 heap_free(This
->name
);
1052 LIST_FOR_EACH_ENTRY_SAFE(comp
, comp_next
, &This
->components
, struct cifcomponent
, entry
)
1054 list_remove(&comp
->entry
);
1055 component_free(comp
);
1058 LIST_FOR_EACH_ENTRY_SAFE(group
, group_next
, &This
->groups
, struct cifgroup
, entry
)
1060 list_remove(&group
->entry
);
1070 static HRESULT WINAPI
ciffile_EnumComponents(ICifFile
*iface
, IEnumCifComponents
**enum_components
, DWORD filter
, void *pv
)
1072 struct ciffile
*This
= impl_from_ICiffile(iface
);
1074 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_components
, filter
, pv
);
1077 FIXME("filter (%x) not supported\n", filter
);
1079 FIXME("how to handle pv (%p)?\n", pv
);
1081 return enum_components_create(iface
, &This
->components
, NULL
, enum_components
);
1084 static HRESULT WINAPI
ciffile_FindComponent(ICifFile
*iface
, const char *id
, ICifComponent
**component
)
1086 struct ciffile
*This
= impl_from_ICiffile(iface
);
1087 struct cifcomponent
*comp
;
1089 TRACE("(%p)->(%s, %p)\n", This
, debugstr_a(id
), component
);
1091 LIST_FOR_EACH_ENTRY(comp
, &This
->components
, struct cifcomponent
, entry
)
1093 if (strcmp(comp
->id
, id
) != 0)
1096 *component
= &comp
->ICifComponent_iface
;
1103 static HRESULT WINAPI
ciffile_EnumGroups(ICifFile
*iface
, IEnumCifGroups
**enum_groups
, DWORD filter
, void *pv
)
1105 struct ciffile
*This
= impl_from_ICiffile(iface
);
1107 TRACE("(%p)->(%p, %u, %p)\n", This
, enum_groups
, filter
, pv
);
1110 FIXME("filter (%x) not supported\n", filter
);
1112 FIXME("how to handle pv (%p)?\n", pv
);
1114 return enum_groups_create(iface
, &This
->groups
, enum_groups
);
1117 static HRESULT WINAPI
ciffile_FindGroup(ICifFile
*iface
, const char *id
, ICifGroup
**group
)
1119 struct ciffile
*This
= impl_from_ICiffile(iface
);
1120 struct cifgroup
*gp
;
1122 TRACE("(%p)->(%s, %p)\n", This
, debugstr_a(id
), group
);
1124 LIST_FOR_EACH_ENTRY(gp
, &This
->groups
, struct cifgroup
, entry
)
1126 if (strcmp(gp
->id
, id
) != 0)
1129 *group
= &gp
->ICifGroup_iface
;
1136 static HRESULT WINAPI
ciffile_EnumModes(ICifFile
*iface
, IEnumCifModes
**cuf_modes
, DWORD filter
, void *pv
)
1138 struct ciffile
*This
= impl_from_ICiffile(iface
);
1140 FIXME("(%p)->(%p, %u, %p): stub\n", This
, cuf_modes
, filter
, pv
);
1145 static HRESULT WINAPI
ciffile_FindMode(ICifFile
*iface
, const char *id
, ICifMode
**mode
)
1147 struct ciffile
*This
= impl_from_ICiffile(iface
);
1149 FIXME("(%p)->(%s, %p): stub\n", This
, debugstr_a(id
), mode
);
1154 static HRESULT WINAPI
ciffile_GetDescription(ICifFile
*iface
, char *desc
, DWORD size
)
1156 struct ciffile
*This
= impl_from_ICiffile(iface
);
1158 TRACE("(%p)->(%p, %u)\n", This
, desc
, size
);
1160 return copy_substring_null(desc
, size
, This
->name
);
1163 static HRESULT WINAPI
ciffile_GetDetDlls(ICifFile
*iface
, char *dlls
, DWORD size
)
1165 struct ciffile
*This
= impl_from_ICiffile(iface
);
1167 FIXME("(%p)->(%p, %u): stub\n", This
, dlls
, size
);
1172 static const ICifFileVtbl ciffileVtbl
=
1174 ciffile_QueryInterface
,
1177 ciffile_EnumComponents
,
1178 ciffile_FindComponent
,
1183 ciffile_GetDescription
,
1187 static BOOL
copy_string(char **dest
, const char *source
)
1195 *dest
= strdupA(source
);
1196 if (!dest
) return FALSE
;
1200 static BOOL
section_get_str(struct inf_section
*inf_sec
, const char *key
, char **value
, const char *def
)
1202 struct inf_value
*inf_val
;
1204 inf_val
= inf_get_value(inf_sec
, key
);
1205 if (!inf_val
) return copy_string(value
, def
);
1207 *value
= inf_value_get_value(inf_val
);
1208 if (!*value
) return FALSE
;
1213 static char *next_part(char **str
, BOOL strip_quotes
)
1218 while (*next
&& *next
!= ',')
1223 *str
= trim(start
, NULL
, strip_quotes
);
1228 *str
= trim(start
, NULL
, strip_quotes
);
1232 static BOOL
value_get_str_field(struct inf_value
*inf_val
, int field
, char **value
, const char *def
)
1234 char *line
, *str
, *next
;
1237 line
= inf_value_get_value(inf_val
);
1238 if (!line
) return FALSE
;
1244 next
= next_part(&str
, TRUE
);
1248 BOOL ret
= copy_string(value
, str
);
1256 return copy_string(value
, def
);
1260 static BOOL section_get_str_field(struct inf_section *inf_sec, const char *key, int field, char **value, const char *def)
1262 struct inf_value *inf_val;
1264 inf_val = inf_get_value(inf_sec, key);
1265 if (!inf_val) return copy_string(value, def);
1267 return value_get_str_field(inf_val, field, value, def);
1271 static BOOL
section_get_dword(struct inf_section
*inf_sec
, const char *key
, DWORD
*value
, DWORD def
)
1273 struct inf_value
*inf_val
;
1276 inf_val
= inf_get_value(inf_sec
, key
);
1283 str
= inf_value_get_value(inf_val
);
1284 if (!str
) return FALSE
;
1292 static BOOL
value_get_dword_field(struct inf_value
*inf_val
, int field
, DWORD
*value
, DWORD def
)
1297 ret
= value_get_str_field(inf_val
, field
, &value_str
, NULL
);
1298 if (!ret
) return FALSE
;
1305 *value
= atoi(value_str
);
1306 heap_free(value_str
);
1311 static BOOL
section_get_dword_field(struct inf_section
*inf_sec
, const char *key
, int field
, DWORD
*value
, DWORD def
)
1313 struct inf_value
*inf_val
;
1315 inf_val
= inf_get_value(inf_sec
, key
);
1322 return value_get_dword_field(inf_val
, field
, value
, def
);
1325 static HRESULT
process_version(struct ciffile
*file
, struct inf_section
*section
)
1327 if (!section_get_str(section
, "DisplayName", &file
->name
, DEFAULT_INSTALLER_DESC
))
1328 return E_OUTOFMEMORY
;
1333 static BOOL
read_version_entry(struct inf_section
*section
, DWORD
*ret_ver
, DWORD
*ret_build
)
1337 char *line
, *str
, *next
;
1339 if (!section_get_str(section
, "Version", &line
, NULL
))
1341 if (!line
) goto done
;
1345 next
= next_part(&str
, TRUE
);
1346 version
|= atoi(str
) << 16;
1347 if (!next
) goto done
;
1350 next
= next_part(&str
, TRUE
);
1351 version
|= atoi(str
) & 0xffff;
1352 if (!next
) goto done
;
1355 next
= next_part(&str
, TRUE
);
1356 build
|= atoi(str
) << 16;
1357 if (!next
) goto done
;
1360 next_part(&str
, TRUE
);
1361 build
|= atoi(str
) & 0xffff;
1370 static BOOL
read_platform_entry(struct inf_section
*section
, DWORD
*ret_platform
)
1372 DWORD platform
= PLATFORM_ALL
;
1373 char *line
, *str
, *next
;
1375 if (!section_get_str(section
, "Platform", &line
, NULL
))
1377 if (!line
) goto done
;
1383 next
= next_part(&str
, TRUE
);
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
;
1400 FIXME("Unknown platform: %s\n", debugstr_a(str
));
1407 *ret_platform
= platform
;
1411 static BOOL
read_dependencies(struct cifcomponent
*component
, struct inf_section
*section
)
1413 struct dependency_info
*dependency
;
1414 char *line
, *str
, *next
;
1417 if (!section_get_str(section
, "Dependencies", &line
, NULL
))
1418 return E_OUTOFMEMORY
;
1419 if (!line
) goto done
;
1425 next
= next_part(&str
, TRUE
);
1427 dependency
= heap_zero_alloc(sizeof(*dependency
));
1428 if (!dependency
) goto done
;
1430 dependency
->id
= strdupA(str
);
1431 if (!dependency
->id
)
1433 heap_free(dependency
);
1437 dependency
->type
= strstr(dependency
->id
, ":");
1438 if (dependency
->type
) *dependency
->type
++ = 0;
1440 list_add_tail(&component
->dependencies
, &dependency
->entry
);
1452 static BOOL
read_urls(struct cifcomponent
*component
, struct inf_section
*section
)
1454 struct inf_value
*inf_value
= NULL
;
1455 struct url_info
*url_entry
;
1459 while (inf_section_next_value(section
, &inf_value
))
1461 str
= inf_value_get_key(inf_value
);
1462 if (!str
) return E_OUTOFMEMORY
;
1464 if (strncasecmp(str
, "URL", 3))
1470 index
= strtol(str
+3, &next
, 10);
1471 if (next
== str
+3 || *next
!= 0 || index
< 1)
1475 url_entry
= heap_zero_alloc(sizeof(*url_entry
));
1476 if (!url_entry
) goto error
;
1478 url_entry
->index
= index
;
1480 if (!value_get_str_field(inf_value
, 1, &url_entry
->url
, NULL
))
1482 if (!url_entry
->url
|| !*url_entry
->url
)
1484 url_entry_free(url_entry
);
1488 if (!value_get_dword_field(inf_value
, 2, &url_entry
->flags
, 0))
1491 list_add_tail(&component
->urls
, &url_entry
->entry
);
1501 url_entry_free(url_entry
);
1505 void add_component_by_priority(struct ciffile
*file
, struct cifcomponent
*component
)
1507 struct cifcomponent
*entry
;
1509 LIST_FOR_EACH_ENTRY(entry
, &file
->components
, struct cifcomponent
, entry
)
1511 if (entry
->priority
> component
->priority
)
1514 list_add_before(&entry
->entry
, &component
->entry
);
1518 list_add_tail(&file
->components
, &component
->entry
);
1521 static HRESULT
process_component(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1523 struct cifcomponent
*component
;
1524 HRESULT hr
= E_OUTOFMEMORY
;
1526 component
= heap_zero_alloc(sizeof(*component
));
1527 if (!component
) return E_OUTOFMEMORY
;
1529 component
->ICifComponent_iface
.lpVtbl
= &cifcomponentVtbl
;
1530 component
->parent
= &file
->ICifFile_iface
;
1532 list_init(&component
->urls
);
1533 list_init(&component
->dependencies
);
1535 component
->queue_state
= ActionNone
;
1537 component
->id
= strdupA(section_name
);
1538 if (!component
->id
) goto error
;
1540 if (!section_get_str(section
, "DisplayName", &component
->description
, NULL
))
1542 if (!section_get_str(section
, "GUID", &component
->guid
, NULL
))
1544 if (!section_get_str(section
, "Details", &component
->details
, NULL
))
1546 if (!section_get_str(section
, "Group", &component
->group
, NULL
))
1548 if (!section_get_str(section
, "Locale", &component
->locale
, "en"))
1550 if (!section_get_str(section
, "PatchID", &component
->patchid
, NULL
))
1553 if (!section_get_dword_field(section
, "Size", 1, &component
->size_download
, 0))
1555 if (!section_get_dword_field(section
, "Size", 2, &component
->size_extracted
, 0))
1557 if (!section_get_dword_field(section
, "InstalledSize", 1, &component
->size_app
, 0))
1559 if (!section_get_dword_field(section
, "InstalledSize", 2, &component
->size_win
, 0))
1562 if (!section_get_str(section
, "SuccessKey", &component
->key_success
, NULL
))
1564 if (!section_get_str(section
, "CancelKey", &component
->key_cancel
, NULL
))
1566 if (!section_get_str(section
, "ProgressKey", &component
->key_progress
, NULL
))
1568 if (!section_get_str(section
, "UninstallKey", &component
->key_uninstall
, NULL
))
1570 if (!section_get_dword(section
, "Reboot", &component
->reboot
, 0))
1572 if (!section_get_dword(section
, "AdminCheck", &component
->admin
, 0))
1574 if (!section_get_dword(section
, "UIVisible", &component
->visibleui
, 1))
1576 if (!section_get_dword(section
, "ActiveSetupAware", &component
->as_aware
, 0))
1578 if (!section_get_dword(section
, "Priority", &component
->priority
, 0))
1581 if (!read_version_entry(section
, &component
->version
, &component
->build
))
1583 if (!read_platform_entry(section
, &component
->platform
))
1585 if (!read_urls(component
, section
))
1587 if (!read_dependencies(component
, section
))
1590 component
->current_priority
= component
->priority
;
1592 add_component_by_priority(file
, component
);
1596 component_free(component
);
1600 static HRESULT
process_group(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1602 struct cifgroup
*group
;
1603 HRESULT hr
= E_OUTOFMEMORY
;
1605 group
= heap_zero_alloc(sizeof(*group
));
1606 if (!group
) return E_OUTOFMEMORY
;
1608 group
->ICifGroup_iface
.lpVtbl
= &cifgroupVtbl
;
1609 group
->parent
= &file
->ICifFile_iface
;
1611 group
->id
= strdupA(section_name
);
1612 if (!group
->id
) goto error
;
1614 if (!section_get_str(section
, "DisplayName", &group
->description
, NULL
))
1616 if (!section_get_dword(section
, "Priority", &group
->priority
, 0))
1619 list_add_head(&file
->groups
, &group
->entry
);
1627 static HRESULT
process_section(struct ciffile
*file
, struct inf_section
*section
, const char *section_name
)
1632 if (!section_get_str(section
, "SectionType", &type
, "Component"))
1633 return E_OUTOFMEMORY
;
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
);
1640 FIXME("Don't know how to process %s\n", debugstr_a(type
));
1646 static HRESULT
process_inf(struct ciffile
*file
, struct inf_file
*inf
)
1648 struct inf_section
*section
= NULL
;
1652 while (SUCCEEDED(hr
) && inf_next_section(inf
, §ion
))
1654 section_name
= inf_section_get_name(section
);
1655 if (!section_name
) return E_OUTOFMEMORY
;
1657 TRACE("start processing section %s\n", debugstr_a(section_name
));
1659 if (!strcasecmp(section_name
, "Strings") ||
1660 !strncasecmp(section_name
, "Strings.", strlen("Strings.")))
1662 /* Ignore string sections */
1664 else if (strcasecmp(section_name
, "Version") == 0)
1665 hr
= process_version(file
, section
);
1667 hr
= process_section(file
, section
, section_name
);
1669 TRACE("finished processing section %s (%x)\n", debugstr_a(section_name
), hr
);
1670 heap_free(section_name
);
1673 /* In case there was no version section, set the default installer description */
1674 if (SUCCEEDED(hr
) && !file
->name
)
1676 file
->name
= strdupA(DEFAULT_INSTALLER_DESC
);
1677 if (!file
->name
) hr
= E_OUTOFMEMORY
;
1683 static HRESULT
load_ciffile(const char *path
, ICifFile
**icif
)
1685 struct inf_file
*inf
= NULL
;
1686 struct ciffile
*file
;
1687 HRESULT hr
= E_FAIL
;
1689 file
= heap_zero_alloc(sizeof(*file
));
1690 if(!file
) return E_OUTOFMEMORY
;
1692 file
->ICifFile_iface
.lpVtbl
= &ciffileVtbl
;
1695 list_init(&file
->components
);
1696 list_init(&file
->groups
);
1698 hr
= inf_load(path
, &inf
);
1699 if (FAILED(hr
)) goto error
;
1701 hr
= process_inf(file
, inf
);
1702 if (FAILED(hr
)) goto error
;
1704 *icif
= &file
->ICifFile_iface
;
1708 if (inf
) inf_free(inf
);
1709 ICifFile_Release(&file
->ICifFile_iface
);
1713 HRESULT WINAPI
GetICifFileFromFile(ICifFile
**icif
, const char *path
)
1715 TRACE("(%p, %s)\n", icif
, debugstr_a(path
));
1717 return load_ciffile(path
, icif
);
1721 HRESULT WINAPI
GetICifRWFileFromFile(ICifRWFile
**icif
, const char *path
)
1723 FIXME("(%p, %s): stub\n", icif
, debugstr_a(path
));