Sync with trunk (48237)
[reactos.git] / base / applications / downloader / main.c
1 /* PROJECT: ReactOS Downloader
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/downloader/xml.c
4 * PURPOSE: Main program
5 * PROGRAMMERS: Maarten Bosma, Lester Kortenhoeven, Dmitry Chapyshev
6 */
7
8 #include <windows.h>
9 #include <commctrl.h>
10 #include <richedit.h>
11 #include <tchar.h>
12 #include <stdio.h>
13 #include <shlwapi.h>
14 #include <shlobj.h>
15 #include "resources.h"
16 #include "structures.h"
17
18 HWND hwnd, hCategories, hApps, hDownloadButton, hUninstallButton, hUpdateButton, hHelpButton, hProfButton;
19 HBITMAP hLogo, hUnderline;
20 WCHAR* DescriptionHeadline = L"";
21 WCHAR* DescriptionText = L"";
22 WCHAR ApplicationText[700];
23
24 struct Category Root;
25 struct Application* SelectedApplication;
26
27 INT_PTR CALLBACK DownloadProc (HWND, UINT, WPARAM, LPARAM);
28 BOOL ProcessXML (const char* filename, struct Category* Root);
29 VOID FreeTree (struct Category* Node);
30 WCHAR Strings [STRING_COUNT][MAX_STRING_LENGHT];
31
32
33 BOOL
34 getUninstaller(WCHAR* RegName, WCHAR* Uninstaller) {
35 HKEY hKey1;
36 HKEY hKey2;
37 DWORD Type = 0;
38 DWORD Size = MAX_PATH;
39 WCHAR Value[MAX_PATH];
40 WCHAR KeyName[MAX_PATH];
41 LONG i = 0;
42
43 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",0,KEY_READ,&hKey1) == ERROR_SUCCESS) {
44 while (RegEnumKeyExW(hKey1,i,KeyName,&Size,NULL,NULL,NULL,NULL) == ERROR_SUCCESS) {
45 ++i;
46 RegOpenKeyExW(hKey1,KeyName,0,KEY_READ,&hKey2);
47 Size = MAX_PATH;
48 if (RegQueryValueExW(hKey2,L"DisplayName",0,&Type,(LPBYTE)Value,&Size) == ERROR_SUCCESS) {
49 Size = MAX_PATH;
50 if (StrCmpW(Value,RegName) == 0) {
51 if (RegQueryValueExW(hKey2,L"UninstallString",0,&Type,(LPBYTE)Uninstaller,&Size) == ERROR_SUCCESS) {
52 RegCloseKey(hKey2);
53 RegCloseKey(hKey1);
54 return TRUE;
55 } else {
56 RegCloseKey(hKey2);
57 RegCloseKey(hKey1);
58 return FALSE;
59 }
60 }
61 }
62 RegCloseKey(hKey2);
63 Size = MAX_PATH;
64 }
65 RegCloseKey(hKey1);
66 }
67 return FALSE;
68 }
69
70 void
71 ShowMessage (WCHAR* title, WCHAR* message)
72 {
73 DescriptionHeadline = title;
74 DescriptionText = message;
75 InvalidateRect(hwnd,NULL,TRUE);
76 UpdateWindow(hwnd);
77 }
78
79 void
80 AddItems(HWND hwnd, struct Category* Category, struct Category* Parent)
81 {
82 TV_INSERTSTRUCTW Insert;
83
84 Insert.item.lParam = (LPARAM)Category;
85 Insert.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;;
86 Insert.item.pszText = Category->Name;
87 Insert.item.cchTextMax = lstrlenW(Category->Name);
88 Insert.item.iImage = Category->Icon;
89 Insert.item.iSelectedImage = Category->Icon;
90 Insert.hInsertAfter = TVI_LAST;
91 Insert.hParent = Category->Parent ? Category->Parent->TreeviewItem : TVI_ROOT;
92
93 Category->TreeviewItem = (HTREEITEM)SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert);
94
95 if(Category->Next)
96 AddItems (hwnd,Category->Next,Parent);
97
98 if(Category->Children)
99 AddItems (hwnd,Category->Children,Category);
100 }
101
102 void
103 CategoryChoosen(HWND hwnd, struct Category* Category)
104 {
105 struct Application* CurrentApplication;
106 TV_INSERTSTRUCTW Insert;
107 WCHAR Uninstaller[200];
108 SelectedApplication = NULL;
109
110 if(Category->Children && !Category->Apps)
111 ShowMessage(Category->Name, Strings[IDS_CHOOSE_SUB]);
112 else if(!Category->Children && Category->Apps)
113 ShowMessage(Category->Name, Strings[IDS_CHOOSE_APP]);
114 else if(Category->Children && Category->Apps)
115 ShowMessage(Category->Name, Strings[IDS_CHOOSE_BOTH]);
116 else
117 ShowMessage(Category->Name, Strings[IDS_NO_APPS]);
118
119 (void)TreeView_DeleteItem(hwnd, TVI_ROOT);
120 (void)TreeView_DeleteItem(hwnd, TVI_ROOT); // Delete twice to bypass bug in windows
121
122 Insert.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE;
123 Insert.hInsertAfter = TVI_LAST;
124 Insert.hParent = TVI_ROOT;
125
126 CurrentApplication = Category->Apps;
127 while(CurrentApplication)
128 {
129 Insert.item.lParam = (LPARAM)CurrentApplication;
130 Insert.item.pszText = CurrentApplication->Name;
131 Insert.item.cchTextMax = lstrlenW(CurrentApplication->Name);
132 Insert.item.iImage = 10;
133 if(StrCmpW(CurrentApplication->RegName,L"")) {
134 if(getUninstaller(CurrentApplication->RegName, Uninstaller))
135 Insert.item.iImage = 9;
136 }
137 SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert);
138 CurrentApplication = CurrentApplication->Next;
139 }
140 }
141
142 BOOL CreateToolTip(HWND hwndTool, HWND hDlg, WCHAR* pText)
143 {
144 HWND hwndTip;
145 TOOLINFO toolInfo;
146
147 if (!hwndTool || !hDlg || !pText)
148 return FALSE;
149
150 hwndTip = CreateWindowExW(0, TOOLTIPS_CLASS, NULL,
151 WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON,
152 CW_USEDEFAULT, CW_USEDEFAULT,
153 CW_USEDEFAULT, CW_USEDEFAULT,
154 hDlg, NULL,
155 GetModuleHandle(NULL), NULL);
156 if (!hwndTip)
157 return FALSE;
158
159 ZeroMemory(&toolInfo, sizeof(TOOLINFO));
160 toolInfo.cbSize = sizeof(toolInfo);
161 toolInfo.hwnd = hDlg;
162 toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
163 toolInfo.uId = (UINT_PTR)hwndTool;
164 toolInfo.lpszText = pText;
165 SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
166
167 return TRUE;
168 }
169
170 BOOL
171 SetupControls (HWND hwnd)
172 {
173 TV_INSERTSTRUCTW Insert = {0};
174 HIMAGELIST hImageList;
175 HINSTANCE hInstance = GetModuleHandle(NULL);
176 WCHAR Cats[MAX_STRING_LENGHT], Apps[MAX_STRING_LENGHT];
177 WCHAR Tooltip1[MAX_STRING_LENGHT], Tooltip2[MAX_STRING_LENGHT], Tooltip3[MAX_STRING_LENGHT];
178 char Buf[MAX_PATH];
179
180 // Getting downloader.xml path
181 if(!GetSystemDirectoryA(Buf,sizeof(Buf))) return FALSE;
182 strcat(Buf, "\\downloader.xml");
183
184 // Parse the XML file
185 if (!ProcessXML(Buf, &Root))
186 return FALSE;
187
188 LoadStringW(hInstance, IDS_CATS_TITLE, Cats, MAX_STRING_LENGHT);
189 LoadStringW(hInstance, IDS_APPS_TITLE, Apps, MAX_STRING_LENGHT);
190
191 // Set up the controls
192 hCategories = CreateWindowExW(0, WC_TREEVIEWW, Cats,
193 WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS,
194 0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
195
196 hApps = CreateWindowExW(0, WC_TREEVIEWW, Apps,
197 WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS,
198 0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
199
200 hLogo = LoadBitmap(GetModuleHandle(NULL),
201 MAKEINTRESOURCE(IDB_LOGO));
202 hUnderline = LoadBitmap(GetModuleHandle(NULL),
203 MAKEINTRESOURCE(IDB_UNDERLINE));
204
205 hHelpButton = CreateWindowW(L"Button", L"",
206 WS_CHILD | WS_VISIBLE | BS_ICON,
207 550, 10, 40, 40,
208 hwnd, 0, hInstance, NULL);
209 LoadString(hInstance, TTT_HELPBUTTON, Tooltip1, MAX_STRING_LENGHT);
210 CreateToolTip(hHelpButton, hwnd, Tooltip1);
211
212 hUpdateButton = CreateWindowW(L"Button", L"",
213 WS_CHILD | WS_VISIBLE | BS_ICON,
214 450, 10, 40, 40,
215 hwnd, 0, hInstance, NULL);
216 LoadString(hInstance, TTT_UPDATEBUTTON, Tooltip2, MAX_STRING_LENGHT);
217 CreateToolTip(hUpdateButton, hwnd, Tooltip2);
218
219 hProfButton = CreateWindowW(L"Button", L"",
220 WS_CHILD | WS_VISIBLE | BS_ICON,
221 500, 10, 40, 40,
222 hwnd, 0, hInstance, NULL);
223 LoadString(hInstance, TTT_PROFBUTTON, Tooltip3, MAX_STRING_LENGHT);
224 CreateToolTip(hProfButton, hwnd, Tooltip3);
225
226 hDownloadButton = CreateWindowW(L"Button", L"",
227 WS_CHILD | WS_VISIBLE | BS_BITMAP,
228 330, 505, 140, 33,
229 hwnd, 0, hInstance, NULL);
230
231 hUninstallButton = CreateWindowW(L"Button", L"",
232 WS_CHILD | WS_VISIBLE | BS_BITMAP,
233 260, 505, 140, 33,
234 hwnd, 0, hInstance, NULL);
235
236 SendMessageW(hProfButton,
237 BM_SETIMAGE,
238 (WPARAM)IMAGE_ICON,
239 (LPARAM)(HANDLE)LoadIcon(hInstance,MAKEINTRESOURCE(IDI_PROF)));
240 SendMessageW(hHelpButton,
241 BM_SETIMAGE,
242 (WPARAM)IMAGE_ICON,
243 (LPARAM)(HANDLE)LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELP)));
244 SendMessageW(hUpdateButton,
245 BM_SETIMAGE,
246 (WPARAM)IMAGE_ICON,
247 (LPARAM)(HANDLE)LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UPDATE)));
248 SendMessageW(hDownloadButton,
249 BM_SETIMAGE,
250 (WPARAM)IMAGE_BITMAP,
251 (LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DOWNLOAD)));
252 SendMessageW(hUninstallButton,
253 BM_SETIMAGE,
254 (WPARAM)IMAGE_BITMAP,
255 (LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_UNINSTALL)));
256 ShowWindow(hUninstallButton, SW_HIDE);
257
258 // Set deflaut entry for hApps
259 Insert.item.mask = TVIF_TEXT|TVIF_IMAGE;
260 Insert.item.pszText = Strings[IDS_CHOOSE_CATEGORY];
261 Insert.item.cchTextMax = lstrlenW(Strings[IDS_CHOOSE_CATEGORY]);
262 Insert.item.iImage = 0;
263 SendMessage(hApps, TVM_INSERTITEM, 0, (LPARAM)&Insert);
264
265 // Create Tree Icons
266 hImageList = ImageList_Create(16, 16, ILC_COLORDDB, 1, 1);
267 SendMessageW(hCategories, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList);
268 SendMessageW(hApps, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList);
269
270 ImageList_Add(hImageList,
271 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_0)), NULL);
272 ImageList_Add(hImageList,
273 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_1)), NULL);
274 ImageList_Add(hImageList,
275 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_2)), NULL);
276 ImageList_Add(hImageList,
277 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_3)), NULL);
278 ImageList_Add(hImageList,
279 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_4)), NULL);
280 ImageList_Add(hImageList,
281 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_5)), NULL);
282 ImageList_Add(hImageList,
283 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_6)), NULL);
284 ImageList_Add(hImageList,
285 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_7)), NULL);
286 ImageList_Add(hImageList,
287 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_8)), NULL);
288 ImageList_Add(hImageList,
289 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_9)), NULL);
290 ImageList_Add(hImageList,
291 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_10)), NULL);
292 ImageList_Add(hImageList,
293 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_11)), NULL);
294 ImageList_Add(hImageList,
295 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_12)), NULL);
296 ImageList_Add(hImageList,
297 LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_13)), NULL);
298
299 // Fill the TreeViews
300 AddItems (hCategories, Root.Children, NULL);
301
302 return TRUE;
303 }
304
305 static void
306 ResizeControl (HWND hwnd, int x1, int y1, int x2, int y2)
307 {
308 // Make resizing a little easier
309 MoveWindow(hwnd, x1, y1, x2-x1, y2-y1, TRUE);
310 }
311
312 static void
313 DrawBitmap (HDC hdc, int x, int y, HBITMAP hBmp)
314 {
315 BITMAP bm;
316 HDC hdcMem = CreateCompatibleDC(hdc);
317
318 SelectObject(hdcMem, hBmp);
319 GetObject(hBmp, sizeof(bm), &bm);
320 TransparentBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, 0xFFFFFF);
321
322 DeleteDC(hdcMem);
323 }
324
325 static void
326 DrawDescription (HDC hdc, RECT DescriptionRect)
327 {
328 int i;
329 HFONT Font;
330 RECT Rect = {DescriptionRect.left+5, DescriptionRect.top+3, DescriptionRect.right-2, DescriptionRect.top+22};
331
332 // Backgroud
333 Rectangle(hdc, DescriptionRect.left, DescriptionRect.top, DescriptionRect.right, DescriptionRect.bottom);
334
335 // Underline
336 for (i=DescriptionRect.left+1;i<DescriptionRect.right-1;i++)
337 DrawBitmap(hdc, i, DescriptionRect.top+22, hUnderline); // less code then stretching ;)
338
339 // Headline
340 Font = CreateFont(-16 , 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
341 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Arial");
342 SelectObject(hdc, Font);
343 DrawTextW(hdc, DescriptionHeadline, lstrlenW(DescriptionHeadline), &Rect, DT_SINGLELINE|DT_NOPREFIX);
344 DeleteObject(Font);
345
346 // Description
347 Font = CreateFont(-13 , 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
348 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Arial");
349 SelectObject(hdc, Font);
350 Rect.top += 50;
351 Rect.bottom = DescriptionRect.bottom-2;
352 DrawTextW(hdc, DescriptionText, lstrlenW(DescriptionText), &Rect, DT_WORDBREAK|DT_NOPREFIX); // ToDo: Call TabbedTextOut to draw a nice table
353 DeleteObject(Font);
354
355 }
356
357 void showUninstaller() {
358 int Split_Vertical = 200;
359 RECT Rect;
360
361 GetClientRect(hwnd,&Rect);
362 ShowWindow(hUninstallButton,SW_SHOW);
363 MoveWindow(hDownloadButton,(Split_Vertical+Rect.right-Rect.left)/2,Rect.bottom-Rect.top-45,140,35,TRUE);;
364 }
365
366 void hideUninstaller() {
367 int Split_Vertical = 200;
368 RECT Rect;
369
370 GetClientRect(hwnd,&Rect);
371 ShowWindow(hUninstallButton,SW_HIDE);
372 MoveWindow(hDownloadButton,(Split_Vertical+Rect.right-Rect.left)/2-70,Rect.bottom-Rect.top-45,140,35,TRUE);
373 }
374
375 void startUninstaller(WCHAR* Uninstaller) {
376 STARTUPINFOW si;
377 PROCESS_INFORMATION pi;
378
379 memset(&si, 0, sizeof(si));
380 si.cb = sizeof(si);
381 CreateProcessW(NULL,Uninstaller,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
382 CloseHandle(pi.hThread);
383 // WaitForSingleObject(pi.hProcess, INFINITE); // If you want to wait for the Unistaller
384 CloseHandle(pi.hProcess);
385 hideUninstaller();
386 }
387
388 BOOL
389 SaveSettings(HWND hwnd)
390 {
391 HKEY hKey;
392 TCHAR szBuf[MAX_PATH];
393 DWORD dwValue;
394
395 if (RegOpenKey(HKEY_LOCAL_MACHINE,
396 TEXT("Software\\ReactOS\\Downloader"),
397 &hKey) != ERROR_SUCCESS)
398 return FALSE;
399
400 GetDlgItemText(hwnd, IDC_DOWNLOAD_FOLDER_EDIT, szBuf, sizeof(szBuf) / sizeof(TCHAR));
401 if (GetFileAttributes(szBuf) == 0xFFFFFFFF)
402 if (!CreateDirectory((LPCTSTR)szBuf,NULL))
403 {
404 LoadString(GetModuleHandle(NULL), IDS_UNABLECREATE_FOLDER, szBuf, sizeof(szBuf) / sizeof(TCHAR));
405 MessageBox(hwnd, (LPCTSTR)szBuf, NULL, MB_ICONSTOP);
406 return FALSE;
407 }
408 if (RegSetValueEx(hKey,
409 L"DownloadFolder",
410 0,
411 REG_SZ,
412 (LPBYTE)szBuf,
413 (DWORD)(sizeof(szBuf) / sizeof(TCHAR))))
414 return FALSE;
415
416 GetDlgItemText(hwnd, IDC_UPDATE_SERVER_EDIT, szBuf, sizeof(szBuf) / sizeof(TCHAR));
417 if (RegSetValueEx(hKey,
418 L"UpdateServer",
419 0,
420 REG_SZ,
421 (LPBYTE)szBuf,
422 (DWORD)(sizeof(szBuf) / sizeof(TCHAR))))
423 return FALSE;
424
425 if (SendDlgItemMessage(hwnd, IDC_DELINST_FILES_CHECKBOX, BM_GETCHECK, 0, 0) == BST_CHECKED)
426 dwValue = 0x1;
427 else
428 dwValue = 0x0;
429 if (RegSetValueEx(hKey,
430 L"DeleteInstaller",
431 0,
432 REG_DWORD,
433 (LPBYTE)&dwValue,
434 sizeof(DWORD)))
435 return FALSE;
436
437 RegCloseKey(hKey);
438
439 return TRUE;
440 }
441
442 BOOL
443 InitProfDlg(HWND hwnd)
444 {
445 HKEY hKey;
446 TCHAR Buf[MAX_PATH];
447 DWORD dwDisp, dwSize;
448 DWORD dwValue, dwType = REG_DWORD;
449
450 if (RegOpenKey(HKEY_LOCAL_MACHINE,
451 TEXT("Software\\ReactOS\\Downloader"),
452 &hKey) != ERROR_SUCCESS)
453 {
454 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, L"Software\\ReactOS\\Downloader",
455 0, NULL, REG_OPTION_NON_VOLATILE,
456 KEY_WRITE, NULL, &hKey, &dwDisp))
457 {
458 LoadString(GetModuleHandle(NULL), IDS_NOTCREATE_REGKEY, Buf, sizeof(Buf) / sizeof(TCHAR));
459 MessageBox(hwnd, (LPCTSTR)Buf, NULL, MB_ICONSTOP);
460 return FALSE;
461 }
462 }
463
464 dwSize = MAX_PATH;
465 if (RegQueryValueEx(hKey,
466 L"DownloadFolder",
467 NULL,
468 NULL,
469 (LPBYTE)&Buf,
470 &dwSize) == ERROR_SUCCESS)
471 {
472 SetDlgItemText(hwnd, IDC_DOWNLOAD_FOLDER_EDIT, Buf);
473 }
474 else
475 {
476 TCHAR DPath[256];
477 int i;
478
479 if (!GetWindowsDirectory(Buf, sizeof(Buf) / sizeof(TCHAR))) return FALSE;
480
481 for (i = 0; i < 4; i++)
482 {
483 if (i == 3)
484 {
485 DPath[i] = '\0';
486 break;
487 }
488 DPath[i] = Buf[i];
489 }
490 LoadString(GetModuleHandle(NULL), IDS_DOWNLOAD_FOLDER, Buf, sizeof(Buf) / sizeof(TCHAR));
491 lstrcat((LPTSTR)DPath, Buf);
492 if (RegSetValueEx(hKey,
493 L"DownloadFolder",
494 0,
495 REG_SZ,
496 (LPBYTE)DPath,
497 (DWORD)(sizeof(DPath) / sizeof(TCHAR))))
498 return FALSE;
499 else
500 {
501 if (GetFileAttributes(DPath) == 0xFFFFFFFF)
502 if (!CreateDirectory((LPCTSTR)DPath,NULL)) return FALSE;
503 SetDlgItemText(hwnd, IDC_DOWNLOAD_FOLDER_EDIT, DPath);
504 }
505 }
506
507 dwSize = MAX_PATH;
508 if (RegQueryValueEx(hKey,
509 L"UpdateServer",
510 NULL,
511 NULL,
512 (LPBYTE)&Buf,
513 &dwSize) == ERROR_SUCCESS)
514 {
515 SetDlgItemText(hwnd, IDC_UPDATE_SERVER_EDIT, Buf);
516 }
517 else
518 {
519 LoadString(GetModuleHandle(NULL), IDS_UPDATE_URL, Buf, sizeof(Buf) / sizeof(TCHAR));
520 if (RegSetValueEx(hKey,
521 L"UpdateServer",
522 0,
523 REG_SZ,
524 (LPBYTE)Buf,
525 (DWORD)(sizeof(Buf) / sizeof(TCHAR))))
526 return FALSE;
527 else
528 {
529 SetDlgItemText(hwnd, IDC_UPDATE_SERVER_EDIT, Buf);
530 }
531 }
532
533 dwSize = sizeof(DWORD);
534 if (RegQueryValueEx(hKey,
535 L"DeleteInstaller",
536 NULL,
537 &dwType,
538 (LPBYTE)&dwValue,
539 &dwSize) == ERROR_SUCCESS)
540 {
541 if (dwValue == 0x1)
542 SendDlgItemMessage(hwnd, IDC_DELINST_FILES_CHECKBOX, BM_SETCHECK, 1, 1);
543 }
544 else
545 {
546 dwValue = 0x0;
547 if (RegSetValueEx(hKey,
548 L"DeleteInstaller",
549 0,
550 REG_DWORD,
551 (LPBYTE)&dwValue,
552 sizeof(DWORD)))
553 return FALSE;
554 }
555
556 RegCloseKey(hKey);
557
558 return TRUE;
559 }
560
561 BOOL
562 ChooseFolder(HWND hwnd)
563 {
564 BROWSEINFO fi;
565 LPCITEMIDLIST lpItemList;
566 TCHAR szPath[MAX_PATH],Buf[256];
567
568 ZeroMemory(&fi, sizeof(BROWSEINFO));
569 fi.hwndOwner = hwnd;
570 LoadString(GetModuleHandle(NULL), IDS_CHOOSE_FOLDER, Buf, sizeof(Buf) / sizeof(TCHAR));
571 fi.lpszTitle = (LPCTSTR)Buf;
572 fi.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_BROWSEFORCOMPUTER | BIF_NEWDIALOGSTYLE;
573 fi.lpfn = NULL;
574 fi.lParam = -1;
575 fi.iImage = 0;
576
577 if(!(lpItemList = SHBrowseForFolder(&fi))) return FALSE;
578 SHGetPathFromIDList(lpItemList, szPath);
579
580 if (_tcslen(szPath) == 0) return FALSE;
581 SetDlgItemText(hwnd, IDC_DOWNLOAD_FOLDER_EDIT, szPath);
582
583 return TRUE;
584 }
585
586 INT_PTR CALLBACK
587 ProfDlgProc(HWND hDlg,
588 UINT message,
589 WPARAM wParam,
590 LPARAM lParam)
591 {
592 static HICON hIcon;
593 UNREFERENCED_PARAMETER(lParam);
594
595 switch (message)
596 {
597 case WM_INITDIALOG:
598 {
599 hIcon = LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_MAIN),IMAGE_ICON,16,16,0);
600 SendMessage(hDlg,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
601 InitProfDlg(hDlg);
602 }
603 break;
604
605 case WM_COMMAND:
606 {
607 switch (wParam)
608 {
609 case IDC_CHOOSE_BUTTON:
610 ChooseFolder(hDlg);
611 break;
612 case IDOK:
613 {
614 SaveSettings(hDlg);
615 DestroyIcon(hIcon);
616 EndDialog(hDlg,LOWORD(wParam));
617 return TRUE;
618 }
619 break;
620 case IDCANCEL:
621 {
622 DestroyIcon(hIcon);
623 EndDialog(hDlg,LOWORD(wParam));
624 return TRUE;
625 }
626 break;
627 }
628 }
629 break;
630 }
631
632 return FALSE;
633 }
634
635 BOOL IsApplicationInstalled(struct Application* App)
636 {
637 WCHAR Uninstaller[200];
638 if(StrCmpW(App->RegName, L"")) {
639 if(getUninstaller(App->RegName, Uninstaller)) {
640 return TRUE;
641 }
642 }
643 return FALSE;
644 }
645
646 struct Application* GetDependency(const WCHAR* Dependency)
647 {
648 struct Category* Category = Root.Children;
649
650 while (Category->Next)
651 {
652 while (Category->Apps)
653 {
654 if(StrCmpW(Category->Apps->RegName, Dependency) == 0)
655 return Category->Apps;
656 Category->Apps = Category->Apps->Next;
657 }
658 Category = Category->Next;
659 }
660 return NULL;
661 }
662
663 LRESULT CALLBACK
664 WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
665 {
666 static RECT DescriptionRect;
667 struct Application* AppToInstall;
668 WCHAR InstallDep[260];
669 WCHAR InstallDepBuffer[260];
670 WCHAR Title[260];
671
672 switch (Message)
673 {
674 case WM_CREATE:
675 {
676 if(!SetupControls(hwnd))
677 return -1;
678 ShowMessage(Strings[IDS_WELCOME_TITLE], Strings[IDS_WELCOME]);
679 }
680 break;
681
682 case WM_PAINT:
683 {
684 PAINTSTRUCT ps;
685 HDC hdc = BeginPaint(hwnd, &ps);
686 HDC BackbufferHdc = CreateCompatibleDC(hdc);
687 HBITMAP BackbufferBmp = CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
688 SelectObject(BackbufferHdc, BackbufferBmp);
689
690 FillRect(BackbufferHdc, &ps.rcPaint, CreateSolidBrush(RGB(235,235,235)));
691 DrawBitmap(BackbufferHdc, 10, 12, hLogo);
692 DrawDescription(BackbufferHdc, DescriptionRect);
693
694 BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, BackbufferHdc, 0, 0, SRCCOPY);
695 DeleteObject(BackbufferBmp);
696 DeleteDC(BackbufferHdc);
697 EndPaint(hwnd, &ps);
698 }
699 break;
700
701 case WM_COMMAND:
702 {
703 if(HIWORD(wParam) == BN_CLICKED)
704 {
705 if (lParam == (LPARAM)hProfButton)
706 {
707 DialogBox(GetModuleHandle(NULL),
708 MAKEINTRESOURCE(IDD_PROF),
709 hwnd,
710 ProfDlgProc);
711 }
712 if (lParam == (LPARAM)hDownloadButton)
713 {
714 if(SelectedApplication)
715 {
716 /* install dependencies */
717 if(StrCmpW(SelectedApplication->Depends, L""))
718 {
719 AppToInstall = SelectedApplication;
720 SelectedApplication = GetDependency(SelectedApplication->Depends);
721 if (SelectedApplication)
722 if (!IsApplicationInstalled(SelectedApplication))
723 {
724 LoadString(GetModuleHandle(NULL), IDS_INSTALL_DEP, InstallDep, sizeof(InstallDep) / sizeof(WCHAR));
725 LoadString(GetModuleHandle(NULL), IDS_WINDOW_TITLE, Title, sizeof(Title) / sizeof(WCHAR));
726 _snwprintf(InstallDepBuffer, sizeof(InstallDepBuffer) / sizeof(WCHAR), InstallDep, SelectedApplication->Name, AppToInstall->Name, SelectedApplication->Name);
727 if (MessageBox(hwnd, InstallDepBuffer, Title, MB_YESNO | MB_ICONINFORMATION) == IDYES)
728 {
729 DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc);
730 }
731 }
732 SelectedApplication = AppToInstall;
733 }
734
735 /* download and install the app */
736 DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc);
737
738 /* install req. hacks to get it working */
739 if(StrCmpW(SelectedApplication->PostInstallAction, L""))
740 {
741 AppToInstall = SelectedApplication;
742 CopyMemory(SelectedApplication->Location, SelectedApplication->PostInstallAction, sizeof(SelectedApplication->Location));
743 DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc);
744 SelectedApplication = AppToInstall;
745 }
746 }
747 else
748 ShowMessage(Strings[IDS_NO_APP_TITLE], Strings[IDS_NO_APP]);
749 }
750 else if (lParam == (LPARAM)hUninstallButton)
751 {
752 if(SelectedApplication)
753 {
754 WCHAR Uninstaller[200];
755 if(StrCmpW(SelectedApplication->RegName, L"")) {
756 if(getUninstaller(SelectedApplication->RegName, Uninstaller))
757 startUninstaller(Uninstaller);
758 }
759 }
760 }
761 else if (lParam == (LPARAM)hUpdateButton)
762 {
763 ShowMessage(Strings[IDS_UPDATE_TITLE], Strings[IDS_UPDATE]);
764 }
765 else if (lParam == (LPARAM)hHelpButton)
766 {
767 ShowMessage(Strings[IDS_HELP_TITLE], Strings[IDS_HELP]);
768 }
769 }
770 }
771 break;
772
773 case WM_NOTIFY:
774 {
775 LPNMHDR data = (LPNMHDR)lParam;
776 WCHAR Uninstaller[200];
777
778 if(data->code == TVN_SELCHANGED)
779 {
780 BOOL bShowUninstaller = FALSE;
781 if(data->hwndFrom == hCategories)
782 {
783 struct Category* Category = (struct Category*) ((LPNMTREEVIEW)lParam)->itemNew.lParam;
784 CategoryChoosen (hApps, Category);
785 }
786 else if(data->hwndFrom == hApps)
787 {
788 SelectedApplication = (struct Application*) ((LPNMTREEVIEW)lParam)->itemNew.lParam;
789 if(SelectedApplication)
790 {
791 ApplicationText[0]=L'\0';
792 if(StrCmpW(SelectedApplication->Version, L"")) {
793 StrCatW(ApplicationText, Strings[IDS_VERSION]);
794 StrCatW(ApplicationText, SelectedApplication->Version);
795 StrCatW(ApplicationText, L"\n");
796 }
797 if(StrCmpW(SelectedApplication->Licence, L"")) {
798 StrCatW(ApplicationText, Strings[IDS_LICENCE]);
799 StrCatW(ApplicationText, SelectedApplication->Licence);
800 StrCatW(ApplicationText, L"\n");
801 }
802 if(StrCmpW(SelectedApplication->Maintainer, L"")) {
803 StrCatW(ApplicationText, Strings[IDS_MAINTAINER]);
804 StrCatW(ApplicationText, SelectedApplication->Maintainer);
805 StrCatW(ApplicationText, L"\n");
806 }
807 if(StrCmpW(SelectedApplication->Licence, L"") || StrCmpW(SelectedApplication->Version, L"") || StrCmpW(SelectedApplication->Maintainer, L""))
808 StrCatW(ApplicationText, L"\n");
809 StrCatW(ApplicationText, SelectedApplication->Description);
810 ShowMessage(SelectedApplication->Name, ApplicationText);
811 if(StrCmpW(SelectedApplication->RegName, L"")) {
812 if(getUninstaller(SelectedApplication->RegName, Uninstaller)) {
813 bShowUninstaller = TRUE;
814 }
815 }
816 }
817 }
818 if (bShowUninstaller)
819 showUninstaller();
820 else
821 hideUninstaller();
822 }
823 }
824 break;
825
826 case WM_SIZING:
827 {
828 LPRECT pRect = (LPRECT)lParam;
829 if (pRect->right-pRect->left < 520)
830 pRect->right = pRect->left + 520;
831
832 if (pRect->bottom-pRect->top < 300)
833 pRect->bottom = pRect->top + 300;
834 }
835 break;
836
837 case WM_SIZE:
838 {
839 int Split_Hozizontal = (HIWORD(lParam)-(45+60))/2 + 60;
840 int Split_Vertical = 200;
841 RECT Rect;
842
843 ResizeControl(hCategories, 10, 60, Split_Vertical, HIWORD(lParam)-10);
844 ResizeControl(hApps, Split_Vertical+5, 60, LOWORD(lParam)-10, Split_Hozizontal);
845 SetRect(&Rect, Split_Vertical+5, Split_Hozizontal+5, LOWORD(lParam)-10, HIWORD(lParam)-50);
846 DescriptionRect = Rect;
847
848 MoveWindow(hHelpButton, LOWORD(lParam)-50, 10, 40, 40, TRUE);
849 MoveWindow(hUpdateButton, LOWORD(lParam)-150, 10, 40, 40, TRUE);
850 MoveWindow(hProfButton, LOWORD(lParam)-100, 10, 40, 40, TRUE);
851 if(IsWindowVisible(hUninstallButton))
852 MoveWindow(hDownloadButton, (Split_Vertical+LOWORD(lParam))/2, HIWORD(lParam)-45, 140, 35, TRUE);
853 else
854 MoveWindow(hDownloadButton, (Split_Vertical+LOWORD(lParam))/2-70, HIWORD(lParam)-45, 140, 35, TRUE);
855 MoveWindow(hUninstallButton, (Split_Vertical+LOWORD(lParam))/2-140, HIWORD(lParam)-45, 140, 35, TRUE);
856 }
857 break;
858
859 case WM_DESTROY:
860 {
861 DeleteObject(hLogo);
862 if(Root.Children)
863 FreeTree(Root.Children);
864 PostQuitMessage(0);
865 return 0;
866 }
867 break;
868 }
869
870 return DefWindowProc (hwnd, Message, wParam, lParam);
871 }
872
873 INT WINAPI
874 wWinMain (HINSTANCE hInstance,
875 HINSTANCE hPrevInst,
876 LPTSTR lpCmdLine,
877 INT nCmdShow)
878 {
879 int i;
880 WNDCLASSEXW WndClass = {0};
881 MSG msg;
882
883 InitCommonControls();
884
885 // Load strings
886 for(i=0; i<STRING_COUNT; i++)
887 LoadStringW(hInstance, i, Strings[i], MAX_STRING_LENGHT); // if you know a better method please tell me.
888
889 // Create the window
890 WndClass.cbSize = sizeof(WNDCLASSEX);
891 WndClass.lpszClassName = L"Downloader";
892 WndClass.lpfnWndProc = WndProc;
893 WndClass.hInstance = hInstance;
894 WndClass.style = CS_HREDRAW | CS_VREDRAW;
895 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
896 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
897
898 RegisterClassExW(&WndClass);
899
900 hwnd = CreateWindowW(L"Downloader",
901 Strings[IDS_WINDOW_TITLE],
902 WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
903 CW_USEDEFAULT,
904 CW_USEDEFAULT,
905 720, 550,
906 NULL, NULL,
907 hInstance,
908 NULL);
909
910 // Show it
911 ShowWindow(hwnd, SW_SHOW);
912 UpdateWindow(hwnd);
913
914 // Message Loop
915 while(GetMessage(&msg,NULL,0,0))
916 {
917 TranslateMessage(&msg);
918 DispatchMessage(&msg);
919 }
920
921 return 0;
922 }