[RAPPS]
[reactos.git] / reactos / base / applications / rapps / loaddlg.cpp
1 /* PROJECT: ReactOS Applications Manager
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/rapps/loaddlg.cpp
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 * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
10 * Copyright 2017 Alexander Shaposhnikov (chaez.san@gmail.com)
11 */
12
13 /*
14 * Based on Wine dlls/shdocvw/shdocvw_main.c
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31 #include "rapps.h"
32
33 #include <shlobj_undoc.h>
34 #include <shlguid_undoc.h>
35
36 #include <atlbase.h>
37 #include <atlcom.h>
38 #include <wininet.h>
39 #include <shellutils.h>
40 #include <windowsx.h>
41
42 class CDownloadDialog :
43 public CComObjectRootEx<CComMultiThreadModelNoCS>,
44 public IBindStatusCallback
45 {
46 HWND m_hDialog;
47 PBOOL m_pbCancelled;
48 BOOL m_UrlHasBeenCopied;
49
50 public:
51 ~CDownloadDialog()
52 {
53 DestroyWindow(m_hDialog);
54 }
55
56 HRESULT Initialize(HWND Dlg, BOOL *pbCancelled)
57 {
58 m_hDialog = Dlg;
59 m_pbCancelled = pbCancelled;
60 m_UrlHasBeenCopied = FALSE;
61 return S_OK;
62 }
63
64 virtual HRESULT STDMETHODCALLTYPE OnStartBinding(
65 DWORD dwReserved,
66 IBinding *pib)
67 {
68 return S_OK;
69 }
70
71 virtual HRESULT STDMETHODCALLTYPE GetPriority(
72 LONG *pnPriority)
73 {
74 return S_OK;
75 }
76
77 virtual HRESULT STDMETHODCALLTYPE OnLowResource(
78 DWORD reserved)
79 {
80 return S_OK;
81 }
82
83 virtual HRESULT STDMETHODCALLTYPE OnProgress(
84 ULONG ulProgress,
85 ULONG ulProgressMax,
86 ULONG ulStatusCode,
87 LPCWSTR szStatusText)
88 {
89 HWND Item;
90 LONG r;
91
92 Item = GetDlgItem(m_hDialog, IDC_DOWNLOAD_PROGRESS);
93 if (Item && ulProgressMax)
94 {
95 WCHAR szProgress[100];
96 WCHAR szProgressMax[100];
97 UINT uiPercentage = ((ULONGLONG) ulProgress * 100) / ulProgressMax;
98
99 /* send the current progress to the progress bar */
100 SendMessageW(Item, PBM_SETPOS, uiPercentage, 0);
101
102 /* format the bits and bytes into pretty and accessible units... */
103 StrFormatByteSizeW(ulProgress, szProgress, _countof(szProgress));
104 StrFormatByteSizeW(ulProgressMax, szProgressMax, _countof(szProgressMax));
105
106 /* ...and post all of it to our subclassed progress bar text subroutine */
107 ATL::CStringW m_ProgressText;
108 m_ProgressText.Format(L"%u%% \x2014 %ls / %ls",
109 uiPercentage,
110 szProgress,
111 szProgressMax);
112 SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) m_ProgressText.GetString());
113 }
114
115 Item = GetDlgItem(m_hDialog, IDC_DOWNLOAD_STATUS);
116 if (Item && szStatusText && wcslen(szStatusText) > 0 && m_UrlHasBeenCopied == FALSE)
117 {
118 DWORD len = wcslen(szStatusText) + 1;
119 ATL::CStringW buf;
120
121 /* beautify our url for display purposes */
122 if (!InternetCanonicalizeUrlW(szStatusText, buf.GetBuffer(len), &len, ICU_DECODE | ICU_NO_ENCODE))
123 {
124 /* just use the original */
125 buf.ReleaseBuffer();
126 buf = szStatusText;
127 }
128 else
129 {
130 buf.ReleaseBuffer();
131 }
132
133 /* paste it into our dialog and don't do it again in this instance */
134 SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) buf.GetString());
135 m_UrlHasBeenCopied = TRUE;
136 }
137
138 SetLastError(0);
139 r = GetWindowLongPtrW(m_hDialog, GWLP_USERDATA);
140 if (0 != r || 0 != GetLastError())
141 {
142 *m_pbCancelled = TRUE;
143 return E_ABORT;
144 }
145
146 return S_OK;
147 }
148
149 virtual HRESULT STDMETHODCALLTYPE OnStopBinding(
150 HRESULT hresult,
151 LPCWSTR szError)
152 {
153 return S_OK;
154 }
155
156 virtual HRESULT STDMETHODCALLTYPE GetBindInfo(
157 DWORD *grfBINDF,
158 BINDINFO *pbindinfo)
159 {
160 return S_OK;
161 }
162
163 virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(
164 DWORD grfBSCF,
165 DWORD dwSize,
166 FORMATETC *pformatetc,
167 STGMEDIUM *pstgmed)
168 {
169 return S_OK;
170 }
171
172 virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(
173 REFIID riid,
174 IUnknown *punk)
175 {
176 return S_OK;
177 }
178
179 BEGIN_COM_MAP(CDownloadDialog)
180 COM_INTERFACE_ENTRY_IID(IID_IBindStatusCallback, IBindStatusCallback)
181 END_COM_MAP()
182 };
183
184 extern "C"
185 HRESULT WINAPI CDownloadDialog_Constructor(HWND Dlg, BOOL *pbCancelled, REFIID riid, LPVOID *ppv)
186 {
187 return ShellObjectCreatorInit<CDownloadDialog>(Dlg, pbCancelled, riid, ppv);
188 }
189
190 #ifdef USE_CERT_PINNING
191 static BOOL CertIsValid(HINTERNET hInternet, LPWSTR lpszHostName)
192 {
193 HINTERNET hConnect;
194 HINTERNET hRequest;
195 DWORD certInfoLength;
196 BOOL Ret = FALSE;
197 INTERNET_CERTIFICATE_INFOW certInfo;
198
199 hConnect = InternetConnectW(hInternet, lpszHostName, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0);
200 if (hConnect)
201 {
202 hRequest = HttpOpenRequestW(hConnect, L"HEAD", NULL, NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
203 if (hRequest != NULL)
204 {
205 Ret = HttpSendRequestW(hRequest, L"", 0, NULL, 0);
206 if (Ret)
207 {
208 certInfoLength = sizeof(certInfo);
209 Ret = InternetQueryOptionW(hRequest,
210 INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
211 &certInfo,
212 &certInfoLength);
213 if (Ret)
214 {
215 if (certInfo.lpszEncryptionAlgName)
216 LocalFree(certInfo.lpszEncryptionAlgName);
217 if (certInfo.lpszIssuerInfo)
218 {
219 if (strcmp((LPSTR) certInfo.lpszIssuerInfo, CERT_ISSUER_INFO) != 0)
220 Ret = FALSE;
221 LocalFree(certInfo.lpszIssuerInfo);
222 }
223 if (certInfo.lpszProtocolName)
224 LocalFree(certInfo.lpszProtocolName);
225 if (certInfo.lpszSignatureAlgName)
226 LocalFree(certInfo.lpszSignatureAlgName);
227 if (certInfo.lpszSubjectInfo)
228 {
229 if (strcmp((LPSTR) certInfo.lpszSubjectInfo, CERT_SUBJECT_INFO) != 0)
230 Ret = FALSE;
231 LocalFree(certInfo.lpszSubjectInfo);
232 }
233 }
234 }
235 InternetCloseHandle(hRequest);
236 }
237 InternetCloseHandle(hConnect);
238 }
239 return Ret;
240 }
241 #endif
242
243 inline VOID
244 MessageBox_LoadString(HWND hMainWnd, INT StringID)
245 {
246 ATL::CString szMsgText;
247 if (szMsgText.LoadStringW(hInst, StringID))
248 MessageBoxW(hMainWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
249 }
250
251 // DownloadManager
252
253 PAPPLICATION_INFO DownloadManager::AppInfo = NULL;
254
255 INT_PTR CALLBACK DownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
256 {
257 HANDLE Thread;
258 DWORD ThreadId;
259 HWND Item;
260
261 switch (uMsg)
262 {
263 case WM_INITDIALOG:
264 {
265 HICON hIconSm, hIconBg;
266 WCHAR szCaption[MAX_PATH];
267 ATL::CStringW szNewCaption;
268
269 hIconBg = (HICON) GetClassLongW(hMainWnd, GCLP_HICON);
270 hIconSm = (HICON) GetClassLongW(hMainWnd, GCLP_HICONSM);
271
272 if (hIconBg && hIconSm)
273 {
274 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIconBg);
275 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSm);
276 }
277
278 // Change caption to show the currently downloaded app
279 GetWindowTextW(Dlg, szCaption, MAX_PATH);
280 szNewCaption.Format(szCaption, AppInfo->szName.GetString());
281 SetWindowTextW(Dlg, szNewCaption.GetString());
282
283 SetWindowLongW(Dlg, GWLP_USERDATA, 0);
284 Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
285 if (Item)
286 {
287 // initialize the default values for our nifty progress bar
288 // and subclass it so that it learns to print a status text
289 SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
290 SendMessageW(Item, PBM_SETPOS, 0, 0);
291
292 SetWindowSubclass(Item, DownloadProgressProc, 0, 0);
293 }
294
295 // add a neat placeholder until the download URL is retrieved
296 SetDlgItemTextW(Dlg, IDC_DOWNLOAD_STATUS, L"\x2022 \x2022 \x2022");
297
298 Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
299 if (!Thread)
300 return FALSE;
301 CloseHandle(Thread);
302 return TRUE;
303 }
304 case WM_COMMAND:
305 if (wParam == IDCANCEL)
306 {
307 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
308 PostMessageW(Dlg, WM_CLOSE, 0, 0);
309 }
310 return FALSE;
311
312 case WM_CLOSE:
313 DestroyWindow(Dlg);
314 return TRUE;
315
316 default:
317 return FALSE;
318 }
319 }
320
321 LRESULT CALLBACK DownloadManager::DownloadProgressProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
322 {
323 static ATL::CStringW szProgressText;
324
325 switch (uMsg)
326 {
327 case WM_SETTEXT:
328 {
329 if (lParam)
330 {
331 szProgressText = (PCWSTR) lParam;
332 }
333 return TRUE;
334 }
335
336 case WM_ERASEBKGND:
337 case WM_PAINT:
338 {
339 PAINTSTRUCT ps;
340 HDC hDC = BeginPaint(hWnd, &ps), hdcMem;
341 HBITMAP hbmMem;
342 HANDLE hOld;
343 RECT myRect;
344 UINT win_width, win_height;
345
346 GetClientRect(hWnd, &myRect);
347
348 /* grab the progress bar rect size */
349 win_width = myRect.right - myRect.left;
350 win_height = myRect.bottom - myRect.top;
351
352 /* create an off-screen DC for double-buffering */
353 hdcMem = CreateCompatibleDC(hDC);
354 hbmMem = CreateCompatibleBitmap(hDC, win_width, win_height);
355
356 hOld = SelectObject(hdcMem, hbmMem);
357
358 /* call the original draw code and redirect it to our memory buffer */
359 DefSubclassProc(hWnd, uMsg, (WPARAM) hdcMem, lParam);
360
361 /* draw our nifty progress text over it */
362 SelectFont(hdcMem, GetStockFont(DEFAULT_GUI_FONT));
363 DrawShadowText(hdcMem, szProgressText.GetString(), szProgressText.GetLength(),
364 &myRect,
365 DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE,
366 GetSysColor(COLOR_CAPTIONTEXT),
367 GetSysColor(COLOR_3DSHADOW),
368 1, 1);
369
370 /* transfer the off-screen DC to the screen */
371 BitBlt(hDC, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
372
373 /* free the off-screen DC */
374 SelectObject(hdcMem, hOld);
375 DeleteObject(hbmMem);
376 DeleteDC(hdcMem);
377
378 EndPaint(hWnd, &ps);
379 return 0;
380 }
381
382 /* Raymond Chen says that we should safely unsubclass all the things!
383 (http://blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx) */
384 case WM_NCDESTROY:
385 {
386 szProgressText.Empty();
387 RemoveWindowSubclass(hWnd, DownloadProgressProc, uIdSubclass);
388 }
389 /* Fall-through */
390 default:
391 return DefSubclassProc(hWnd, uMsg, wParam, lParam);
392 }
393 }
394
395 DWORD WINAPI DownloadManager::ThreadFunc(LPVOID Context)
396 {
397 CComPtr<IBindStatusCallback> dl;
398 ATL::CStringW Path;
399 PWSTR p, q;
400 HWND Dlg = (HWND) Context;
401 ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
402 ULONG dwCurrentBytesRead = 0;
403 ULONG dwStatusLen = sizeof(dwStatus);
404 BOOL bCancelled = FALSE;
405 BOOL bTempfile = FALSE;
406 BOOL bCab = FALSE;
407 HINTERNET hOpen = NULL;
408 HINTERNET hFile = NULL;
409 HANDLE hOut = INVALID_HANDLE_VALUE;
410 unsigned char lpBuffer[4096];
411 LPCWSTR lpszAgent = L"RApps/1.0";
412 URL_COMPONENTS urlComponents;
413 size_t urlLength, filenameLength;
414
415 if (!AppInfo)
416 {
417 MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
418 goto end;
419 }
420
421 /* build the path for the download */
422 p = wcsrchr(AppInfo->szUrlDownload.GetString(), L'/');
423 q = wcsrchr(AppInfo->szUrlDownload.GetString(), L'?');
424
425 /* do we have a final slash separator? */
426 if (!p)
427 goto end;
428
429 /* prepare the tentative length of the filename, maybe we've to remove part of it later on */
430 filenameLength = wcslen(p) * sizeof(WCHAR);
431
432 /* do we have query arguments in the target URL after the filename? account for them
433 (e.g. https://example.org/myfile.exe?no_adware_plz) */
434 if (q && q > p && (q - p) > 0)
435 filenameLength -= wcslen(q - 1) * sizeof(WCHAR);
436
437 /* is this URL an update package for RAPPS? if so store it in a different place */
438 if (AppInfo->szUrlDownload == APPLICATION_DATABASE_URL)
439 {
440 bCab = TRUE;
441 if (!GetStorageDirectory(Path))
442 goto end;
443 }
444 else
445 {
446 Path = SettingsInfo.szDownloadDir;
447 }
448
449 /* is the path valid? can we access it? */
450 if (GetFileAttributesW(Path.GetString()) == INVALID_FILE_ATTRIBUTES)
451 {
452 if (!CreateDirectoryW(Path.GetString(), NULL))
453 goto end;
454 }
455
456 /* append a \ to the provided file system path, and the filename portion from the URL after that */
457 Path.Format(L"\\%ls", (p + 1));
458
459 if (!bCab && AppInfo->szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES)
460 {
461 /* only open it in case of total correctness */
462 if (VerifyInteg(AppInfo->szSHA1, Path))
463 goto run;
464 }
465
466 /* download it */
467 bTempfile = TRUE;
468 CDownloadDialog_Constructor(Dlg, &bCancelled, IID_PPV_ARG(IBindStatusCallback, &dl));
469
470 if (dl == NULL)
471 goto end;
472
473 /* FIXME: this should just be using the system-wide proxy settings */
474 switch (SettingsInfo.Proxy)
475 {
476 case 0: /* preconfig */
477 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
478 break;
479 case 1: /* direct (no proxy) */
480 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
481 break;
482 case 2: /* use proxy */
483 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
484 break;
485 default: /* preconfig */
486 hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
487 break;
488 }
489
490 if (!hOpen)
491 goto end;
492
493 hFile = InternetOpenUrlW(hOpen, AppInfo->szUrlDownload, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_KEEP_CONNECTION, 0);
494 if (!hFile)
495 {
496 MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD2);
497 goto end;
498 }
499
500 if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
501 goto end;
502
503 if (dwStatus != HTTP_STATUS_OK)
504 {
505 MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_DOWNLOAD);
506 goto end;
507 }
508
509 dwStatusLen = sizeof(dwStatus);
510
511 memset(&urlComponents, 0, sizeof(urlComponents));
512 urlComponents.dwStructSize = sizeof(urlComponents);
513
514 urlLength = AppInfo->szUrlDownload.GetLength();
515 urlComponents.dwSchemeLength = urlLength + 1;
516 urlComponents.lpszScheme = (LPWSTR) malloc(urlComponents.dwSchemeLength * sizeof(WCHAR));
517 urlComponents.dwHostNameLength = urlLength + 1;
518 urlComponents.lpszHostName = (LPWSTR) malloc(urlComponents.dwHostNameLength * sizeof(WCHAR));
519
520 if (!InternetCrackUrlW(AppInfo->szUrlDownload, urlLength + 1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
521 goto end;
522
523 if (urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
524 HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatus, 0);
525
526 if (urlComponents.nScheme == INTERNET_SCHEME_FTP)
527 dwContentLen = FtpGetFileSize(hFile, &dwStatus);
528
529 #ifdef USE_CERT_PINNING
530 /* are we using HTTPS to download the RAPPS update package? check if the certificate is original */
531 if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) &&
532 (wcscmp(AppInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0) &&
533 (!CertIsValid(hOpen, urlComponents.lpszHostName)))
534 {
535 MessageBox_LoadString(hMainWnd, IDS_CERT_DOES_NOT_MATCH);
536 goto end;
537 }
538 #endif
539
540 free(urlComponents.lpszScheme);
541 free(urlComponents.lpszHostName);
542
543 hOut = CreateFileW(Path.GetString(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
544
545 if (hOut == INVALID_HANDLE_VALUE)
546 goto end;
547
548 do
549 {
550 if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead))
551 {
552 MessageBox_LoadString(hMainWnd, IDS_INTERRUPTED_DOWNLOAD);
553 goto end;
554 }
555
556 if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL))
557 {
558 MessageBox_LoadString(hMainWnd, IDS_UNABLE_TO_WRITE);
559 goto end;
560 }
561
562 dwCurrentBytesRead += dwBytesRead;
563 dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, AppInfo->szUrlDownload);
564 } while (dwBytesRead && !bCancelled);
565
566 CloseHandle(hOut);
567 hOut = INVALID_HANDLE_VALUE;
568
569 if (bCancelled)
570 goto end;
571
572 /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
573 verify its integrity by using the native advapi32.A_SHA1 functions */
574 if (!bCab && AppInfo->szSHA1[0] != 0)
575 {
576 ATL::CStringW szMsgText;
577
578 /* change a few strings in the download dialog to reflect the verification process */
579 if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_TITLE))
580 goto end;
581
582 SetWindowText(Dlg, szMsgText.GetString());
583 SendMessageW(GetDlgItem(Dlg, IDC_DOWNLOAD_STATUS), WM_SETTEXT, 0, (LPARAM) Path.GetString());
584
585 /* this may take a while, depending on the file size */
586 if (!VerifyInteg(AppInfo->szSHA1, Path.GetString()))
587 {
588 if (!szMsgText.LoadStringW(hInst, IDS_INTEG_CHECK_FAIL))
589 goto end;
590
591 MessageBoxW(Dlg, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
592 goto end;
593 }
594 }
595
596 ShowWindow(Dlg, SW_HIDE);
597
598 run:
599 /* run it */
600 if (!bCab)
601 ShellExecuteW(NULL, L"open", Path.GetString(), NULL, NULL, SW_SHOWNORMAL);
602
603 end:
604 if (hOut != INVALID_HANDLE_VALUE)
605 CloseHandle(hOut);
606
607 InternetCloseHandle(hFile);
608 InternetCloseHandle(hOpen);
609
610 if (bTempfile)
611 {
612 if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
613 DeleteFileW(Path.GetString());
614 }
615
616 EndDialog(Dlg, 0);
617
618 return 0;
619 }
620
621 //TODO: Maybe launch this (similar function) in a seperate thread, so the list could be updated
622 BOOL DownloadManager::DownloadListOfApplications(const ATL::CSimpleArray<PAPPLICATION_INFO>& AppsList)
623 {
624 BOOL bResult = TRUE;
625
626 for (INT i = 0; i < AppsList.GetSize(); ++i)
627 {
628 bResult = DownloadApplication(AppsList[i]) && bResult;
629 }
630 return bResult;
631 }
632
633 BOOL DownloadManager::DownloadApplication(PAPPLICATION_INFO pAppInfo)
634 {
635 if (!pAppInfo)
636 {
637 return FALSE;
638 }
639
640 // Create a dialog and issue a download process
641 AppInfo = pAppInfo;
642 LaunchDownloadDialog();
643
644 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, AppInfo->szName.GetString());
645
646 return TRUE;
647 }
648
649 VOID DownloadManager::DownloadApplicationsDB(LPCWSTR lpUrl)
650 {
651 APPLICATION_INFO IntInfo;
652 IntInfo.szUrlDownload = lpUrl;
653
654 AppInfo = &IntInfo;
655
656 LaunchDownloadDialog();
657 }
658
659 //TODO: Reuse the dialog
660 VOID DownloadManager::LaunchDownloadDialog()
661 {
662 CreateDialogW(hInst,
663 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
664 hMainWnd,
665 DownloadDlgProc);
666 }