No need to define __USE_W32API
[reactos.git] / rosapps / downloader / download.c
1 /* PROJECT: ReactOS Downloader (was GetFirefox)
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/downloader/download.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 2007 Dmitry Chapyshev ()lentind@yandex.ru)
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #define COBJMACROS
29 #define WIN32_NO_STATUS
30 #include <windows.h>
31 #include <commctrl.h>
32 #include <shlobj.h>
33 #include <shlwapi.h>
34 #include <urlmon.h>
35
36 #include "resources.h"
37 #include "structures.h"
38
39 #define NDEBUG
40 #include <debug.h>
41
42 extern struct Application* SelectedApplication;
43 extern WCHAR Strings [STRING_COUNT][MAX_STRING_LENGHT];
44
45 typedef struct _IBindStatusCallbackImpl
46 {
47 const IBindStatusCallbackVtbl *vtbl;
48 LONG ref;
49 HWND hDialog;
50 BOOL *pbCancelled;
51 } IBindStatusCallbackImpl;
52
53 static HRESULT WINAPI
54 dlQueryInterface(IBindStatusCallback* This, REFIID riid, void** ppvObject)
55 {
56 if (NULL == ppvObject)
57 {
58 return E_POINTER;
59 }
60
61 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IBindStatusCallback))
62 {
63 IBindStatusCallback_AddRef( This );
64 *ppvObject = This;
65 return S_OK;
66 }
67
68 return E_NOINTERFACE;
69 }
70
71 static ULONG WINAPI
72 dlAddRef(IBindStatusCallback* iface)
73 {
74 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
75
76 return InterlockedIncrement(&This->ref);
77 }
78
79 static ULONG WINAPI
80 dlRelease(IBindStatusCallback* iface)
81 {
82 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
83 DWORD ref = InterlockedDecrement(&This->ref);
84
85 if( !ref )
86 {
87 DestroyWindow( This->hDialog );
88 HeapFree(GetProcessHeap(), 0, This);
89 }
90
91 return ref;
92 }
93
94 static HRESULT WINAPI
95 dlOnStartBinding(IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib)
96 {
97 DPRINT1("OnStartBinding not implemented\n");
98
99 return S_OK;
100 }
101
102 static HRESULT WINAPI
103 dlGetPriority(IBindStatusCallback* iface, LONG* pnPriority)
104 {
105 DPRINT1("GetPriority not implemented\n");
106
107 return S_OK;
108 }
109
110 static HRESULT WINAPI
111 dlOnLowResource( IBindStatusCallback* iface, DWORD reserved)
112 {
113 DPRINT1("OnLowResource not implemented\n");
114
115 return S_OK;
116 }
117
118 static HRESULT WINAPI
119 dlOnProgress(IBindStatusCallback* iface, ULONG ulProgress,
120 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
121 {
122 IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
123 HWND Item;
124 LONG r;
125 WCHAR OldText[100];
126
127 Item = GetDlgItem(This->hDialog, IDC_PROGRESS);
128 if (NULL != Item && 0 != ulProgressMax)
129 {
130 SendMessageW(Item, PBM_SETPOS, (ulProgress * 100) / ulProgressMax, 0);
131 }
132
133 Item = GetDlgItem(This->hDialog, IDC_STATUS);
134 if (NULL != Item && NULL != szStatusText)
135 {
136 SendMessageW(Item, WM_GETTEXT, sizeof(OldText) / sizeof(OldText[0]),
137 (LPARAM) OldText);
138 if (sizeof(OldText) / sizeof(OldText[0]) - 1 <= wcslen(OldText) || 0 != wcscmp(OldText, szStatusText))
139 {
140 SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) szStatusText);
141 }
142 }
143
144 SetLastError(0);
145 r = GetWindowLongPtrW(This->hDialog, GWLP_USERDATA);
146 if (0 != r || 0 != GetLastError())
147 {
148 *This->pbCancelled = TRUE;
149 DPRINT("Cancelled\n");
150 return E_ABORT;
151 }
152
153 return S_OK;
154 }
155
156 static HRESULT WINAPI
157 dlOnStopBinding(IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError)
158 {
159 DPRINT1("OnStopBinding not implemented\n");
160
161 return S_OK;
162 }
163
164 static HRESULT WINAPI
165 dlGetBindInfo(IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo)
166 {
167 DPRINT1("GetBindInfo not implemented\n");
168
169 return S_OK;
170 }
171
172 static HRESULT WINAPI
173 dlOnDataAvailable(IBindStatusCallback* iface, DWORD grfBSCF,
174 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
175 {
176 DPRINT1("OnDataAvailable implemented\n");
177
178 return S_OK;
179 }
180
181 static HRESULT WINAPI
182 dlOnObjectAvailable(IBindStatusCallback* iface, REFIID riid, IUnknown* punk)
183 {
184 DPRINT1("OnObjectAvailable implemented\n");
185
186 return S_OK;
187 }
188
189 static const IBindStatusCallbackVtbl dlVtbl =
190 {
191 dlQueryInterface,
192 dlAddRef,
193 dlRelease,
194 dlOnStartBinding,
195 dlGetPriority,
196 dlOnLowResource,
197 dlOnProgress,
198 dlOnStopBinding,
199 dlGetBindInfo,
200 dlOnDataAvailable,
201 dlOnObjectAvailable
202 };
203
204 static IBindStatusCallback*
205 CreateDl(HWND Dlg, BOOL *pbCancelled)
206 {
207 IBindStatusCallbackImpl *This;
208
209 This = HeapAlloc(GetProcessHeap(), 0, sizeof(IBindStatusCallbackImpl));
210 This->vtbl = &dlVtbl;
211 This->ref = 1;
212 This->hDialog = Dlg;
213 This->pbCancelled = pbCancelled;
214
215 return (IBindStatusCallback*) This;
216 }
217
218 static DWORD WINAPI
219 ThreadFunc(LPVOID Context)
220 {
221 //static const WCHAR szUrl[] = DownloadUrl;
222 IBindStatusCallback *dl;
223 WCHAR path[MAX_PATH];
224 LPWSTR p;
225 STARTUPINFOW si;
226 PROCESS_INFORMATION pi;
227 HWND Dlg = (HWND) Context;
228 DWORD r;
229 BOOL bCancelled = FALSE;
230 BOOL bTempfile = FALSE;
231 HKEY hKey;
232
233 /* built the path for the download */
234 p = wcsrchr(SelectedApplication->Location, L'/');
235 if (NULL == p)
236 {
237 goto end;
238 }
239 if (RegOpenKey(HKEY_LOCAL_MACHINE,
240 TEXT("Software\\ReactOS\\Download!"),
241 &hKey) != ERROR_SUCCESS)
242 {
243 goto end;
244 }
245
246 DWORD dwSize = MAX_PATH;
247 if (RegQueryValueEx(hKey,
248 L"DownloadFolder",
249 NULL,
250 NULL,
251 (LPBYTE)&path,
252 &dwSize) != ERROR_SUCCESS)
253 {
254 goto end;
255 }
256
257 if (GetFileAttributes(path) == 0xFFFFFFFF)
258 if (!CreateDirectory((LPCTSTR)path,NULL))
259 {
260 goto end;
261 }
262 wcscat(path, L"\\");
263 wcscat(path, p + 1);
264
265 /* download it */
266 bTempfile = TRUE;
267 dl = CreateDl(Context, &bCancelled);
268 r = URLDownloadToFileW(NULL, SelectedApplication->Location, path, 0, dl);
269 if (NULL != dl)
270 {
271 IBindStatusCallback_Release(dl);
272 }
273 if (S_OK != r)
274 {
275 MessageBoxW(0,Strings[IDS_DOWNLOAD_ERROR],0,0);
276 goto end;
277 }
278 else if (bCancelled)
279 {
280 goto end;
281 }
282 ShowWindow(Dlg, SW_HIDE);
283
284 /* run it */
285 memset(&si, 0, sizeof(si));
286 si.cb = sizeof(si);
287 r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
288 if (0 == r)
289 {
290 goto end;
291 }
292 CloseHandle(pi.hThread);
293 WaitForSingleObject(pi.hProcess, INFINITE);
294 CloseHandle(pi.hProcess);
295
296 end:
297 if (bTempfile)
298 {
299 DWORD dwSize = sizeof(DWORD);
300 DWORD dwValue, dwType = REG_DWORD;
301 if (RegQueryValueEx(hKey,
302 L"DeleteInstaller",
303 NULL,
304 &dwType,
305 (LPBYTE)&dwValue,
306 &dwSize) == ERROR_SUCCESS)
307 if (dwValue == 0x1)
308 DeleteFileW(path);
309 RegCloseKey(hKey);
310 }
311 EndDialog(Dlg, 0);
312 return 0;
313 }
314
315 INT_PTR CALLBACK
316 DownloadProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
317 {
318 HANDLE Thread;
319 DWORD ThreadId;
320 HWND Item;
321
322 switch (Msg)
323 {
324 case WM_INITDIALOG:/*
325 Icon = LoadIconW((HINSTANCE) GetWindowLongPtr(Dlg, GWLP_HINSTANCE),
326 MAKEINTRESOURCEW(IDI_ICON_MAIN));
327 if (NULL != Icon)
328 {
329 SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) Icon);
330 SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) Icon);
331 }*/
332 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0);
333 Item = GetDlgItem(Dlg, IDC_PROGRESS);
334 if (NULL != Item)
335 {
336 SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0,100));
337 SendMessageW(Item, PBM_SETPOS, 0, 0);
338 }/*
339 Item = GetDlgItem(Dlg, IDC_REMOVE);
340 if (NULL != Item)
341 {
342 if (GetShortcutName(ShortcutName) &&
343 INVALID_FILE_ATTRIBUTES != GetFileAttributesW(ShortcutName))
344 {
345 SendMessageW(Item, BM_SETCHECK, BST_CHECKED, 0);
346 }
347 else
348 {
349 SendMessageW(Item, BM_SETCHECK, BST_UNCHECKED, 0);
350 ShowWindow(Item, SW_HIDE);
351 }
352 }*/
353 Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
354 if (NULL == Thread)
355 {
356 return FALSE;
357 }
358 CloseHandle(Thread);
359 return TRUE;
360
361 case WM_COMMAND:
362 if (wParam == IDCANCEL)
363 {
364 SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
365 PostMessage(Dlg, WM_CLOSE, 0, 0);
366 }
367 return FALSE;
368
369 case WM_CLOSE:
370 EndDialog(Dlg, 0);
371 return TRUE;
372
373 default:
374 return FALSE;
375 }
376 }