12fc3a9d5da3011e3d732bc27d1cc6a1ea2b51b7
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
13 #include "resources.h"
14 #include "structures.h"
16 #define XML_PATH "C:\\ReactOS\\system32\\downloader.xml"
18 HWND hwnd
, hCategories
, hApps
, hDownloadButton
, hUninstallButton
, hUpdateButton
, hHelpButton
;
19 HBITMAP hLogo
, hUnderline
;
20 WCHAR
* DescriptionHeadline
= L
"";
21 WCHAR
* DescriptionText
= L
"";
22 WCHAR ApplicationText
[700];
25 struct Application
* SelectedApplication
;
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
];
33 BOOL
getUninstaller(WCHAR
* RegName
, WCHAR
* Uninstaller
) {
35 const DWORD ArraySize
= 200;
40 DWORD Size
= ArraySize
;
41 WCHAR Value
[ArraySize
];
42 WCHAR KeyName
[ArraySize
];
45 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",0,KEY_READ
,&hKey1
) == ERROR_SUCCESS
) {
46 while (RegEnumKeyExW(hKey1
,i
,KeyName
,&Size
,NULL
,NULL
,NULL
,NULL
) == ERROR_SUCCESS
) {
48 RegOpenKeyExW(hKey1
,KeyName
,0,KEY_READ
,&hKey2
);
50 if (RegQueryValueExW(hKey2
,L
"DisplayName",0,&Type
,(LPBYTE
)Value
,&Size
) == ERROR_SUCCESS
) {
52 if (StrCmpW(Value
,RegName
) == 0) {
53 if (RegQueryValueExW(hKey2
,L
"UninstallString",0,&Type
,(LPBYTE
)Uninstaller
,&Size
) == ERROR_SUCCESS
) {
72 void ShowMessage (WCHAR
* title
, WCHAR
* message
)
74 DescriptionHeadline
= title
;
75 DescriptionText
= message
;
76 InvalidateRect(hwnd
,NULL
,TRUE
);
80 void AddItems (HWND hwnd
, struct Category
* Category
, struct Category
* Parent
)
82 TV_INSERTSTRUCTW Insert
;
84 Insert
.item
.lParam
= (UINT
)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
;
93 Category
->TreeviewItem
= (HTREEITEM
)SendMessage(hwnd
, TVM_INSERTITEM
, 0, (LPARAM
)&Insert
);
96 AddItems (hwnd
,Category
->Next
,Parent
);
98 if(Category
->Children
)
99 AddItems (hwnd
,Category
->Children
,Category
);
102 void CategoryChoosen (HWND hwnd
, struct Category
* Category
)
104 struct Application
* CurrentApplication
;
105 TV_INSERTSTRUCTW Insert
;
106 SelectedApplication
= NULL
;
108 if(Category
->Children
&& !Category
->Apps
)
109 ShowMessage(Category
->Name
, Strings
[IDS_CHOOSE_SUB
]);
110 else if(!Category
->Children
&& Category
->Apps
)
111 ShowMessage(Category
->Name
, Strings
[IDS_CHOOSE_APP
]);
112 else if(Category
->Children
&& Category
->Apps
)
113 ShowMessage(Category
->Name
, Strings
[IDS_CHOOSE_BOTH
]);
115 ShowMessage(Category
->Name
, Strings
[IDS_NO_APPS
]);
117 (void)TreeView_DeleteItem(hwnd
, TVI_ROOT
);
118 (void)TreeView_DeleteItem(hwnd
, TVI_ROOT
); // Delete twice to bypass bug in windows
120 Insert
.item
.mask
= TVIF_TEXT
|TVIF_PARAM
|TVIF_IMAGE
;
121 Insert
.hInsertAfter
= TVI_LAST
;
122 Insert
.hParent
= TVI_ROOT
;
124 CurrentApplication
= Category
->Apps
;
126 WCHAR Uninstaller
[200];
127 while(CurrentApplication
)
129 Insert
.item
.lParam
= (UINT
)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;
137 SendMessage(hwnd
, TVM_INSERTITEM
, 0, (LPARAM
)&Insert
);
138 CurrentApplication
= CurrentApplication
->Next
;
142 BOOL
SetupControls (HWND hwnd
)
144 TV_INSERTSTRUCTW Insert
= {0};
145 HIMAGELIST hImageList
;
146 HINSTANCE hInstance
= GetModuleHandle(NULL
);
148 // Parse the XML file
149 if (ProcessXML (XML_PATH
, &Root
) == FALSE
)
152 // Set up the controls
153 hCategories
= CreateWindowExW(0, WC_TREEVIEWW
, L
"Categories", WS_CHILD
|WS_VISIBLE
|WS_BORDER
|TVS_HASLINES
|TVS_LINESATROOT
|TVS_HASBUTTONS
|TVS_SHOWSELALWAYS
,
154 0, 0, 0, 0, hwnd
, NULL
, hInstance
, NULL
);
156 hApps
= CreateWindowExW(0, WC_TREEVIEWW
, L
"Applications", WS_CHILD
|WS_VISIBLE
|WS_BORDER
|TVS_HASLINES
|TVS_LINESATROOT
|TVS_HASBUTTONS
|TVS_SHOWSELALWAYS
,
157 0, 0, 0, 0, hwnd
, NULL
, hInstance
, NULL
);
159 hLogo
= LoadBitmap(GetModuleHandle(NULL
), MAKEINTRESOURCE(IDB_LOGO
));
160 hUnderline
= LoadBitmap(GetModuleHandle(NULL
), MAKEINTRESOURCE(IDB_UNDERLINE
));
162 hHelpButton
= CreateWindowW (L
"Button", L
"", WS_CHILD
|WS_VISIBLE
|BS_BITMAP
, 550, 10, 40, 40, hwnd
, 0, hInstance
, NULL
);
163 hUpdateButton
= CreateWindowW (L
"Button", L
"", WS_CHILD
|WS_VISIBLE
|BS_BITMAP
, 500, 10, 40, 40, hwnd
, 0, hInstance
, NULL
);
164 hDownloadButton
= CreateWindowW (L
"Button", L
"", WS_CHILD
|WS_VISIBLE
|BS_BITMAP
, 330, 505, 140, 33, hwnd
, 0, hInstance
, NULL
);
165 hUninstallButton
= CreateWindowW (L
"Button", L
"", WS_CHILD
|WS_VISIBLE
|BS_BITMAP
, 260, 505, 140, 33, hwnd
, 0, hInstance
, NULL
);
167 SendMessageW(hHelpButton
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)(HANDLE
)LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_HELP
)));
168 SendMessageW(hUpdateButton
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
,(LPARAM
)(HANDLE
)LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_UPDATE
)));
169 SendMessageW(hDownloadButton
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
,(LPARAM
)(HANDLE
)LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_DOWNLOAD
)));
170 SendMessageW(hUninstallButton
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
,(LPARAM
)(HANDLE
)LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_UNINSTALL
)));
171 ShowWindow(hUninstallButton
, SW_HIDE
);
173 // Set deflaut entry for hApps
174 Insert
.item
.mask
= TVIF_TEXT
|TVIF_IMAGE
;
175 Insert
.item
.pszText
= Strings
[IDS_CHOOSE_CATEGORY
];
176 Insert
.item
.cchTextMax
= lstrlenW(Strings
[IDS_CHOOSE_CATEGORY
]);
177 Insert
.item
.iImage
= 0;
178 SendMessage(hApps
, TVM_INSERTITEM
, 0, (LPARAM
)&Insert
);
181 hImageList
= ImageList_Create(16, 16, ILC_COLORDDB
, 1, 1);
182 SendMessageW(hCategories
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)(HIMAGELIST
)hImageList
);
183 SendMessageW(hApps
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)(HIMAGELIST
)hImageList
);
185 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_0
)), NULL
);
186 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_1
)), NULL
);
187 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_2
)), NULL
);
188 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_3
)), NULL
);
189 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_4
)), NULL
);
190 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_5
)), NULL
);
191 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_6
)), NULL
);
192 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_7
)), NULL
);
193 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_8
)), NULL
);
194 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_9
)), NULL
);
195 ImageList_Add(hImageList
, LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_10
)), NULL
);
197 // Fill the TreeViews
198 AddItems (hCategories
, Root
.Children
, NULL
);
203 static void ResizeControl (HWND hwnd
, int x1
, int y1
, int x2
, int y2
)
205 // Make resizing a little easier
206 MoveWindow(hwnd
, x1
, y1
, x2
-x1
, y2
-y1
, TRUE
);
209 static void DrawBitmap (HDC hdc
, int x
, int y
, HBITMAP hBmp
)
212 HDC hdcMem
= CreateCompatibleDC(hdc
);
214 SelectObject(hdcMem
, hBmp
);
215 GetObject(hBmp
, sizeof(bm
), &bm
);
216 TransparentBlt(hdc
, x
, y
, bm
.bmWidth
, bm
.bmHeight
, hdcMem
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, 0xFFFFFF);
221 static void DrawDescription (HDC hdc
, RECT DescriptionRect
)
225 RECT Rect
= {DescriptionRect
.left
+5, DescriptionRect
.top
+3, DescriptionRect
.right
-2, DescriptionRect
.top
+22};
228 Rectangle(hdc
, DescriptionRect
.left
, DescriptionRect
.top
, DescriptionRect
.right
, DescriptionRect
.bottom
);
231 for (i
=DescriptionRect
.left
+1;i
<DescriptionRect
.right
-1;i
++)
232 DrawBitmap(hdc
, i
, DescriptionRect
.top
+22, hUnderline
); // less code then stretching ;)
235 Font
= CreateFont(-16 , 0, 0, 0, FW_EXTRABOLD
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
236 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, FF_DONTCARE
, L
"Arial");
237 SelectObject(hdc
, Font
);
238 DrawTextW(hdc
, DescriptionHeadline
, lstrlenW(DescriptionHeadline
), &Rect
, DT_SINGLELINE
|DT_NOPREFIX
);
242 Font
= CreateFont(-13 , 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
243 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, FF_DONTCARE
, L
"Arial");
244 SelectObject(hdc
, Font
);
246 Rect
.bottom
= DescriptionRect
.bottom
-2;
247 DrawTextW(hdc
, DescriptionText
, lstrlenW(DescriptionText
), &Rect
, DT_WORDBREAK
|DT_NOPREFIX
); // ToDo: Call TabbedTextOut to draw a nice table
252 void showUninstaller() {
253 int Split_Vertical
= 200;
256 GetClientRect(hwnd
,&Rect
);
257 ShowWindow(hUninstallButton
,SW_SHOW
);
258 MoveWindow(hDownloadButton
,(Split_Vertical
+Rect
.right
-Rect
.left
)/2,Rect
.bottom
-Rect
.top
-45,140,35,TRUE
);;
261 void hideUninstaller() {
262 int Split_Vertical
= 200;
265 GetClientRect(hwnd
,&Rect
);
266 ShowWindow(hUninstallButton
,SW_HIDE
);
267 MoveWindow(hDownloadButton
,(Split_Vertical
+Rect
.right
-Rect
.left
)/2-70,Rect
.bottom
-Rect
.top
-45,140,35,TRUE
);
270 void startUninstaller(WCHAR
* Uninstaller
) {
272 PROCESS_INFORMATION pi
;
274 memset(&si
, 0, sizeof(si
));
276 CreateProcessW(NULL
,Uninstaller
,NULL
,NULL
,FALSE
,0,NULL
,NULL
,&si
,&pi
);
277 CloseHandle(pi
.hThread
);
278 // WaitForSingleObject(pi.hProcess, INFINITE); // If you want to wait for the Unistaller
279 CloseHandle(pi
.hProcess
);
283 LRESULT CALLBACK
WndProc (HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
285 static RECT DescriptionRect
;
291 if(!SetupControls(hwnd
))
293 ShowMessage(Strings
[IDS_WELCOME_TITLE
], Strings
[IDS_WELCOME
]);
300 HDC hdc
= BeginPaint(hwnd
, &ps
);
301 HDC BackbufferHdc
= CreateCompatibleDC(hdc
);
302 HBITMAP BackbufferBmp
= CreateCompatibleBitmap(hdc
, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
303 SelectObject(BackbufferHdc
, BackbufferBmp
);
305 FillRect(BackbufferHdc
, &ps
.rcPaint
, CreateSolidBrush(RGB(235,235,235)));
306 DrawBitmap(BackbufferHdc
, 10, 12, hLogo
);
307 DrawDescription(BackbufferHdc
, DescriptionRect
);
309 BitBlt(hdc
, 0, 0, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
, BackbufferHdc
, 0, 0, SRCCOPY
);
310 DeleteObject(BackbufferBmp
);
311 DeleteDC(BackbufferHdc
);
318 if(HIWORD(wParam
) == BN_CLICKED
)
320 if (lParam
== (LPARAM
)hDownloadButton
)
322 if(SelectedApplication
)
323 DialogBoxW(GetModuleHandle(NULL
), MAKEINTRESOURCEW(IDD_DOWNLOAD
), 0, DownloadProc
);
325 ShowMessage(Strings
[IDS_NO_APP_TITLE
], Strings
[IDS_NO_APP
]);
327 else if (lParam
== (LPARAM
)hUninstallButton
)
329 if(SelectedApplication
)
331 WCHAR Uninstaller
[200];
332 if(StrCmpW(SelectedApplication
->RegName
, L
"")) {
333 if(getUninstaller(SelectedApplication
->RegName
, Uninstaller
))
334 startUninstaller(Uninstaller
);
338 else if (lParam
== (LPARAM
)hUpdateButton
)
340 ShowMessage(Strings
[IDS_UPDATE_TITLE
], Strings
[IDS_UPDATE
]);
342 else if (lParam
== (LPARAM
)hHelpButton
)
344 ShowMessage(Strings
[IDS_HELP_TITLE
], Strings
[IDS_HELP
]);
352 LPNMHDR data
= (LPNMHDR
)lParam
;
353 if(data
->code
== TVN_SELCHANGED
)
355 BOOL bShowUninstaller
= FALSE
;
356 if(data
->hwndFrom
== hCategories
)
358 struct Category
* Category
= (struct Category
*) ((LPNMTREEVIEW
)lParam
)->itemNew
.lParam
;
359 CategoryChoosen (hApps
, Category
);
361 else if(data
->hwndFrom
== hApps
)
363 SelectedApplication
= (struct Application
*) ((LPNMTREEVIEW
)lParam
)->itemNew
.lParam
;
364 if(SelectedApplication
)
366 ApplicationText
[0]=L
'\0';
367 if(StrCmpW(SelectedApplication
->Version
, L
"")) {
368 StrCatW(ApplicationText
, Strings
[IDS_VERSION
]);
369 StrCatW(ApplicationText
, SelectedApplication
->Version
);
370 StrCatW(ApplicationText
, L
"\n");
372 if(StrCmpW(SelectedApplication
->Licence
, L
"")) {
373 StrCatW(ApplicationText
, Strings
[IDS_LICENCE
]);
374 StrCatW(ApplicationText
, SelectedApplication
->Licence
);
375 StrCatW(ApplicationText
, L
"\n");
377 if(StrCmpW(SelectedApplication
->Maintainer
, L
"")) {
378 StrCatW(ApplicationText
, Strings
[IDS_MAINTAINER
]);
379 StrCatW(ApplicationText
, SelectedApplication
->Maintainer
);
380 StrCatW(ApplicationText
, L
"\n");
382 if(StrCmpW(SelectedApplication
->Licence
, L
"") || StrCmpW(SelectedApplication
->Version
, L
"") || StrCmpW(SelectedApplication
->Maintainer
, L
""))
383 StrCatW(ApplicationText
, L
"\n");
384 StrCatW(ApplicationText
, SelectedApplication
->Description
);
385 ShowMessage(SelectedApplication
->Name
, ApplicationText
);
386 WCHAR Uninstaller
[200];
387 if(StrCmpW(SelectedApplication
->RegName
, L
"")) {
388 if(getUninstaller(SelectedApplication
->RegName
, Uninstaller
)) {
389 bShowUninstaller
= TRUE
;
394 if (bShowUninstaller
)
404 LPRECT pRect
= (LPRECT
)lParam
;
405 if (pRect
->right
-pRect
->left
< 520)
406 pRect
->right
= pRect
->left
+ 520;
408 if (pRect
->bottom
-pRect
->top
< 300)
409 pRect
->bottom
= pRect
->top
+ 300;
415 int Split_Hozizontal
= (HIWORD(lParam
)-(45+60))/2 + 60;
416 int Split_Vertical
= 200;
418 ResizeControl(hCategories
, 10, 60, Split_Vertical
, HIWORD(lParam
)-10);
419 ResizeControl(hApps
, Split_Vertical
+5, 60, LOWORD(lParam
)-10, Split_Hozizontal
);
420 RECT Rect
= {Split_Vertical
+5, Split_Hozizontal
+5, LOWORD(lParam
)-10, HIWORD(lParam
)-50};
421 DescriptionRect
= Rect
;
423 MoveWindow(hHelpButton
, LOWORD(lParam
)-50, 10, 40, 40, TRUE
);
424 MoveWindow(hUpdateButton
, LOWORD(lParam
)-100, 10, 40, 40, TRUE
);
425 if(IsWindowVisible(hUninstallButton
))
426 MoveWindow(hDownloadButton
, (Split_Vertical
+LOWORD(lParam
))/2, HIWORD(lParam
)-45, 140, 35, TRUE
);
428 MoveWindow(hDownloadButton
, (Split_Vertical
+LOWORD(lParam
))/2-70, HIWORD(lParam
)-45, 140, 35, TRUE
);
429 MoveWindow(hUninstallButton
, (Split_Vertical
+LOWORD(lParam
))/2-140, HIWORD(lParam
)-45, 140, 35, TRUE
);
437 FreeTree(Root
.Children
);
444 return DefWindowProc (hwnd
, Message
, wParam
, lParam
);
447 INT WINAPI
WinMain (HINSTANCE hInstance
, HINSTANCE hPrevInst
,
448 LPSTR lpCmdLine
, INT nCmdShow
)
451 WNDCLASSEXW WndClass
= {0};
454 InitCommonControls();
457 for(i
=0; i
<STRING_COUNT
; i
++)
458 LoadStringW(hInstance
, i
, Strings
[i
], MAX_STRING_LENGHT
); // if you know a better method please tell me.
461 WndClass
.cbSize
= sizeof(WNDCLASSEX
);
462 WndClass
.lpszClassName
= L
"Downloader";
463 WndClass
.lpfnWndProc
= WndProc
;
464 WndClass
.hInstance
= hInstance
;
465 WndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
466 WndClass
.hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
467 WndClass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
469 RegisterClassExW(&WndClass
);
471 hwnd
= CreateWindowW(L
"Downloader",
472 Strings
[IDS_WINDOW_TITLE
],
473 WS_OVERLAPPEDWINDOW
|WS_CLIPCHILDREN
,
482 ShowWindow(hwnd
, SW_SHOW
);
486 while(GetMessage(&msg
,NULL
,0,0))
488 TranslateMessage(&msg
);
489 DispatchMessage(&msg
);