2 * INSENG Implementation
4 * Copyright 2006 Mike McCormack
5 * Copyright 2016 Michael Müller
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
41 #include "inseng_private.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(inseng
);
47 static HINSTANCE instance
;
59 IEnumCifComponents
*enum_comp
;
65 ULONGLONG download_start
;
68 struct InstallEngine
{
69 IInstallEngine2 IInstallEngine2_iface
;
70 IInstallEngineTiming IInstallEngineTiming_iface
;
73 IInstallEngineCallback
*callback
;
79 /* used for the installation thread */
80 struct thread_info thread
;
85 IBindStatusCallback IBindStatusCallback_iface
;
97 InstallEngine
*engine
;
102 static inline InstallEngine
*impl_from_IInstallEngine2(IInstallEngine2
*iface
)
104 return CONTAINING_RECORD(iface
, InstallEngine
, IInstallEngine2_iface
);
107 static inline struct downloadcb
*impl_from_IBindStatusCallback(IBindStatusCallback
*iface
)
109 return CONTAINING_RECORD(iface
, struct downloadcb
, IBindStatusCallback_iface
);
112 static inline InstallEngine
*impl_from_IInstallEngineTiming(IInstallEngineTiming
*iface
)
114 return CONTAINING_RECORD(iface
, InstallEngine
, IInstallEngineTiming_iface
);
117 static HRESULT WINAPI
downloadcb_QueryInterface(IBindStatusCallback
*iface
, REFIID riid
, void **ppv
)
119 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
121 if (IsEqualGUID(&IID_IUnknown
, riid
))
123 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
124 *ppv
= &This
->IBindStatusCallback_iface
;
126 else if (IsEqualGUID(&IID_IBindStatusCallback
, riid
))
128 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This
, ppv
);
129 *ppv
= &This
->IBindStatusCallback_iface
;
133 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
135 return E_NOINTERFACE
;
138 IUnknown_AddRef((IUnknown
*)*ppv
);
142 static ULONG WINAPI
downloadcb_AddRef(IBindStatusCallback
*iface
)
144 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
145 LONG ref
= InterlockedIncrement(&This
->ref
);
147 TRACE("(%p) ref = %d\n", This
, ref
);
152 static ULONG WINAPI
downloadcb_Release(IBindStatusCallback
*iface
)
154 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
155 LONG ref
= InterlockedDecrement(&This
->ref
);
157 TRACE("(%p) ref = %d\n", This
, ref
);
161 heap_free(This
->file_name
);
162 heap_free(This
->cache_file
);
164 IInstallEngine2_Release(&This
->engine
->IInstallEngine2_iface
);
171 static HRESULT WINAPI
downloadcb_OnStartBinding(IBindStatusCallback
*iface
, DWORD reserved
, IBinding
*pbind
)
173 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
175 TRACE("(%p)->(%u %p)\n", This
, reserved
, pbind
);
180 static HRESULT WINAPI
downloadcb_GetPriority(IBindStatusCallback
*iface
, LONG
*priority
)
182 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
184 FIXME("(%p)->(%p): stub\n", This
, priority
);
189 static HRESULT WINAPI
downloadcb_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
191 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
193 FIXME("(%p)->(%u): stub\n", This
, reserved
);
198 static HRESULT WINAPI
downloadcb_OnProgress(IBindStatusCallback
*iface
, ULONG progress
,
199 ULONG progress_max
, ULONG status
, const WCHAR
*status_text
)
201 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
204 TRACE("%p)->(%u %u %u %s)\n", This
, progress
, progress_max
, status
, debugstr_w(status_text
));
208 case BINDSTATUS_BEGINDOWNLOADDATA
:
209 if (!This
->engine
->thread
.download_start
)
210 This
->engine
->thread
.download_start
= GetTickCount64();
212 case BINDSTATUS_DOWNLOADINGDATA
:
213 case BINDSTATUS_ENDDOWNLOADDATA
:
214 This
->engine
->thread
.downloaded_kb
= This
->dl_previous_kb
+ progress
/ 1024;
215 if (This
->engine
->callback
)
217 hr
= IInstallEngineCallback_OnComponentProgress(This
->engine
->callback
,
218 This
->id
, INSTALLSTATUS_DOWNLOADING
, This
->display
, NULL
, progress
/ 1024, This
->dl_size
);
222 case BINDSTATUS_CACHEFILENAMEAVAILABLE
:
223 This
->cache_file
= strdupW(status_text
);
224 if (!This
->cache_file
)
226 ERR("Failed to allocate memory for cache file\n");
231 case BINDSTATUS_CONNECTING
:
232 case BINDSTATUS_SENDINGREQUEST
:
233 case BINDSTATUS_MIMETYPEAVAILABLE
:
234 case BINDSTATUS_FINDINGRESOURCE
:
238 FIXME("Unsupported status %u\n", status
);
244 static HRESULT WINAPI
downloadcb_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
246 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
248 TRACE("(%p)->(%08x %s)\n", This
, hresult
, debugstr_w(szError
));
256 if (!This
->cache_file
)
262 if (CopyFileW(This
->cache_file
, This
->file_name
, FALSE
))
266 ERR("CopyFile failed: %u\n", GetLastError());
271 SetEvent(This
->event_done
);
275 static HRESULT WINAPI
downloadcb_GetBindInfo(IBindStatusCallback
*iface
,
276 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
278 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
280 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
282 *grfBINDF
= BINDF_PULLDATA
| BINDF_NEEDFILE
;
286 static HRESULT WINAPI
downloadcb_OnDataAvailable(IBindStatusCallback
*iface
,
287 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
289 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
291 TRACE("(%p)->(%08x %u %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
296 static HRESULT WINAPI
downloadcb_OnObjectAvailable(IBindStatusCallback
*iface
,
297 REFIID riid
, IUnknown
*punk
)
299 struct downloadcb
*This
= impl_from_IBindStatusCallback(iface
);
301 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
306 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
=
308 downloadcb_QueryInterface
,
311 downloadcb_OnStartBinding
,
312 downloadcb_GetPriority
,
313 downloadcb_OnLowResource
,
314 downloadcb_OnProgress
,
315 downloadcb_OnStopBinding
,
316 downloadcb_GetBindInfo
,
317 downloadcb_OnDataAvailable
,
318 downloadcb_OnObjectAvailable
321 static HRESULT
downloadcb_create(InstallEngine
*engine
, HANDLE event
, char *file_name
, char *id
,
322 char *display
, DWORD dl_size
, struct downloadcb
**callback
)
324 struct downloadcb
*cb
;
326 cb
= heap_alloc_zero(sizeof(*cb
));
327 if (!cb
) return E_OUTOFMEMORY
;
329 cb
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
333 cb
->display
= display
;
335 cb
->dl_size
= dl_size
;
336 cb
->dl_previous_kb
= engine
->thread
.downloaded_kb
;
337 cb
->event_done
= event
;
338 cb
->file_name
= strAtoW(file_name
);
342 return E_OUTOFMEMORY
;
345 IInstallEngine2_AddRef(&engine
->IInstallEngine2_iface
);
351 static HRESULT WINAPI
InstallEngine_QueryInterface(IInstallEngine2
*iface
, REFIID riid
, void **ppv
)
353 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
355 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
356 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
357 *ppv
= &This
->IInstallEngine2_iface
;
358 }else if(IsEqualGUID(&IID_IInstallEngine
, riid
)) {
359 TRACE("(%p)->(IID_IInstallEngine %p)\n", This
, ppv
);
360 *ppv
= &This
->IInstallEngine2_iface
;
361 }else if(IsEqualGUID(&IID_IInstallEngine2
, riid
)) {
362 TRACE("(%p)->(IID_IInstallEngine2 %p)\n", This
, ppv
);
363 *ppv
= &This
->IInstallEngine2_iface
;
364 }else if(IsEqualGUID(&IID_IInstallEngineTiming
, riid
)) {
365 TRACE("(%p)->(IID_IInstallEngineTiming %p)\n", This
, ppv
);
366 *ppv
= &This
->IInstallEngineTiming_iface
;
368 FIXME("(%p)->(%s %p) not found\n", This
, debugstr_guid(riid
), ppv
);
370 return E_NOINTERFACE
;
373 IUnknown_AddRef((IUnknown
*)*ppv
);
377 static ULONG WINAPI
InstallEngine_AddRef(IInstallEngine2
*iface
)
379 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
380 LONG ref
= InterlockedIncrement(&This
->ref
);
382 TRACE("(%p) ref=%d\n", This
, ref
);
387 static ULONG WINAPI
InstallEngine_Release(IInstallEngine2
*iface
)
389 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
390 LONG ref
= InterlockedDecrement(&This
->ref
);
392 TRACE("(%p) ref=%d\n", This
, ref
);
397 ICifFile_Release(This
->icif
);
399 heap_free(This
->baseurl
);
400 heap_free(This
->downloaddir
);
407 static void set_status(InstallEngine
*This
, DWORD status
)
409 This
->status
= status
;
412 IInstallEngineCallback_OnEngineStatusChange(This
->callback
, status
, 0);
415 static HRESULT
calc_sizes(IEnumCifComponents
*enum_comp
, DWORD operation
, DWORD
*size_download
, DWORD
*size_install
)
422 /* FIXME: what about inactive dependencies and how does
423 * INSTALLOPTIONS_FORCEDEPENDENCIES play into this ?*/
425 hr
= IEnumCifComponents_Reset(enum_comp
);
426 if (FAILED(hr
)) return hr
;
428 while (SUCCEEDED(IEnumCifComponents_Next(enum_comp
, &comp
)))
430 if (ICifComponent_GetInstallQueueState(comp
) != ActionInstall
)
433 /* FIXME: handle install options and find out the default options*/
434 if (operation
== OP_DOWNLOAD
&& ICifComponent_IsComponentDownloaded(comp
) == S_FALSE
)
435 download
= ICifComponent_GetDownloadSize(comp
);
437 if (operation == OP_INSTALL && ICifComponent_IsComponentInstalled(comp) == S_FALSE)
438 install = ICifComponent_GetInstalledSize(comp);
442 *size_download
= download
;
443 *size_install
= install
;
448 static HRESULT
get_next_component(IEnumCifComponents
*enum_comp
, DWORD operation
, ICifComponent
**ret_comp
)
453 hr
= IEnumCifComponents_Reset(enum_comp
);
454 if (FAILED(hr
)) return hr
;
456 while (SUCCEEDED(IEnumCifComponents_Next(enum_comp
, &comp
)))
458 if (ICifComponent_GetInstallQueueState(comp
) != ActionInstall
)
461 /* FIXME: handle install options and find out the default options*/
462 if (operation
== OP_DOWNLOAD
&& ICifComponent_IsComponentDownloaded(comp
) != S_FALSE
)
464 if (operation
== OP_INSTALL
&& ICifComponent_IsComponentInstalled(comp
) != S_FALSE
)
474 static HRESULT
get_url(ICifComponent
*comp
, int index
, char **url
, DWORD
*flags
)
476 char *url_temp
= NULL
;
477 int size
= MAX_PATH
/ 2;
480 /* FIXME: should we add an internal get function to prevent this ugly code ? */
482 /* check if there is an url with such an index */
483 hr
= ICifComponent_GetUrl(comp
, index
, NULL
, 0, flags
);
495 url_temp
= heap_alloc(size
);
496 if (!url_temp
) return E_OUTOFMEMORY
;
498 hr
= ICifComponent_GetUrl(comp
, index
, url_temp
, size
, flags
);
505 while (strlen(url_temp
) == size
-1);
511 static char *combine_url(char *baseurl
, char *url
)
513 int len_base
= strlen(baseurl
);
514 int len_url
= strlen(url
);
517 combined
= heap_alloc(len_base
+ len_url
+ 2);
518 if (!combined
) return NULL
;
520 strcpy(combined
, baseurl
);
521 if (len_base
&& combined
[len_base
-1] != '/')
522 strcat(combined
, "/");
523 strcat(combined
, url
);
528 static HRESULT
generate_moniker(char *baseurl
, char *url
, DWORD flags
, IMoniker
**moniker
)
533 if (flags
& URLF_RELATIVEURL
)
539 combined
= combine_url(baseurl
, url
);
540 if (!combined
) return E_OUTOFMEMORY
;
542 urlW
= strAtoW(combined
);
544 if (!urlW
) return E_OUTOFMEMORY
;
549 if (!urlW
) return E_OUTOFMEMORY
;
552 hr
= CreateURLMoniker(NULL
, urlW
, moniker
);
557 static char *merge_path(char *path1
, char *path2
)
559 int len
= strlen(path1
) + strlen(path2
) + 2;
560 char *combined
= heap_alloc(len
);
562 if (!combined
) return NULL
;
563 strcpy(combined
, path1
);
564 strcat(combined
, "\\");
565 strcat(combined
, path2
);
570 static HRESULT
download_url(InstallEngine
*This
, char *id
, char *display
, char *url
, DWORD flags
, DWORD dl_size
)
572 struct downloadcb
*callback
= NULL
;
573 char *filename
= NULL
;
574 IUnknown
*unk
= NULL
;
575 IMoniker
*mon
= NULL
;
576 IBindCtx
*bindctx
= NULL
;
580 if (!This
->downloaddir
)
582 WARN("No download directory set\n");
586 hr
= generate_moniker(This
->baseurl
, url
, flags
, &mon
);
589 FIXME("Failed to create moniker\n");
593 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
596 IMoniker_Release(mon
);
600 filename
= strrchr(url
, '/');
601 if (!filename
) filename
= url
;
603 filename
= merge_path(This
->downloaddir
, filename
);
610 hr
= downloadcb_create(This
, event
, filename
, id
, display
, dl_size
, &callback
);
611 if (FAILED(hr
)) goto error
;
613 hr
= CreateAsyncBindCtx(0, &callback
->IBindStatusCallback_iface
, NULL
, &bindctx
);
614 if(FAILED(hr
)) goto error
;
616 hr
= IMoniker_BindToStorage(mon
, bindctx
, NULL
, &IID_IUnknown
, (void**)&unk
);
617 if (FAILED(hr
)) goto error
;
618 if (unk
) IUnknown_Release(unk
);
621 IMoniker_Release(mon
);
622 IBindCtx_Release(bindctx
);
624 WaitForSingleObject(event
, INFINITE
);
628 IBindStatusCallback_Release(&callback
->IBindStatusCallback_iface
);
632 if (mon
) IMoniker_Release(mon
);
633 if (event
) CloseHandle(event
);
634 if (callback
) IBindStatusCallback_Release(&callback
->IBindStatusCallback_iface
);
635 if (bindctx
) IBindCtx_Release(bindctx
);
636 if (filename
) heap_free(filename
);
640 static HRESULT
process_component_dependencies(InstallEngine
*This
, ICifComponent
*comp
)
642 char id
[MAX_ID_LENGTH
+1], type
;
649 hr
= ICifComponent_GetDependency(comp
, i
, id
, sizeof(id
), &type
, &ver
, &build
);
651 FIXME("Can't handle dependencies yet: %s\n", debugstr_a(id
));
659 static HRESULT
process_component(InstallEngine
*This
, ICifComponent
*comp
)
661 DWORD size_dl
, size_install
, phase
;
662 char display
[MAX_DISPLAYNAME_LENGTH
+1];
663 char id
[MAX_ID_LENGTH
+1];
667 hr
= ICifComponent_GetID(comp
, id
, sizeof(id
));
668 if (FAILED(hr
)) return hr
;
670 TRACE("processing component %s\n", debugstr_a(id
));
672 hr
= ICifComponent_GetDescription(comp
, display
, sizeof(display
));
673 if (FAILED(hr
)) return hr
;
675 size_dl
= (This
->thread
.operation
== OP_DOWNLOAD
) ? ICifComponent_GetDownloadSize(comp
) : 0;
676 size_install
= 0; /* (This->thread.operation == OP_INSTALL) ? ICifComponent_GetInstalledSize(comp) : 0; */
680 IInstallEngineCallback_OnStartComponent(This
->callback
, id
, size_dl
, size_install
, display
);
681 IInstallEngineCallback_OnComponentProgress(This
->callback
, id
, INSTALLSTATUS_INITIALIZING
, display
, NULL
, 0, 0);
682 phase
= INSTALLSTATUS_INITIALIZING
;
685 hr
= process_component_dependencies(This
, comp
);
686 if (FAILED(hr
)) return hr
;
688 if (This
->thread
.operation
== OP_DOWNLOAD
)
695 phase
= INSTALLSTATUS_DOWNLOADING
;
697 hr
= get_url(comp
, i
, &url
, &flags
);
698 if (FAILED(hr
)) goto done
;
701 TRACE("processing url %s\n", debugstr_a(url
));
703 hr
= download_url(This
, id
, display
, url
, flags
, size_dl
);
710 IInstallEngineCallback_OnEngineProblem(This
->callback
, ENGINEPROBLEM_DOWNLOADFAIL
, &retry
);
711 if (!retry
) goto done
;
717 phase
= INSTALLSTATUS_CHECKINGTRUST
;
718 /* FIXME: check trust */
719 IInstallEngineCallback_OnComponentProgress(This
->callback
, id
, INSTALLSTATUS_CHECKINGTRUST
, display
, NULL
, 0, 0);
722 component_set_downloaded(comp
, TRUE
);
723 phase
= INSTALLSTATUS_DOWNLOADFINISHED
;
726 FIXME("Installation not yet implemented\n");
729 IInstallEngineCallback_OnStopComponent(This
->callback
, id
, hr
, phase
, display
, 0);
733 DWORD WINAPI
thread_installation(LPVOID param
)
735 InstallEngine
*This
= param
;
740 IInstallEngineCallback_OnStartInstall(This
->callback
, This
->thread
.download_size
, This
->thread
.install_size
);
744 hr
= get_next_component(This
->thread
.enum_comp
, This
->thread
.operation
, &comp
);
745 if (FAILED(hr
)) break;
752 hr
= process_component(This
, comp
);
753 if (FAILED(hr
)) break;
757 IInstallEngineCallback_OnStopInstall(This
->callback
, hr
, NULL
, 0);
759 IEnumCifComponents_Release(This
->thread
.enum_comp
);
760 IInstallEngine2_Release(&This
->IInstallEngine2_iface
);
762 set_status(This
, ENGINESTATUS_READY
);
766 static HRESULT
start_installation(InstallEngine
*This
, DWORD operation
, DWORD jobflags
)
771 This
->thread
.operation
= operation
;
772 This
->thread
.jobflags
= jobflags
;
773 This
->thread
.downloaded_kb
= 0;
774 This
->thread
.download_start
= 0;
776 /* Windows sends the OnStartInstall event from a different thread,
777 * but OnStartInstall already contains the required download and install size.
778 * The only way to signal an error from the thread is to send an OnStopComponent /
779 * OnStopInstall signal which can only occur after OnStartInstall. We need to
780 * precompute the sizes here to be able inform the application about errors while
781 * calculating the required sizes. */
783 hr
= ICifFile_EnumComponents(This
->icif
, &This
->thread
.enum_comp
, 0, NULL
);
784 if (FAILED(hr
)) return hr
;
786 hr
= calc_sizes(This
->thread
.enum_comp
, operation
, &This
->thread
.download_size
, &This
->thread
.install_size
);
787 if (FAILED(hr
)) goto error
;
789 IInstallEngine2_AddRef(&This
->IInstallEngine2_iface
);
791 thread
= CreateThread(NULL
, 0, thread_installation
, This
, 0, NULL
);
794 IInstallEngine2_Release(&This
->IInstallEngine2_iface
);
803 IEnumCifComponents_Release(This
->thread
.enum_comp
);
807 static HRESULT WINAPI
InstallEngine_GetEngineStatus(IInstallEngine2
*iface
, DWORD
*status
)
809 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
811 TRACE("(%p)->(%p)\n", This
, status
);
816 *status
= This
->status
;
820 static HRESULT WINAPI
InstallEngine_SetCifFile(IInstallEngine2
*iface
, const char *cab_name
, const char *cif_name
)
822 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
824 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_a(cab_name
), debugstr_a(cif_name
));
829 static HRESULT WINAPI
InstallEngine_DownloadComponents(IInstallEngine2
*iface
, DWORD flags
)
831 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
833 TRACE("(%p)->(%x)\n", This
, flags
);
835 /* The interface is not really threadsafe on windows, but we can at least prevent multiple installations */
836 if (InterlockedCompareExchange((LONG
*)&This
->status
, ENGINESTATUS_INSTALLING
, ENGINESTATUS_READY
) != ENGINESTATUS_READY
)
840 IInstallEngineCallback_OnEngineStatusChange(This
->callback
, ENGINESTATUS_INSTALLING
, 0);
842 return start_installation(This
, OP_DOWNLOAD
, flags
);
845 static HRESULT WINAPI
InstallEngine_InstallComponents(IInstallEngine2
*iface
, DWORD flags
)
847 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
849 FIXME("(%p)->(%x): stub\n", This
, flags
);
854 static HRESULT WINAPI
InstallEngine_EnumInstallIDs(IInstallEngine2
*iface
, UINT index
, char **id
)
856 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
858 FIXME("(%p)->(%u %p): stub\n", This
, index
, id
);
863 static HRESULT WINAPI
InstallEngine_EnumDownloadIDs(IInstallEngine2
*iface
, UINT index
, char **id
)
865 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
866 IEnumCifComponents
*enum_components
;
870 TRACE("(%p)->(%u %p)\n", This
, index
, id
);
872 if (!This
->icif
|| !id
)
875 hr
= ICifFile_EnumComponents(This
->icif
, &enum_components
, 0, NULL
);
876 if (FAILED(hr
)) return hr
;
880 hr
= IEnumCifComponents_Next(enum_components
, &comp
);
881 if (FAILED(hr
)) goto done
;
883 if (ICifComponent_GetInstallQueueState(comp
) != ActionInstall
)
886 if (ICifComponent_IsComponentDownloaded(comp
) != S_FALSE
)
891 char *id_src
= component_get_id(comp
);
892 *id
= CoTaskMemAlloc(strlen(id_src
) + 1);
905 IEnumCifComponents_Release(enum_components
);
909 static HRESULT WINAPI
InstallEngine_IsComponentInstalled(IInstallEngine2
*iface
, const char *id
, DWORD
*status
)
911 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
913 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_a(id
), status
);
918 static HRESULT WINAPI
InstallEngine_RegisterInstallEngineCallback(IInstallEngine2
*iface
, IInstallEngineCallback
*callback
)
920 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
922 TRACE("(%p)->(%p)\n", This
, callback
);
924 This
->callback
= callback
;
928 static HRESULT WINAPI
InstallEngine_UnregisterInstallEngineCallback(IInstallEngine2
*iface
)
930 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
932 TRACE("(%p)\n", This
);
934 This
->callback
= NULL
;
938 static HRESULT WINAPI
InstallEngine_SetAction(IInstallEngine2
*iface
, const char *id
, DWORD action
, DWORD priority
)
940 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
944 TRACE("(%p)->(%s %u %u)\n", This
, debugstr_a(id
), action
, priority
);
947 return E_FAIL
; /* FIXME: check error code */
949 hr
= ICifFile_FindComponent(This
->icif
, id
, &comp
);
950 if (FAILED(hr
)) return hr
;
952 hr
= ICifComponent_SetInstallQueueState(comp
, action
);
953 if (FAILED(hr
)) return hr
;
955 hr
= ICifComponent_SetCurrentPriority(comp
, priority
);
959 static HRESULT WINAPI
InstallEngine_GetSizes(IInstallEngine2
*iface
, const char *id
, COMPONENT_SIZES
*sizes
)
961 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
963 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_a(id
), sizes
);
968 static HRESULT WINAPI
InstallEngine_LaunchExtraCommand(IInstallEngine2
*iface
, const char *inf_name
, const char *section
)
970 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
972 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_a(inf_name
), debugstr_a(section
));
977 static HRESULT WINAPI
InstallEngine_GetDisplayName(IInstallEngine2
*iface
, const char *id
, const char *name
)
979 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
981 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_a(id
), debugstr_a(name
));
986 static HRESULT WINAPI
InstallEngine_SetBaseUrl(IInstallEngine2
*iface
, const char *base_name
)
988 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
990 TRACE("(%p)->(%s)\n", This
, debugstr_a(base_name
));
993 heap_free(This
->baseurl
);
995 This
->baseurl
= strdupA(base_name
);
996 return This
->baseurl
? S_OK
: E_OUTOFMEMORY
;
999 static HRESULT WINAPI
InstallEngine_SetDownloadDir(IInstallEngine2
*iface
, const char *download_dir
)
1001 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1003 TRACE("(%p)->(%s)\n", This
, debugstr_a(download_dir
));
1005 if (This
->downloaddir
)
1006 heap_free(This
->downloaddir
);
1008 This
->downloaddir
= strdupA(download_dir
);
1009 return This
->downloaddir
? S_OK
: E_OUTOFMEMORY
;
1012 static HRESULT WINAPI
InstallEngine_SetInstallDrive(IInstallEngine2
*iface
, char drive
)
1014 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1016 FIXME("(%p)->(%c): stub\n", This
, drive
);
1021 static HRESULT WINAPI
InstallEngine_SetInstallOptions(IInstallEngine2
*iface
, DWORD flags
)
1023 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1025 FIXME("(%p)->(%x): stub\n", This
, flags
);
1030 static HRESULT WINAPI
InstallEngine_SetHWND(IInstallEngine2
*iface
, HWND hwnd
)
1032 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1034 FIXME("(%p)->(%p): stub\n", This
, hwnd
);
1039 static HRESULT WINAPI
InstallEngine_SetIStream(IInstallEngine2
*iface
, IStream
*stream
)
1041 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1043 FIXME("(%p)->(%p): stub\n", This
, stream
);
1048 static HRESULT WINAPI
InstallEngine_Abort(IInstallEngine2
*iface
, DWORD flags
)
1050 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1052 FIXME("(%p)->(%x): stub\n", This
, flags
);
1057 static HRESULT WINAPI
InstallEngine_Suspend(IInstallEngine2
*iface
)
1059 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1061 FIXME("(%p): stub\n", This
);
1066 static HRESULT WINAPI
InstallEngine_Resume(IInstallEngine2
*iface
)
1068 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1070 FIXME("(%p): stub\n", This
);
1075 static HRESULT WINAPI
InstallEngine2_SetLocalCif(IInstallEngine2
*iface
, const char *cif
)
1077 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1080 TRACE("(%p)->(%s)\n", This
, debugstr_a(cif
));
1083 ICifFile_Release(This
->icif
);
1085 set_status(This
, ENGINESTATUS_LOADING
);
1087 hr
= GetICifFileFromFile(&This
->icif
, cif
);
1089 set_status(This
, ENGINESTATUS_READY
);
1093 set_status(This
, ENGINESTATUS_NOTREADY
);
1098 static HRESULT WINAPI
InstallEngine2_GetICifFile(IInstallEngine2
*iface
, ICifFile
**cif_file
)
1100 InstallEngine
*This
= impl_from_IInstallEngine2(iface
);
1102 TRACE("(%p)->(%p)\n", This
, cif_file
);
1104 if (!This
->icif
|| !cif_file
)
1107 ICifFile_AddRef(This
->icif
);
1108 *cif_file
= This
->icif
;
1112 static const IInstallEngine2Vtbl InstallEngine2Vtbl
=
1114 InstallEngine_QueryInterface
,
1115 InstallEngine_AddRef
,
1116 InstallEngine_Release
,
1117 InstallEngine_GetEngineStatus
,
1118 InstallEngine_SetCifFile
,
1119 InstallEngine_DownloadComponents
,
1120 InstallEngine_InstallComponents
,
1121 InstallEngine_EnumInstallIDs
,
1122 InstallEngine_EnumDownloadIDs
,
1123 InstallEngine_IsComponentInstalled
,
1124 InstallEngine_RegisterInstallEngineCallback
,
1125 InstallEngine_UnregisterInstallEngineCallback
,
1126 InstallEngine_SetAction
,
1127 InstallEngine_GetSizes
,
1128 InstallEngine_LaunchExtraCommand
,
1129 InstallEngine_GetDisplayName
,
1130 InstallEngine_SetBaseUrl
,
1131 InstallEngine_SetDownloadDir
,
1132 InstallEngine_SetInstallDrive
,
1133 InstallEngine_SetInstallOptions
,
1134 InstallEngine_SetHWND
,
1135 InstallEngine_SetIStream
,
1136 InstallEngine_Abort
,
1137 InstallEngine_Suspend
,
1138 InstallEngine_Resume
,
1139 InstallEngine2_SetLocalCif
,
1140 InstallEngine2_GetICifFile
1143 static HRESULT WINAPI
InstallEngineTiming_QueryInterface(IInstallEngineTiming
*iface
, REFIID riid
, void **ppv
)
1145 InstallEngine
*This
= impl_from_IInstallEngineTiming(iface
);
1146 return IInstallEngine2_QueryInterface(&This
->IInstallEngine2_iface
, riid
, ppv
);
1149 static ULONG WINAPI
InstallEngineTiming_AddRef(IInstallEngineTiming
*iface
)
1151 InstallEngine
*This
= impl_from_IInstallEngineTiming(iface
);
1152 return IInstallEngine2_AddRef(&This
->IInstallEngine2_iface
);
1155 static ULONG WINAPI
InstallEngineTiming_Release(IInstallEngineTiming
*iface
)
1157 InstallEngine
*This
= impl_from_IInstallEngineTiming(iface
);
1158 return IInstallEngine2_Release(&This
->IInstallEngine2_iface
);
1161 static HRESULT WINAPI
InstallEngineTiming_GetRates(IInstallEngineTiming
*iface
, DWORD
*download
, DWORD
*install
)
1163 InstallEngine
*This
= impl_from_IInstallEngineTiming(iface
);
1165 FIXME("(%p)->(%p, %p): stub\n", This
, download
, install
);
1173 static HRESULT WINAPI
InstallEngineTiming_GetInstallProgress(IInstallEngineTiming
*iface
, INSTALLPROGRESS
*progress
)
1175 InstallEngine
*This
= impl_from_IInstallEngineTiming(iface
);
1180 FIXME("(%p)->(%p): semi-stub\n", This
, progress
);
1182 TRACE("(%p)->(%p): semi-stub\n", This
, progress
);
1184 progress
->dwDownloadKBRemaining
= max(This
->thread
.download_size
, This
->thread
.downloaded_kb
) - This
->thread
.downloaded_kb
;
1186 elapsed
= GetTickCount64() - This
->thread
.download_start
;
1187 if (This
->thread
.download_start
&& This
->thread
.downloaded_kb
&& elapsed
> 100)
1188 progress
->dwDownloadSecsRemaining
= (progress
->dwDownloadKBRemaining
* elapsed
) / (This
->thread
.downloaded_kb
* 1000);
1190 progress
->dwDownloadSecsRemaining
= -1;
1192 progress
->dwInstallKBRemaining
= 0;
1193 progress
->dwInstallSecsRemaining
= -1;
1198 static const IInstallEngineTimingVtbl InstallEngineTimingVtbl
=
1200 InstallEngineTiming_QueryInterface
,
1201 InstallEngineTiming_AddRef
,
1202 InstallEngineTiming_Release
,
1203 InstallEngineTiming_GetRates
,
1204 InstallEngineTiming_GetInstallProgress
,
1207 static HRESULT WINAPI
ClassFactory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppv
)
1211 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
1212 TRACE("(%p)->(IID_IUnknown %p)\n", iface
, ppv
);
1214 }else if(IsEqualGUID(&IID_IClassFactory
, riid
)) {
1215 TRACE("(%p)->(IID_IClassFactory %p)\n", iface
, ppv
);
1220 IUnknown_AddRef((IUnknown
*)*ppv
);
1224 FIXME("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppv
);
1225 return E_NOINTERFACE
;
1228 static ULONG WINAPI
ClassFactory_AddRef(IClassFactory
*iface
)
1233 static ULONG WINAPI
ClassFactory_Release(IClassFactory
*iface
)
1238 static HRESULT WINAPI
ClassFactory_LockServer(IClassFactory
*iface
, BOOL fLock
)
1243 static HRESULT WINAPI
InstallEngineCF_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
,
1244 REFIID riid
, void **ppv
)
1246 InstallEngine
*engine
;
1249 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
1251 engine
= heap_alloc_zero(sizeof(*engine
));
1253 return E_OUTOFMEMORY
;
1255 engine
->IInstallEngine2_iface
.lpVtbl
= &InstallEngine2Vtbl
;
1256 engine
->IInstallEngineTiming_iface
.lpVtbl
= &InstallEngineTimingVtbl
;
1258 engine
->status
= ENGINESTATUS_NOTREADY
;
1260 hres
= IInstallEngine2_QueryInterface(&engine
->IInstallEngine2_iface
, riid
, ppv
);
1261 IInstallEngine2_Release(&engine
->IInstallEngine2_iface
);
1265 static const IClassFactoryVtbl InstallEngineCFVtbl
= {
1266 ClassFactory_QueryInterface
,
1267 ClassFactory_AddRef
,
1268 ClassFactory_Release
,
1269 InstallEngineCF_CreateInstance
,
1270 ClassFactory_LockServer
1273 static IClassFactory InstallEngineCF
= { &InstallEngineCFVtbl
};
1275 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpv
)
1279 case DLL_WINE_PREATTACH
:
1280 return FALSE
; /* prefer native version */
1281 case DLL_PROCESS_ATTACH
:
1282 instance
= hInstDLL
;
1283 DisableThreadLibraryCalls(hInstDLL
);
1289 /***********************************************************************
1290 * DllGetClassObject (INSENG.@)
1292 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID iid
, LPVOID
*ppv
)
1294 if(IsEqualGUID(rclsid
, &CLSID_InstallEngine
)) {
1295 TRACE("(CLSID_InstallEngine %s %p)\n", debugstr_guid(iid
), ppv
);
1296 return IClassFactory_QueryInterface(&InstallEngineCF
, iid
, ppv
);
1299 FIXME("(%s %s %p)\n", debugstr_guid(rclsid
), debugstr_guid(iid
), ppv
);
1300 return CLASS_E_CLASSNOTAVAILABLE
;
1303 /***********************************************************************
1304 * DllCanUnloadNow (INSENG.@)
1306 HRESULT WINAPI
DllCanUnloadNow(void)
1311 /***********************************************************************
1312 * DllRegisterServer (INSENG.@)
1314 HRESULT WINAPI
DllRegisterServer(void)
1316 return __wine_register_resources( instance
);
1319 /***********************************************************************
1320 * DllUnregisterServer (INSENG.@)
1322 HRESULT WINAPI
DllUnregisterServer(void)
1324 return __wine_unregister_resources( instance
);
1327 BOOL WINAPI
CheckTrustEx( LPVOID a
, LPVOID b
, LPVOID c
, LPVOID d
, LPVOID e
)
1329 FIXME("%p %p %p %p %p\n", a
, b
, c
, d
, e
);
1333 /***********************************************************************
1334 * DllInstall (INSENG.@)
1336 HRESULT WINAPI
DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
1338 FIXME("(%s, %s): stub\n", bInstall
? "TRUE" : "FALSE", debugstr_w(cmdline
));