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