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