2 * Copyright 2012 Jacek Caban for CodeWeavers
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
23 #include "urlmon_main.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
33 static const WCHAR ctxW[] = {'c','t','x',0};
34 static const WCHAR cab_extW[] = {'.','c','a','b',0};
35 static const WCHAR infW[] = {'i','n','f',0};
36 static const WCHAR dllW[] = {'d','l','l',0};
37 static const WCHAR ocxW[] = {'o','c','x',0};
47 IBindStatusCallback *callback;
51 const WCHAR *cache_file;
53 const WCHAR *file_name;
54 enum install_type install_type;
60 static void release_install_ctx(install_ctx_t *ctx)
63 IUri_Release(ctx->uri);
65 IBindStatusCallback_Release(ctx->callback);
66 heap_free(ctx->install_file);
70 static inline BOOL file_exists(const WCHAR *file_name)
72 return GetFileAttributesW(file_name) != INVALID_FILE_ATTRIBUTES;
75 static HRESULT extract_cab_file(install_ctx_t *ctx)
77 size_t path_len, file_len;
81 hres = ExtractFilesW(ctx->cache_file, ctx->tmp_dir, 0, NULL, NULL, 0);
83 WARN("ExtractFilesW failed: %08x\n", hres);
87 path_len = strlenW(ctx->tmp_dir);
88 file_len = strlenW(ctx->file_name);
89 ctx->install_file = heap_alloc((path_len+file_len+2)*sizeof(WCHAR));
90 if(!ctx->install_file)
93 memcpy(ctx->install_file, ctx->tmp_dir, path_len*sizeof(WCHAR));
94 ctx->install_file[path_len] = '\\';
95 memcpy(ctx->install_file+path_len+1, ctx->file_name, (file_len+1)*sizeof(WCHAR));
97 /* NOTE: Assume that file_name contains ".cab" extension */
98 ptr = ctx->install_file+path_len+1+file_len-3;
100 memcpy(ptr, infW, sizeof(infW));
101 if(file_exists(ctx->install_file)) {
102 ctx->install_type = INSTALL_INF;
106 memcpy(ptr, dllW, sizeof(dllW));
107 if(file_exists(ctx->install_file)) {
108 ctx->install_type = INSTALL_DLL;
112 memcpy(ptr, ocxW, sizeof(ocxW));
113 if(file_exists(ctx->install_file)) {
114 ctx->install_type = INSTALL_DLL;
118 FIXME("No known install file\n");
122 static HRESULT setup_dll(install_ctx_t *ctx)
127 HRESULT (WINAPI *reg_func)(void);
129 module = LoadLibraryW(ctx->install_file);
133 reg_func = (void*)GetProcAddress(module, "DllRegisterServer");
137 WARN("no DllRegisterServer function\n");
145 static HRESULT install_cab_file(install_ctx_t *ctx)
147 WCHAR tmp_path[MAX_PATH], tmp_dir[MAX_PATH];
148 BOOL res = FALSE, leave_temp = FALSE;
152 GetTempPathW(sizeof(tmp_path)/sizeof(WCHAR), tmp_path);
154 for(i=0; !res && i < 100; i++) {
155 GetTempFileNameW(tmp_path, NULL, GetTickCount() + i*17037, tmp_dir);
156 res = CreateDirectoryW(tmp_dir, NULL);
161 ctx->tmp_dir = tmp_dir;
163 TRACE("Using temporary directory %s\n", debugstr_w(tmp_dir));
165 hres = extract_cab_file(ctx);
166 if(SUCCEEDED(hres)) {
168 IBindStatusCallback_OnProgress(ctx->callback, 0, 0, BINDSTATUS_INSTALLINGCOMPONENTS, ctx->install_file);
170 switch(ctx->install_type) {
172 hres = RunSetupCommandW(ctx->hwnd, ctx->install_file, NULL, ctx->tmp_dir, NULL, NULL, RSC_FLAG_INF, NULL);
174 WARN("RunSetupCommandW failed: %08x\n", hres);
177 FIXME("Installing DLL, registering in temporary location\n");
178 hres = setup_dll(ctx);
188 RemoveDirectoryW(ctx->tmp_dir);
192 static void update_counter(install_ctx_t *ctx, HWND hwnd)
196 if(--ctx->counter <= 0) {
199 KillTimer(hwnd, ctx->timer);
200 LoadStringW(urlmon_instance, IDS_AXINSTALL_INSTALL, text, sizeof(text)/sizeof(WCHAR));
202 button_hwnd = GetDlgItem(hwnd, ID_AXINSTALL_INSTALL_BTN);
203 EnableWindow(button_hwnd, TRUE);
206 LoadStringW(urlmon_instance, IDS_AXINSTALL_INSTALLN, buf, sizeof(buf)/sizeof(WCHAR));
207 sprintfW(text, buf, ctx->counter);
210 SetDlgItemTextW(hwnd, ID_AXINSTALL_INSTALL_BTN, text);
213 static BOOL init_warning_dialog(HWND hwnd, install_ctx_t *ctx)
218 if(!SetPropW(hwnd, ctxW, ctx))
221 hres = IUri_GetDisplayUri(ctx->uri, &display_uri);
225 SetDlgItemTextW(hwnd, ID_AXINSTALL_LOCATION, display_uri);
226 SysFreeString(display_uri);
228 SendDlgItemMessageW(hwnd, ID_AXINSTALL_ICON, STM_SETICON,
229 (WPARAM)LoadIconW(0, (const WCHAR*)OIC_WARNING), 0);
232 update_counter(ctx, hwnd);
233 ctx->timer = SetTimer(hwnd, 1, 1000, NULL);
237 static INT_PTR WINAPI warning_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
240 case WM_INITDIALOG: {
241 if(!init_warning_dialog(hwnd, (install_ctx_t*)lparam))
247 case ID_AXINSTALL_INSTALL_BTN: {
248 install_ctx_t *ctx = GetPropW(hwnd, ctxW);
259 update_counter(GetPropW(hwnd, ctxW), hwnd);
266 static BOOL install_warning(install_ctx_t *ctx)
268 IWindowForBindingUI *window_iface;
269 HWND parent_hwnd = NULL;
273 FIXME("no callback\n");
277 hres = IBindStatusCallback_QueryInterface(ctx->callback, &IID_IWindowForBindingUI, (void**)&window_iface);
281 hres = IWindowForBindingUI_GetWindow(window_iface, &IID_ICodeInstall, &ctx->hwnd);
282 IWindowForBindingUI_Release(window_iface);
287 DialogBoxParamW(urlmon_instance, MAKEINTRESOURCEW(ID_AXINSTALL_WARNING_DLG), parent_hwnd, warning_proc, (LPARAM)ctx);
291 static HRESULT install_file(install_ctx_t *ctx, const WCHAR *cache_file)
296 TRACE("%s\n", debugstr_w(cache_file));
298 ctx->cache_file = cache_file;
300 if(!install_warning(ctx)) {
301 TRACE("Installation cancelled\n");
305 hres = IUri_GetPath(ctx->uri, &path);
306 if(SUCCEEDED(hres)) {
307 const WCHAR *ptr, *ptr2, *ext;
309 ptr = strrchrW(path, '/');
315 ptr2 = strrchrW(ptr, '\\');
319 ctx->file_name = ptr;
320 ext = strrchrW(ptr, '.');
324 if(!strcmpW(ext, cab_extW)) {
325 hres = install_cab_file(ctx);
327 FIXME("Unsupported extension %s\n", debugstr_w(ext));
336 static void failure_msgbox(install_ctx_t *ctx, HRESULT hres)
338 WCHAR buf[1024], fmt[1024];
340 LoadStringW(urlmon_instance, IDS_AXINSTALL_FAILURE, fmt, sizeof(fmt)/sizeof(WCHAR));
341 sprintfW(buf, fmt, hres);
342 MessageBoxW(ctx->hwnd, buf, NULL, MB_OK);
345 static HRESULT distunit_on_stop(void *ctx, const WCHAR *cache_file, HRESULT hresult, const WCHAR *error_str)
347 install_ctx_t *install_ctx = ctx;
349 TRACE("(%p %s %08x %s)\n", ctx, debugstr_w(cache_file), hresult, debugstr_w(error_str));
351 if(hresult == S_OK) {
352 hresult = install_file(install_ctx, cache_file);
354 failure_msgbox(ctx, hresult);
357 if(install_ctx->callback)
358 IBindStatusCallback_OnStopBinding(install_ctx->callback, hresult, error_str);
360 if(install_ctx->release_on_stop)
361 release_install_ctx(install_ctx);
365 /***********************************************************************
366 * AsyncInstallDistributionUnit (URLMON.@)
368 HRESULT WINAPI AsyncInstallDistributionUnit(const WCHAR *szDistUnit, const WCHAR *szTYPE, const WCHAR *szExt,
369 DWORD dwFileVersionMS, DWORD dwFileVersionLS, const WCHAR *szURL, IBindCtx *pbc, void *pvReserved, DWORD flags)
374 TRACE("(%s %s %s %x %x %s %p %p %x)\n", debugstr_w(szDistUnit), debugstr_w(szTYPE), debugstr_w(szExt),
375 dwFileVersionMS, dwFileVersionLS, debugstr_w(szURL), pbc, pvReserved, flags);
377 if(szDistUnit || szTYPE || szExt)
378 FIXME("Unsupported arguments\n");
380 ctx = heap_alloc_zero(sizeof(*ctx));
382 return E_OUTOFMEMORY;
384 hres = CreateUri(szURL, 0, 0, &ctx->uri);
387 return E_OUTOFMEMORY;
390 ctx->callback = bsc_from_bctx(pbc);
392 hres = download_to_cache(ctx->uri, distunit_on_stop, ctx, ctx->callback);
393 if(hres == MK_S_ASYNCHRONOUS)
394 ctx->release_on_stop = TRUE;
396 release_install_ctx(ctx);