Sync to trunk revision 61757.
[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 #include "rapps.h"
29
30 static PAPPLICATION_INFO AppInfo;
31 static HICON hIcon = NULL;
32
33 typedef struct _IBindStatusCallbackImpl
34 {
35 const IBindStatusCallbackVtbl *vtbl;
36 LONG ref;
37 HWND hDialog;
38 BOOL *pbCancelled;
39 } IBindStatusCallbackImpl;
40
41 static
42 HRESULT WINAPI
43 dlQueryInterface(IBindStatusCallback* This, REFIID riid, void** ppvObject)
44 {
45 if (!ppvObject) return E_POINTER;
46
47 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IBindStatusCallback))
48 {
49 IBindStatusCallback_AddRef(This);
50 *ppvObject = This;
51 return S_OK;
52 }
53
54 return E_NOINTERFACE;
55 }
56
57 static
58 ULONG WINAPI
59 dlAddRef(IBindStatusCallback* iface)
60 {
61 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl*) iface;
62 return InterlockedIncrement(&This->ref);
63 }
64
65 static
66 ULONG WINAPI
67 dlRelease(IBindStatusCallback* iface)
68 {
69 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl*) iface;
70 DWORD ref = InterlockedDecrement(&This->ref);
71
72 if (!ref)
73 {
74 DestroyWindow(This->hDialog);
75 HeapFree(GetProcessHeap(), 0, This);
76 }
77
78 return ref;
79 }
80
81 static
82 HRESULT WINAPI
83 dlOnStartBinding(IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib)
84 {
85 return S_OK;
86 }
87
88 static
89 HRESULT WINAPI
90 dlGetPriority(IBindStatusCallback* iface, LONG* pnPriority)
91 {
92 return S_OK;
93 }
94
95 static
96 HRESULT WINAPI
97 dlOnLowResource( IBindStatusCallback* iface, DWORD reserved)
98 {
99 return S_OK;
100 }
101
102 static
103 HRESULT WINAPI
104 dlOnProgress(IBindStatusCallback* iface,
105 ULONG ulProgress,
106 ULONG ulProgressMax,
107 ULONG ulStatusCode,
108 LPCWSTR szStatusText)
109 {
110 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
111 HWND Item;
112 LONG r;
113 WCHAR OldText[100];
114
115 Item = GetDlgItem(This->hDialog, IDC_DOWNLOAD_PROGRESS);
116 if (Item && ulProgressMax)
117 {
118 SendMessageW(Item, PBM_SETPOS, ((ULONGLONG)ulProgress * 100) / ulProgressMax, 0);
119 }
120
121 Item = GetDlgItem(This->hDialog, IDC_DOWNLOAD_STATUS);
122 if (Item && szStatusText)
123 {
124 SendMessageW(Item, WM_GETTEXT, sizeof(OldText) / sizeof(OldText[0]), (LPARAM) OldText);
125 if (sizeof(OldText) / sizeof(OldText[0]) - 1 <= wcslen(OldText) || 0 != wcscmp(OldText, szStatusText))
126 {
127 SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) szStatusText);
128 }
129 }
130
131 SetLastError(0);
132 r = GetWindowLongPtrW(This->hDialog, GWLP_USERDATA);
133 if (0 != r || 0 != GetLastError())
134 {
135 *This->pbCancelled = TRUE;
136 return E_ABORT;
137 }
138
139 return S_OK;
140 }
141
142 static
143 HRESULT WINAPI
144 dlOnStopBinding(IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError)
145 {
146 return S_OK;
147 }
148
149 static
150 HRESULT WINAPI
151 dlGetBindInfo(IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo)
152 {
153 return S_OK;
154 }
155
156 static
157 HRESULT WINAPI
158 dlOnDataAvailable(IBindStatusCallback* iface, DWORD grfBSCF,
159 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
160 {
161 return S_OK;
162 }
163
164 static
165 HRESULT WINAPI
166 dlOnObjectAvailable(IBindStatusCallback* iface, REFIID riid, IUnknown* punk)
167 {
168 return S_OK;
169 }
170
171 static const IBindStatusCallbackVtbl dlVtbl =
172 {
173 dlQueryInterface,
174 dlAddRef,
175 dlRelease,
176 dlOnStartBinding,
177 dlGetPriority,
178 dlOnLowResource,
179 dlOnProgress,
180 dlOnStopBinding,
181 dlGetBindInfo,
182 dlOnDataAvailable,
183 dlOnObjectAvailable
184 };
185
186 static IBindStatusCallback*
187 CreateDl(HWND Dlg, BOOL *pbCancelled)
188 {
189 IBindStatusCallbackImpl *This;
190
191 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IBindStatusCallbackImpl));
192 if (!This) return NULL;
193
194 This->vtbl = &dlVtbl;
195 This->ref = 1;
196 This->hDialog = Dlg;
197 This->pbCancelled = pbCancelled;
198
199 return (IBindStatusCallback*) This;
200 }
201
202 static
203 DWORD WINAPI
204 ThreadFunc(LPVOID Context)
205 {
206 IBindStatusCallback *dl;
207 WCHAR path[MAX_PATH];
208 LPWSTR p;
209 STARTUPINFOW si;
210 PROCESS_INFORMATION pi;
211 HWND Dlg = (HWND) Context;
212 DWORD r, len;
213 BOOL bCancelled = FALSE;
214 BOOL bTempfile = FALSE;
215 BOOL bCab = FALSE;
216
217 /* built the path for the download */
218 p = wcsrchr(AppInfo->szUrlDownload, L'/');
219 if (!p) goto end;
220
221 len = wcslen(AppInfo->szUrlDownload);
222 if (len > 4)
223 {
224 if (AppInfo->szUrlDownload[len - 4] == '.' &&
225 AppInfo->szUrlDownload[len - 3] == 'c' &&
226 AppInfo->szUrlDownload[len - 2] == 'a' &&
227 AppInfo->szUrlDownload[len - 1] == 'b')
228 {
229 bCab = TRUE;
230 if (!GetStorageDirectory(path, sizeof(path) / sizeof(path[0])))
231 goto end;
232 }
233 else
234 {
235 if (FAILED(StringCbCopyW(path, sizeof(path),
236 SettingsInfo.szDownloadDir)))
237 {
238 goto end;
239 }
240 }
241 }
242 else goto end;
243
244 if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
245 {
246 if (!CreateDirectoryW(path, NULL))
247 goto end;
248 }
249
250 if (FAILED(StringCbCatW(path, sizeof(path), L"\\")))
251 goto end;
252 if (FAILED(StringCbCatW(path, sizeof(path), p + 1)))
253 goto end;
254
255 /* download it */
256 bTempfile = TRUE;
257 dl = CreateDl(Context, &bCancelled);
258 r = URLDownloadToFileW(NULL, AppInfo->szUrlDownload, path, 0, dl);
259 if (dl) IBindStatusCallback_Release(dl);
260 if (S_OK != r) goto end;
261 else if (bCancelled) goto end;
262
263 ShowWindow(Dlg, SW_HIDE);
264
265 /* run it */
266 ZeroMemory(&si, sizeof(si));
267 si.cb = sizeof(si);
268 r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
269 if (0 == r) goto end;
270
271 CloseHandle(pi.hThread);
272 WaitForSingleObject(pi.hProcess, INFINITE);
273 CloseHandle(pi.hProcess);
274
275 end:
276 if (bTempfile)
277 {
278 if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
279 DeleteFileW(path);
280 }
281
282 EndDialog(Dlg, 0);
283
284 return 0;
285 }
286
287 static
288 INT_PTR CALLBACK
289 DownloadDlgProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
290 {
291 HANDLE Thread;
292 DWORD ThreadId;
293 HWND Item;
294
295 switch (Msg)
296 {
297 case WM_INITDIALOG:
298
299 hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
300 if (hIcon)
301 {
302 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
303 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
304 }
305
306 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0);
307 Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
308 if (Item)
309 {
310 SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
311 SendMessageW(Item, PBM_SETPOS, 0, 0);
312 }
313
314 Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
315 if (!Thread) return FALSE;
316 CloseHandle(Thread);
317 return TRUE;
318
319 case WM_COMMAND:
320 if (wParam == IDCANCEL)
321 {
322 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
323 PostMessageW(Dlg, WM_CLOSE, 0, 0);
324 }
325 return FALSE;
326
327 case WM_CLOSE:
328 if (hIcon) DestroyIcon(hIcon);
329 EndDialog(Dlg, 0);
330 return TRUE;
331
332 default:
333 return FALSE;
334 }
335 }
336
337 BOOL
338 DownloadApplication(INT Index)
339 {
340 if (!IS_AVAILABLE_ENUM(SelectedEnumType))
341 return FALSE;
342
343 AppInfo = (PAPPLICATION_INFO) ListViewGetlParam(Index);
344 if (!AppInfo) return FALSE;
345
346 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, AppInfo->szName);
347
348 DialogBoxW(hInst,
349 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
350 hMainWnd,
351 DownloadDlgProc);
352
353 return TRUE;
354 }
355
356 VOID
357 DownloadApplicationsDB(LPWSTR lpUrl)
358 {
359 APPLICATION_INFO IntInfo;
360
361 ZeroMemory(&IntInfo, sizeof(APPLICATION_INFO));
362 if (FAILED(StringCbCopyW(IntInfo.szUrlDownload,
363 sizeof(IntInfo.szUrlDownload),
364 lpUrl)))
365 {
366 return;
367 }
368
369 AppInfo = &IntInfo;
370
371 DialogBoxW(hInst,
372 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
373 hMainWnd,
374 DownloadDlgProc);
375 }
376