[RAPPS]
[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 #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 (!GetCurrentDirectoryW(MAX_PATH, path))
231 goto end;
232 }
233 else
234 {
235 wcscpy(path, SettingsInfo.szDownloadDir);
236 }
237 }
238 else goto end;
239
240 if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
241 {
242 if (!CreateDirectoryW(path, NULL))
243 goto end;
244 }
245
246 wcscat(path, L"\\");
247 wcscat(path, p + 1);
248
249 /* download it */
250 bTempfile = TRUE;
251 dl = CreateDl(Context, &bCancelled);
252 r = URLDownloadToFileW(NULL, AppInfo->szUrlDownload, path, 0, dl);
253 if (dl) IBindStatusCallback_Release(dl);
254 if (S_OK != r) goto end;
255 else if (bCancelled) goto end;
256
257 ShowWindow(Dlg, SW_HIDE);
258
259 /* run it */
260 ZeroMemory(&si, sizeof(si));
261 si.cb = sizeof(si);
262 r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
263 if (0 == r) goto end;
264
265 CloseHandle(pi.hThread);
266 WaitForSingleObject(pi.hProcess, INFINITE);
267 CloseHandle(pi.hProcess);
268
269 end:
270 if (bTempfile)
271 {
272 if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
273 DeleteFileW(path);
274 }
275
276 EndDialog(Dlg, 0);
277
278 return 0;
279 }
280
281 static
282 INT_PTR CALLBACK
283 DownloadDlgProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
284 {
285 HANDLE Thread;
286 DWORD ThreadId;
287 HWND Item;
288
289 switch (Msg)
290 {
291 case WM_INITDIALOG:
292
293 hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
294 if (hIcon)
295 {
296 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
297 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
298 }
299
300 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0);
301 Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
302 if (Item)
303 {
304 SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
305 SendMessageW(Item, PBM_SETPOS, 0, 0);
306 }
307
308 Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
309 if (!Thread) return FALSE;
310 CloseHandle(Thread);
311 return TRUE;
312
313 case WM_COMMAND:
314 if (wParam == IDCANCEL)
315 {
316 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
317 PostMessageW(Dlg, WM_CLOSE, 0, 0);
318 }
319 return FALSE;
320
321 case WM_CLOSE:
322 if (hIcon) DestroyIcon(hIcon);
323 EndDialog(Dlg, 0);
324 return TRUE;
325
326 default:
327 return FALSE;
328 }
329 }
330
331 BOOL
332 DownloadApplication(INT Index)
333 {
334 if (!IS_AVAILABLE_ENUM(SelectedEnumType))
335 return FALSE;
336
337 AppInfo = (PAPPLICATION_INFO) ListViewGetlParam(Index);
338 if (!AppInfo) return FALSE;
339
340 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_INSTALL, AppInfo->szName);
341
342 DialogBoxW(hInst,
343 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
344 hMainWnd,
345 DownloadDlgProc);
346
347 return TRUE;
348 }
349
350 VOID
351 DownloadApplicationsDB(LPWSTR lpUrl)
352 {
353 APPLICATION_INFO IntInfo;
354
355 ZeroMemory(&IntInfo, sizeof(APPLICATION_INFO));
356 wcscpy(IntInfo.szUrlDownload, lpUrl);
357
358 AppInfo = &IntInfo;
359
360 DialogBoxW(hInst,
361 MAKEINTRESOURCEW(IDD_DOWNLOAD_DIALOG),
362 hMainWnd,
363 DownloadDlgProc);
364 }
365