* Sync with recent trunk (r52637).
[reactos.git] / base / applications / rapps / loaddlg.c
1 /* PROJECT: ReactOS Applications Manager
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/rapps/loaddlg.c
4 * PURPOSE: Displaying a download dialog
5 * COPYRIGHT: Copyright 2001 John R. Sheets (for CodeWeavers)
6 * Copyright 2004 Mike McCormack (for CodeWeavers)
7 * Copyright 2005 Ge van Geldorp (gvg@reactos.org)
8 * Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
9 */
10 /*
11 * Based on Wine dlls/shdocvw/shdocvw_main.c
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 #define COBJMACROS
29 #define WIN32_NO_STATUS
30
31 #include "rapps.h"
32 #include "resource.h"
33
34 #include <commctrl.h>
35 #include <shlobj.h>
36 #include <shlwapi.h>
37 #include <urlmon.h>
38
39 static PAPPLICATION_INFO AppInfo;
40 static HICON hIcon = NULL;
41
42 typedef struct _IBindStatusCallbackImpl
43 {
44 const IBindStatusCallbackVtbl *vtbl;
45 LONG ref;
46 HWND hDialog;
47 BOOL *pbCancelled;
48 } IBindStatusCallbackImpl;
49
50 static
51 HRESULT WINAPI
52 dlQueryInterface(IBindStatusCallback* This, REFIID riid, void** ppvObject)
53 {
54 if (!ppvObject) return E_POINTER;
55
56 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IBindStatusCallback))
57 {
58 IBindStatusCallback_AddRef(This);
59 *ppvObject = This;
60 return S_OK;
61 }
62
63 return E_NOINTERFACE;
64 }
65
66 static
67 ULONG WINAPI
68 dlAddRef(IBindStatusCallback* iface)
69 {
70 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl*) iface;
71 return InterlockedIncrement(&This->ref);
72 }
73
74 static
75 ULONG WINAPI
76 dlRelease(IBindStatusCallback* iface)
77 {
78 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl*) iface;
79 DWORD ref = InterlockedDecrement(&This->ref);
80
81 if (!ref)
82 {
83 DestroyWindow(This->hDialog);
84 HeapFree(GetProcessHeap(), 0, This);
85 }
86
87 return ref;
88 }
89
90 static
91 HRESULT WINAPI
92 dlOnStartBinding(IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib)
93 {
94 return S_OK;
95 }
96
97 static
98 HRESULT WINAPI
99 dlGetPriority(IBindStatusCallback* iface, LONG* pnPriority)
100 {
101 return S_OK;
102 }
103
104 static
105 HRESULT WINAPI
106 dlOnLowResource( IBindStatusCallback* iface, DWORD reserved)
107 {
108 return S_OK;
109 }
110
111 static
112 HRESULT WINAPI
113 dlOnProgress(IBindStatusCallback* iface,
114 ULONG ulProgress,
115 ULONG ulProgressMax,
116 ULONG ulStatusCode,
117 LPCWSTR szStatusText)
118 {
119 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
120 HWND Item;
121 LONG r;
122 WCHAR OldText[100];
123
124 Item = GetDlgItem(This->hDialog, IDC_DOWNLOAD_PROGRESS);
125 if (Item && ulProgressMax)
126 {
127 SendMessageW(Item, PBM_SETPOS, ((ULONGLONG)ulProgress * 100) / ulProgressMax, 0);
128 }
129
130 Item = GetDlgItem(This->hDialog, IDC_DOWNLOAD_STATUS);
131 if (Item && szStatusText)
132 {
133 SendMessageW(Item, WM_GETTEXT, sizeof(OldText) / sizeof(OldText[0]), (LPARAM) OldText);
134 if (sizeof(OldText) / sizeof(OldText[0]) - 1 <= wcslen(OldText) || 0 != wcscmp(OldText, szStatusText))
135 {
136 SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) szStatusText);
137 }
138 }
139
140 SetLastError(0);
141 r = GetWindowLongPtrW(This->hDialog, GWLP_USERDATA);
142 if (0 != r || 0 != GetLastError())
143 {
144 *This->pbCancelled = TRUE;
145 return E_ABORT;
146 }
147
148 return S_OK;
149 }
150
151 static
152 HRESULT WINAPI
153 dlOnStopBinding(IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError)
154 {
155 return S_OK;
156 }
157
158 static
159 HRESULT WINAPI
160 dlGetBindInfo(IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo)
161 {
162 return S_OK;
163 }
164
165 static
166 HRESULT WINAPI
167 dlOnDataAvailable(IBindStatusCallback* iface, DWORD grfBSCF,
168 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
169 {
170 return S_OK;
171 }
172
173 static
174 HRESULT WINAPI
175 dlOnObjectAvailable(IBindStatusCallback* iface, REFIID riid, IUnknown* punk)
176 {
177 return S_OK;
178 }
179
180 static const IBindStatusCallbackVtbl dlVtbl =
181 {
182 dlQueryInterface,
183 dlAddRef,
184 dlRelease,
185 dlOnStartBinding,
186 dlGetPriority,
187 dlOnLowResource,
188 dlOnProgress,
189 dlOnStopBinding,
190 dlGetBindInfo,
191 dlOnDataAvailable,
192 dlOnObjectAvailable
193 };
194
195 static IBindStatusCallback*
196 CreateDl(HWND Dlg, BOOL *pbCancelled)
197 {
198 IBindStatusCallbackImpl *This;
199
200 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IBindStatusCallbackImpl));
201 if (!This) return NULL;
202
203 This->vtbl = &dlVtbl;
204 This->ref = 1;
205 This->hDialog = Dlg;
206 This->pbCancelled = pbCancelled;
207
208 return (IBindStatusCallback*) This;
209 }
210
211 static
212 DWORD WINAPI
213 ThreadFunc(LPVOID Context)
214 {
215 IBindStatusCallback *dl;
216 WCHAR path[MAX_PATH];
217 LPWSTR p;
218 STARTUPINFOW si;
219 PROCESS_INFORMATION pi;
220 HWND Dlg = (HWND) Context;
221 DWORD r, len;
222 BOOL bCancelled = FALSE;
223 BOOL bTempfile = FALSE;
224 BOOL bCab = FALSE;
225
226 /* built the path for the download */
227 p = wcsrchr(AppInfo->szUrlDownload, L'/');
228 if (!p) goto end;
229
230 len = wcslen(AppInfo->szUrlDownload);
231 if (len > 4)
232 {
233 if (AppInfo->szUrlDownload[len - 4] == '.' &&
234 AppInfo->szUrlDownload[len - 3] == 'c' &&
235 AppInfo->szUrlDownload[len - 2] == 'a' &&
236 AppInfo->szUrlDownload[len - 1] == 'b')
237 {
238 bCab = TRUE;
239 if (!GetCurrentDirectoryW(MAX_PATH, path))
240 goto end;
241 }
242 else
243 {
244 wcscpy(path, SettingsInfo.szDownloadDir);
245 }
246 }
247 else goto end;
248
249 if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
250 {
251 if (!CreateDirectoryW(path, NULL))
252 goto end;
253 }
254
255 wcscat(path, L"\\");
256 wcscat(path, p + 1);
257
258 /* download it */
259 bTempfile = TRUE;
260 dl = CreateDl(Context, &bCancelled);
261 r = URLDownloadToFileW(NULL, AppInfo->szUrlDownload, path, 0, dl);
262 if (dl) IBindStatusCallback_Release(dl);
263 if (S_OK != r) goto end;
264 else if (bCancelled) goto end;
265
266 ShowWindow(Dlg, SW_HIDE);
267
268 /* run it */
269 memset(&si, 0, sizeof(si));
270 si.cb = sizeof(si);
271 r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
272 if (0 == r) goto end;
273
274 CloseHandle(pi.hThread);
275 WaitForSingleObject(pi.hProcess, INFINITE);
276 CloseHandle(pi.hProcess);
277
278 end:
279 if (bTempfile)
280 {
281 if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
282 DeleteFileW(path);
283 }
284
285 EndDialog(Dlg, 0);
286
287 return 0;
288 }
289
290 static
291 INT_PTR CALLBACK
292 DownloadDlgProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
293 {
294 HANDLE Thread;
295 DWORD ThreadId;
296 HWND Item;
297
298 switch (Msg)
299 {
300 case WM_INITDIALOG:
301
302 hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
303 if (hIcon)
304 {
305 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
306 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
307 }
308
309 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0);
310 Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
311 if (Item)
312 {
313 SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
314 SendMessageW(Item, PBM_SETPOS, 0, 0);
315 }
316
317 Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
318 if (!Thread) return FALSE;
319 CloseHandle(Thread);
320 return TRUE;
321
322 case WM_COMMAND:
323 if (wParam == IDCANCEL)
324 {
325 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
326 PostMessageW(Dlg, WM_CLOSE, 0, 0);
327 }
328 return FALSE;
329
330 case WM_CLOSE:
331 if (hIcon) DestroyIcon(hIcon);
332 EndDialog(Dlg, 0);
333 return TRUE;
334
335 default:
336 return FALSE;
337 }
338 }
339
340 BOOL
341 DownloadApplication(INT Index)
342 {
343 if (!IS_AVAILABLE_ENUM(SelectedEnumType))
344 return FALSE;
345
346 AppInfo = (PAPPLICATION_INFO) ListViewGetlParam(Index);
347 if (!AppInfo) return FALSE;
348
349 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, AppInfo->szName);
350
351 DialogBoxW(hInst,
352 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
353 hMainWnd,
354 DownloadDlgProc);
355
356 return TRUE;
357 }
358
359 VOID
360 DownloadApplicationsDB(LPWSTR lpUrl)
361 {
362 APPLICATION_INFO IntInfo;
363
364 ZeroMemory(&IntInfo, sizeof(APPLICATION_INFO));
365 wcscpy(IntInfo.szUrlDownload, lpUrl);
366
367 AppInfo = &IntInfo;
368
369 DialogBoxW(hInst,
370 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
371 hMainWnd,
372 DownloadDlgProc);
373 }
374