[CMAKE]
[reactos.git] / base / applications / rapps / winmain.c
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/winmain.c
5 * PURPOSE: Main program
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 */
8
9 #include "rapps.h"
10
11 HWND hMainWnd;
12 HINSTANCE hInst;
13 HIMAGELIST hImageTreeView = NULL;
14 INT SelectedEnumType = ENUM_ALL_COMPONENTS;
15 SETTINGS_INFO SettingsInfo;
16
17
18 VOID
19 FillDafaultSettings(PSETTINGS_INFO pSettingsInfo)
20 {
21 pSettingsInfo->bSaveWndPos = TRUE;
22 pSettingsInfo->bUpdateAtStart = FALSE;
23 pSettingsInfo->bLogEnabled = TRUE;
24 wcscpy(pSettingsInfo->szDownloadDir, L"C:\\Downloads");
25 pSettingsInfo->bDelInstaller = FALSE;
26
27 pSettingsInfo->Maximized = FALSE;
28 pSettingsInfo->Left = 0;
29 pSettingsInfo->Top = 0;
30 pSettingsInfo->Right = 680;
31 pSettingsInfo->Bottom = 450;
32 }
33
34 static BOOL
35 LoadSettings(VOID)
36 {
37 HKEY hKey;
38 DWORD dwSize;
39
40 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\ReactOS\\rapps", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
41 {
42 dwSize = sizeof(SETTINGS_INFO);
43 if (RegQueryValueExW(hKey, L"Settings", NULL, NULL, (LPBYTE)&SettingsInfo, &dwSize) == ERROR_SUCCESS)
44 {
45 RegCloseKey(hKey);
46 return TRUE;
47 }
48
49 RegCloseKey(hKey);
50 }
51
52 return FALSE;
53 }
54
55 VOID
56 SaveSettings(HWND hwnd)
57 {
58 WINDOWPLACEMENT wp;
59 HKEY hKey;
60
61 if (SettingsInfo.bSaveWndPos)
62 {
63 wp.length = sizeof(WINDOWPLACEMENT);
64 GetWindowPlacement(hwnd, &wp);
65
66 SettingsInfo.Left = wp.rcNormalPosition.left;
67 SettingsInfo.Top = wp.rcNormalPosition.top;
68 SettingsInfo.Right = wp.rcNormalPosition.right;
69 SettingsInfo.Bottom = wp.rcNormalPosition.bottom;
70 SettingsInfo.Maximized = (IsZoomed(hwnd) || (wp.flags & WPF_RESTORETOMAXIMIZED));
71 }
72
73 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\ReactOS\\rapps", 0, NULL,
74 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
75 {
76 RegSetValueEx(hKey, L"Settings", 0, REG_BINARY, (LPBYTE)&SettingsInfo, sizeof(SETTINGS_INFO));
77 RegCloseKey(hKey);
78 }
79 }
80
81 VOID
82 FreeInstalledAppList(VOID)
83 {
84 INT Count = ListView_GetItemCount(hListView) - 1;
85 PINSTALLED_INFO Info;
86
87 while (Count >= 0)
88 {
89 Info = ListViewGetlParam(Count);
90 if (Info)
91 {
92 RegCloseKey(Info->hSubKey);
93 HeapFree(GetProcessHeap(), 0, Info);
94 }
95 Count--;
96 }
97 }
98
99 BOOL
100 CALLBACK
101 EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, INSTALLED_INFO Info)
102 {
103 PINSTALLED_INFO ItemInfo;
104 WCHAR szText[MAX_PATH];
105 INT Index;
106
107 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
108 if (!ItemInfo) return FALSE;
109
110 *ItemInfo = Info;
111
112 Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM)ItemInfo);
113
114 /* Get version info */
115 GetApplicationString((HKEY)ItemInfo->hSubKey, L"DisplayVersion", szText);
116 ListView_SetItemText(hListView, Index, 1, szText);
117 /* Get comments */
118 GetApplicationString((HKEY)ItemInfo->hSubKey, L"Comments", szText);
119 ListView_SetItemText(hListView, Index, 2, szText);
120
121 return TRUE;
122 }
123
124 VOID
125 FreeAvailableAppList(VOID)
126 {
127 INT Count = ListView_GetItemCount(hListView) - 1;
128 PVOID Info;
129
130 while (Count >= 0)
131 {
132 Info = ListViewGetlParam(Count);
133 if (Info)
134 HeapFree(GetProcessHeap(), 0, Info);
135 Count--;
136 }
137 }
138
139 BOOL
140 CALLBACK
141 EnumAvailableAppProc(APPLICATION_INFO Info)
142 {
143 PAPPLICATION_INFO ItemInfo;
144 INT Index;
145
146 /* Only add a ListView entry if...
147 - no RegName was supplied (so we cannot determine whether the application is installed or not) or
148 - a RegName was supplied and the application is not installed
149 */
150 if (!*Info.szRegName || (!IsInstalledApplication(Info.szRegName, FALSE) && !IsInstalledApplication(Info.szRegName, TRUE)))
151 {
152 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_INFO));
153 if (!ItemInfo) return FALSE;
154
155 *ItemInfo = Info;
156
157 Index = ListViewAddItem(Info.Category, 0, Info.szName, (LPARAM)ItemInfo);
158 ListView_SetItemText(hListView, Index, 1, Info.szVersion);
159 ListView_SetItemText(hListView, Index, 2, Info.szDesc);
160 }
161
162 return TRUE;
163 }
164
165 VOID
166 UpdateApplicationsList(INT EnumType)
167 {
168 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
169 HICON hIcon;
170 HIMAGELIST hImageListView;
171
172 (VOID) ListView_DeleteAllItems(hListView);
173
174 /* Create image list */
175 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
176 LISTVIEW_ICON_SIZE,
177 GetSystemColorDepth() | ILC_MASK,
178 0, 1);
179
180 hIcon = LoadImage(hInst,
181 MAKEINTRESOURCE(IDI_MAIN),
182 IMAGE_ICON,
183 LISTVIEW_ICON_SIZE,
184 LISTVIEW_ICON_SIZE,
185 LR_CREATEDIBSECTION);
186
187 ImageList_AddIcon(hImageListView, hIcon);
188 DestroyIcon(hIcon);
189
190 if (EnumType == -1) EnumType = SelectedEnumType;
191
192 if (IS_INSTALLED_ENUM(SelectedEnumType))
193 FreeInstalledAppList();
194 else if (IS_AVAILABLE_ENUM(SelectedEnumType))
195 FreeAvailableAppList();
196
197 if (IS_INSTALLED_ENUM(EnumType))
198 {
199 /* Enum installed applications and updates */
200 EnumInstalledApplications(EnumType, TRUE, EnumInstalledAppProc);
201 EnumInstalledApplications(EnumType, FALSE, EnumInstalledAppProc);
202 }
203 else if (IS_AVAILABLE_ENUM(EnumType))
204 {
205 /* Enum availabled applications */
206 EnumAvailableApplications(EnumType, EnumAvailableAppProc);
207 }
208
209 /* Set image list for ListView */
210 hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
211
212 /* Destroy old image list */
213 if (hImageListView)
214 ImageList_Destroy(hImageListView);
215
216 SelectedEnumType = EnumType;
217
218 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
219 swprintf(szBuffer1, szBuffer2, ListView_GetItemCount(hListView));
220 SetStatusBarText(szBuffer1);
221
222 SetWelcomeText();
223 }
224
225 VOID
226 InitApplicationsList(VOID)
227 {
228 WCHAR szText[MAX_STR_LEN];
229
230 /* Add columns to ListView */
231 LoadStringW(hInst, IDS_APP_NAME, szText, sizeof(szText) / sizeof(WCHAR));
232 ListViewAddColumn(0, szText, 200, LVCFMT_LEFT);
233
234 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, sizeof(szText) / sizeof(WCHAR));
235 ListViewAddColumn(1, szText, 90, LVCFMT_RIGHT);
236
237 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, sizeof(szText) / sizeof(WCHAR));
238 ListViewAddColumn(3, szText, 250, LVCFMT_LEFT);
239
240 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
241 }
242
243 HTREEITEM
244 AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
245 {
246 WCHAR szText[MAX_STR_LEN];
247 INT Index;
248 HICON hIcon;
249
250 hIcon = LoadImage(hInst,
251 MAKEINTRESOURCE(IconIndex),
252 IMAGE_ICON,
253 TREEVIEW_ICON_SIZE,
254 TREEVIEW_ICON_SIZE,
255 LR_CREATEDIBSECTION);
256
257 Index = ImageList_AddIcon(hImageTreeView, hIcon);
258 DestroyIcon(hIcon);
259
260 LoadStringW(hInst, TextIndex, szText, sizeof(szText) / sizeof(TCHAR));
261
262 return TreeViewAddItem(hRootItem, szText, Index, Index, TextIndex);
263 }
264
265 VOID
266 InitCategoriesList(VOID)
267 {
268 HTREEITEM hRootItem1, hRootItem2;
269
270 /* Create image list */
271 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE,
272 TREEVIEW_ICON_SIZE,
273 GetSystemColorDepth() | ILC_MASK,
274 0, 1);
275
276 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
277 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
278 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
279
280 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
281 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
282 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
283 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
284 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
285 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
286 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
287 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
288 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
289 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
290 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
291 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
292 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
293 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
294 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
295 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
296
297 (VOID) TreeView_SetImageList(hTreeView, hImageTreeView, TVSIL_NORMAL);
298
299 (VOID) TreeView_Expand(hTreeView, hRootItem2, TVE_EXPAND);
300 (VOID) TreeView_Expand(hTreeView, hRootItem1, TVE_EXPAND);
301
302 (VOID) TreeView_SelectItem(hTreeView, hRootItem1);
303 }
304
305 BOOL
306 InitControls(HWND hwnd)
307 {
308 if (SettingsInfo.bSaveWndPos)
309 {
310 MoveWindow(hwnd, SettingsInfo.Left, SettingsInfo.Top,
311 SettingsInfo.Right - SettingsInfo.Left,
312 SettingsInfo.Bottom - SettingsInfo.Top, TRUE);
313
314 if (SettingsInfo.Maximized) ShowWindow(hwnd, SW_MAXIMIZE);
315 }
316
317 if (CreateStatusBar(hwnd) &&
318 CreateToolBar(hwnd) &&
319 CreateListView(hwnd) &&
320 CreateTreeView(hwnd) &&
321 CreateRichEdit(hwnd) &&
322 CreateVSplitBar(hwnd) &&
323 CreateHSplitBar(hwnd))
324 {
325 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
326
327 InitApplicationsList();
328
329 InitCategoriesList();
330
331 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
332 swprintf(szBuffer1, szBuffer2, ListView_GetItemCount(hListView));
333 SetStatusBarText(szBuffer1);
334 return TRUE;
335 }
336
337 return FALSE;
338 }
339
340 VOID
341 MainWndOnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
342 {
343 WORD wCommand = LOWORD(wParam);
344
345 if (lParam == (LPARAM)hSearchBar)
346 {
347 WCHAR szBuf[MAX_STR_LEN];
348
349 switch (HIWORD(wParam))
350 {
351 case EN_SETFOCUS:
352 {
353 WCHAR szWndText[MAX_STR_LEN];
354
355 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
356 GetWindowTextW(hSearchBar, szWndText, MAX_STR_LEN);
357 if (wcscmp(szBuf, szWndText) == 0) SetWindowTextW(hSearchBar, L"");
358 }
359 break;
360
361 case EN_KILLFOCUS:
362 {
363 GetWindowTextW(hSearchBar, szBuf, MAX_STR_LEN);
364 if (wcslen(szBuf) < 1)
365 {
366 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
367 SetWindowTextW(hSearchBar, szBuf);
368 }
369 }
370 break;
371
372 case EN_CHANGE:
373 /* TODO: Implement search */
374 break;
375 }
376
377 return;
378 }
379
380 switch (wCommand)
381 {
382 case ID_OPEN_LINK:
383 ShellExecuteW(hwnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
384 HeapFree(GetProcessHeap(), 0, pLink);
385 break;
386
387 case ID_COPY_LINK:
388 CopyTextToClipboard(pLink);
389 HeapFree(GetProcessHeap(), 0, pLink);
390 break;
391
392 case ID_SETTINGS:
393 CreateSettingsDlg(hwnd);
394 break;
395
396 case ID_EXIT:
397 PostMessageW(hwnd, WM_CLOSE, 0, 0);
398 break;
399
400 case ID_INSTALL:
401 if (DownloadApplication(-1))
402 /* TODO: Implement install dialog
403 * if (InstallApplication(-1))
404 */
405 UpdateApplicationsList(-1);
406 break;
407
408 case ID_UNINSTALL:
409 if (UninstallApplication(-1, FALSE))
410 UpdateApplicationsList(-1);
411 break;
412
413 case ID_MODIFY:
414 if (UninstallApplication(-1, TRUE))
415 UpdateApplicationsList(-1);
416 break;
417
418 case ID_REGREMOVE:
419 RemoveAppFromRegistry(-1);
420 break;
421
422 case ID_REFRESH:
423 UpdateApplicationsList(-1);
424 break;
425
426 case ID_HELP:
427 MessageBoxW(hwnd, L"Help not implemented yet", NULL, MB_OK);
428 break;
429
430 case ID_ABOUT:
431 ShowAboutDialog();
432 break;
433 }
434 }
435
436 VOID
437 MainWndOnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
438 {
439 HDWP hdwp = BeginDeferWindowPos(5);
440 INT SearchBarWidth = GetWindowWidth(hSearchBar);
441 INT RichPos = GetWindowHeight(hRichEdit);
442 INT NewPos = HIWORD(lParam) - (RichPos + SPLIT_WIDTH + GetWindowHeight(hStatusBar));
443 INT VSplitterPos;
444
445 /* Size status bar */
446 SendMessage(hStatusBar, WM_SIZE, 0, 0);
447
448 /* Size tool bar */
449 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
450
451 /* Size SearchBar */
452 MoveWindow(hSearchBar, LOWORD(lParam) - SearchBarWidth - 4, 5, SearchBarWidth, 22, TRUE);
453
454 /*
455 * HIWORD(lParam) - Height of main window
456 * LOWORD(lParam) - Width of main window
457 */
458
459 /* Size vertical splitter bar */
460 DeferWindowPos(hdwp,
461 hVSplitter,
462 0,
463 (VSplitterPos = GetWindowWidth(hTreeView)),
464 GetWindowHeight(hToolBar),
465 SPLIT_WIDTH,
466 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
467 SWP_NOZORDER|SWP_NOACTIVATE);
468
469 /* Size TreeView */
470 DeferWindowPos(hdwp,
471 hTreeView,
472 0,
473 0,
474 GetWindowHeight(hToolBar),
475 VSplitterPos,
476 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
477 SWP_NOZORDER|SWP_NOACTIVATE);
478
479 while (NewPos < SPLIT_WIDTH + GetWindowHeight(hToolBar))
480 {
481 RichPos--;
482 NewPos = HIWORD(lParam) - (RichPos +
483 SPLIT_WIDTH + GetWindowHeight(hStatusBar));
484 }
485 SetHSplitterPos(NewPos);
486
487 /* Size ListView */
488 DeferWindowPos(hdwp,
489 hListView,
490 0,
491 VSplitterPos + SPLIT_WIDTH,
492 GetWindowHeight(hToolBar),
493 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
494 GetHSplitterPos() - GetWindowHeight(hToolBar),
495 SWP_NOZORDER|SWP_NOACTIVATE);
496
497 /* Size RichEdit */
498 DeferWindowPos(hdwp,
499 hRichEdit,
500 0,
501 VSplitterPos + SPLIT_WIDTH,
502 GetHSplitterPos() + SPLIT_WIDTH,
503 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
504 RichPos,
505 SWP_NOZORDER|SWP_NOACTIVATE);
506
507 /* Size horizontal splitter bar */
508 DeferWindowPos(hdwp,
509 hHSplitter,
510 0,
511 VSplitterPos + SPLIT_WIDTH,
512 GetHSplitterPos(),
513 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
514 SPLIT_WIDTH,
515 SWP_NOZORDER|SWP_NOACTIVATE);
516
517 EndDeferWindowPos(hdwp);
518 }
519
520 LRESULT CALLBACK
521 MainWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
522 {
523 switch (Msg)
524 {
525 case WM_CREATE:
526 if (!InitControls(hwnd))
527 PostMessage(hwnd, WM_CLOSE, 0, 0);
528
529 if (SettingsInfo.bUpdateAtStart)
530 UpdateAppsDB();
531 break;
532
533 case WM_COMMAND:
534 MainWndOnCommand(hwnd, wParam, lParam);
535 break;
536
537 case WM_NOTIFY:
538 {
539 LPNMHDR data = (LPNMHDR)lParam;
540
541 switch (data->code)
542 {
543 case TVN_SELCHANGED:
544 {
545 if (data->hwndFrom == hTreeView)
546 {
547 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam)
548 {
549 case IDS_INSTALLED:
550 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
551 break;
552
553 case IDS_APPLICATIONS:
554 UpdateApplicationsList(ENUM_APPLICATIONS);
555 break;
556
557 case IDS_UPDATES:
558 UpdateApplicationsList(ENUM_UPDATES);
559 break;
560
561 case IDS_AVAILABLEFORINST:
562 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
563 break;
564
565 case IDS_CAT_AUDIO:
566 UpdateApplicationsList(ENUM_CAT_AUDIO);
567 break;
568
569 case IDS_CAT_DEVEL:
570 UpdateApplicationsList(ENUM_CAT_DEVEL);
571 break;
572
573 case IDS_CAT_DRIVERS:
574 UpdateApplicationsList(ENUM_CAT_DRIVERS);
575 break;
576
577 case IDS_CAT_EDU:
578 UpdateApplicationsList(ENUM_CAT_EDU);
579 break;
580
581 case IDS_CAT_ENGINEER:
582 UpdateApplicationsList(ENUM_CAT_ENGINEER);
583 break;
584
585 case IDS_CAT_FINANCE:
586 UpdateApplicationsList(ENUM_CAT_FINANCE);
587 break;
588
589 case IDS_CAT_GAMES:
590 UpdateApplicationsList(ENUM_CAT_GAMES);
591 break;
592
593 case IDS_CAT_GRAPHICS:
594 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
595 break;
596
597 case IDS_CAT_INTERNET:
598 UpdateApplicationsList(ENUM_CAT_INTERNET);
599 break;
600
601 case IDS_CAT_LIBS:
602 UpdateApplicationsList(ENUM_CAT_LIBS);
603 break;
604
605 case IDS_CAT_OFFICE:
606 UpdateApplicationsList(ENUM_CAT_OFFICE);
607 break;
608
609 case IDS_CAT_OTHER:
610 UpdateApplicationsList(ENUM_CAT_OTHER);
611 break;
612
613 case IDS_CAT_SCIENCE:
614 UpdateApplicationsList(ENUM_CAT_SCIENCE);
615 break;
616
617 case IDS_CAT_TOOLS:
618 UpdateApplicationsList(ENUM_CAT_TOOLS);
619 break;
620
621 case IDS_CAT_VIDEO:
622 UpdateApplicationsList(ENUM_CAT_VIDEO);
623 break;
624 }
625 }
626 }
627 break;
628
629 case LVN_KEYDOWN:
630 {
631 LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN) lParam;
632
633 if (pnkd->hdr.hwndFrom == hListView)
634 {
635 INT ItemIndex = (INT) SendMessage(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
636
637 if (pnkd->wVKey == VK_UP) ItemIndex -= 1;
638 if (pnkd->wVKey == VK_DOWN) ItemIndex += 1;
639
640 if (IS_INSTALLED_ENUM(SelectedEnumType))
641 ShowInstalledAppInfo(ItemIndex);
642 if (IS_AVAILABLE_ENUM(SelectedEnumType))
643 ShowAvailableAppInfo(ItemIndex);
644 }
645 }
646 break;
647
648 case LVN_COLUMNCLICK:
649 {
650 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
651
652 (VOID) ListView_SortItems(hListView, ListViewCompareFunc, pnmv->iSubItem);
653 bAscending = !bAscending;
654 }
655 break;
656
657 case NM_CLICK:
658 if (data->hwndFrom == hListView)
659 {
660 if (IS_INSTALLED_ENUM(SelectedEnumType))
661 ShowInstalledAppInfo(-1);
662 if (IS_AVAILABLE_ENUM(SelectedEnumType))
663 ShowAvailableAppInfo(-1);
664 }
665 break;
666
667 case NM_RCLICK:
668 if (data->hwndFrom == hListView)
669 ShowPopupMenu(hListView, IDR_APPLICATIONMENU);
670 break;
671
672 case EN_LINK:
673 RichEditOnLink(hwnd, (ENLINK*)lParam);
674 break;
675
676 case TTN_GETDISPINFO:
677 ToolBarOnGetDispInfo((LPTOOLTIPTEXT)lParam);
678 break;
679 }
680 }
681 break;
682
683 case WM_PAINT:
684 break;
685
686 case WM_SIZE:
687 {
688 if ((GetClientWindowHeight(hMainWnd) - GetWindowHeight(hStatusBar) - SPLIT_WIDTH) < GetHSplitterPos())
689 {
690 INT NewSplitPos = GetClientWindowHeight(hwnd) - 100 - GetWindowHeight(hStatusBar) - SPLIT_WIDTH;
691 if (NewSplitPos > GetWindowHeight(hToolBar) + SPLIT_WIDTH)
692 SetHSplitterPos(NewSplitPos);
693 }
694
695 MainWndOnSize(hwnd, wParam, lParam);
696 }
697 break;
698
699 case WM_SIZING:
700 {
701 int RichEditHeight = GetWindowHeight(hRichEdit);
702 LPRECT pRect = (LPRECT)lParam;
703
704 while (RichEditHeight <= 100)
705 {
706 if (GetHSplitterPos() - 1 < GetWindowHeight(hToolBar) + GetWindowHeight(hListView) + SPLIT_WIDTH)
707 break;
708 SetHSplitterPos(GetHSplitterPos() - 1);
709 RichEditHeight++;
710 }
711
712 if (pRect->right-pRect->left < 565)
713 pRect->right = pRect->left + 565;
714
715 if (pRect->bottom-pRect->top < 300)
716 pRect->bottom = pRect->top + 300;
717 return TRUE;
718 }
719
720 case WM_SYSCOLORCHANGE:
721 {
722 /* Forward WM_SYSCOLORCHANGE to common controls */
723 SendMessage(hListView, WM_SYSCOLORCHANGE, 0, 0);
724 SendMessage(hTreeView, WM_SYSCOLORCHANGE, 0, 0);
725 SendMessage(hToolBar, WM_SYSCOLORCHANGE, 0, 0);
726 SendMessageW(hRichEdit, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
727 }
728 break;
729
730 case WM_DESTROY:
731 {
732 ShowWindow(hwnd, SW_HIDE);
733 SaveSettings(hwnd);
734
735 FreeLogs();
736
737 if (IS_AVAILABLE_ENUM(SelectedEnumType))
738 FreeAvailableAppList();
739 if (IS_INSTALLED_ENUM(SelectedEnumType))
740 FreeInstalledAppList();
741 if (hImageTreeView) ImageList_Destroy(hImageTreeView);
742
743 PostQuitMessage(0);
744 return 0;
745 }
746 break;
747 }
748
749 return DefWindowProc(hwnd, Msg, wParam, lParam);
750 }
751
752 int WINAPI
753 wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
754 {
755 WNDCLASSEXW WndClass = {0};
756 WCHAR szWindowClass[] = L"ROSAPPMGR";
757 WCHAR szWindowName[MAX_STR_LEN];
758 WCHAR szErrorText[MAX_STR_LEN];
759 HANDLE hMutex = NULL;
760 MSG Msg;
761
762 hInst = hInstance;
763
764 if (!IsUserAnAdmin())
765 {
766 LoadStringW(hInst, IDS_USER_NOT_ADMIN, szErrorText, sizeof(szErrorText) / sizeof(WCHAR));
767 MessageBox(0, szErrorText, NULL, MB_OK | MB_ICONWARNING);
768 return 1;
769 }
770
771 hMutex = CreateMutexW(NULL, FALSE, szWindowClass);
772 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
773 {
774 /* If already started, it is found its window */
775 HWND hWindow = FindWindowW(szWindowClass, NULL);
776
777 /* Activate window */
778 ShowWindow(hWindow, SW_SHOWNORMAL);
779 SetForegroundWindow(hWindow);
780 return 1;
781 }
782
783 if (!LoadSettings())
784 {
785 FillDafaultSettings(&SettingsInfo);
786 }
787
788 InitLogs();
789
790 InitCommonControls();
791
792 /* Create the window */
793 WndClass.cbSize = sizeof(WNDCLASSEXW);
794 WndClass.lpszClassName = szWindowClass;
795 WndClass.lpfnWndProc = MainWindowProc;
796 WndClass.hInstance = hInstance;
797 WndClass.style = CS_HREDRAW | CS_VREDRAW;
798 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
799 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
800 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
801 WndClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
802
803 if (RegisterClassExW(&WndClass) == (ATOM)0) goto Exit;
804
805 LoadStringW(hInst, IDS_APPTITLE, szWindowName, sizeof(szWindowName) / sizeof(WCHAR));
806
807 hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
808 szWindowClass,
809 szWindowName,
810 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
811 CW_USEDEFAULT,
812 CW_USEDEFAULT,
813 680,
814 450,
815 NULL,
816 NULL,
817 hInstance,
818 NULL);
819
820 if (!hMainWnd) goto Exit;
821
822 /* Show it */
823 ShowWindow(hMainWnd, SW_SHOW);
824 UpdateWindow(hMainWnd);
825
826 /* Message Loop */
827 while (GetMessage(&Msg, NULL, 0, 0))
828 {
829 TranslateMessage(&Msg);
830 DispatchMessage(&Msg);
831 }
832
833 Exit:
834 if (hMutex) CloseHandle(hMutex);
835
836 return 0;
837 }