* Sync up to trunk head (r60691).
[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 FillDefaultSettings(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_RESETDB:
427 UpdateAppsDB();
428 UpdateApplicationsList(-1);
429 break;
430
431 case ID_HELP:
432 MessageBoxW(hwnd, L"Help not implemented yet", NULL, MB_OK);
433 break;
434
435 case ID_ABOUT:
436 ShowAboutDialog();
437 break;
438 }
439 }
440
441 VOID
442 MainWndOnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
443 {
444 HDWP hdwp = BeginDeferWindowPos(5);
445 INT SearchBarWidth = GetWindowWidth(hSearchBar);
446 INT RichPos = GetWindowHeight(hRichEdit);
447 INT NewPos = HIWORD(lParam) - (RichPos + SPLIT_WIDTH + GetWindowHeight(hStatusBar));
448 INT VSplitterPos;
449
450 /* Size status bar */
451 SendMessage(hStatusBar, WM_SIZE, 0, 0);
452
453 /* Size tool bar */
454 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
455
456 /* Size SearchBar */
457 MoveWindow(hSearchBar, LOWORD(lParam) - SearchBarWidth - 4, 5, SearchBarWidth, 22, TRUE);
458
459 /*
460 * HIWORD(lParam) - Height of main window
461 * LOWORD(lParam) - Width of main window
462 */
463
464 /* Size vertical splitter bar */
465 DeferWindowPos(hdwp,
466 hVSplitter,
467 0,
468 (VSplitterPos = GetWindowWidth(hTreeView)),
469 GetWindowHeight(hToolBar),
470 SPLIT_WIDTH,
471 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
472 SWP_NOZORDER|SWP_NOACTIVATE);
473
474 /* Size TreeView */
475 DeferWindowPos(hdwp,
476 hTreeView,
477 0,
478 0,
479 GetWindowHeight(hToolBar),
480 VSplitterPos,
481 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
482 SWP_NOZORDER|SWP_NOACTIVATE);
483
484 while (NewPos < SPLIT_WIDTH + GetWindowHeight(hToolBar))
485 {
486 RichPos--;
487 NewPos = HIWORD(lParam) - (RichPos +
488 SPLIT_WIDTH + GetWindowHeight(hStatusBar));
489 }
490 SetHSplitterPos(NewPos);
491
492 /* Size ListView */
493 DeferWindowPos(hdwp,
494 hListView,
495 0,
496 VSplitterPos + SPLIT_WIDTH,
497 GetWindowHeight(hToolBar),
498 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
499 GetHSplitterPos() - GetWindowHeight(hToolBar),
500 SWP_NOZORDER|SWP_NOACTIVATE);
501
502 /* Size RichEdit */
503 DeferWindowPos(hdwp,
504 hRichEdit,
505 0,
506 VSplitterPos + SPLIT_WIDTH,
507 GetHSplitterPos() + SPLIT_WIDTH,
508 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
509 RichPos,
510 SWP_NOZORDER|SWP_NOACTIVATE);
511
512 /* Size horizontal splitter bar */
513 DeferWindowPos(hdwp,
514 hHSplitter,
515 0,
516 VSplitterPos + SPLIT_WIDTH,
517 GetHSplitterPos(),
518 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
519 SPLIT_WIDTH,
520 SWP_NOZORDER|SWP_NOACTIVATE);
521
522 EndDeferWindowPos(hdwp);
523 }
524
525 LRESULT CALLBACK
526 MainWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
527 {
528 switch (Msg)
529 {
530 case WM_CREATE:
531 if (!InitControls(hwnd))
532 PostMessage(hwnd, WM_CLOSE, 0, 0);
533
534 if (SettingsInfo.bUpdateAtStart)
535 UpdateAppsDB();
536 break;
537
538 case WM_COMMAND:
539 MainWndOnCommand(hwnd, wParam, lParam);
540 break;
541
542 case WM_NOTIFY:
543 {
544 LPNMHDR data = (LPNMHDR)lParam;
545
546 switch (data->code)
547 {
548 case TVN_SELCHANGED:
549 {
550 if (data->hwndFrom == hTreeView)
551 {
552 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam)
553 {
554 case IDS_INSTALLED:
555 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
556 break;
557
558 case IDS_APPLICATIONS:
559 UpdateApplicationsList(ENUM_APPLICATIONS);
560 break;
561
562 case IDS_UPDATES:
563 UpdateApplicationsList(ENUM_UPDATES);
564 break;
565
566 case IDS_AVAILABLEFORINST:
567 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
568 break;
569
570 case IDS_CAT_AUDIO:
571 UpdateApplicationsList(ENUM_CAT_AUDIO);
572 break;
573
574 case IDS_CAT_DEVEL:
575 UpdateApplicationsList(ENUM_CAT_DEVEL);
576 break;
577
578 case IDS_CAT_DRIVERS:
579 UpdateApplicationsList(ENUM_CAT_DRIVERS);
580 break;
581
582 case IDS_CAT_EDU:
583 UpdateApplicationsList(ENUM_CAT_EDU);
584 break;
585
586 case IDS_CAT_ENGINEER:
587 UpdateApplicationsList(ENUM_CAT_ENGINEER);
588 break;
589
590 case IDS_CAT_FINANCE:
591 UpdateApplicationsList(ENUM_CAT_FINANCE);
592 break;
593
594 case IDS_CAT_GAMES:
595 UpdateApplicationsList(ENUM_CAT_GAMES);
596 break;
597
598 case IDS_CAT_GRAPHICS:
599 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
600 break;
601
602 case IDS_CAT_INTERNET:
603 UpdateApplicationsList(ENUM_CAT_INTERNET);
604 break;
605
606 case IDS_CAT_LIBS:
607 UpdateApplicationsList(ENUM_CAT_LIBS);
608 break;
609
610 case IDS_CAT_OFFICE:
611 UpdateApplicationsList(ENUM_CAT_OFFICE);
612 break;
613
614 case IDS_CAT_OTHER:
615 UpdateApplicationsList(ENUM_CAT_OTHER);
616 break;
617
618 case IDS_CAT_SCIENCE:
619 UpdateApplicationsList(ENUM_CAT_SCIENCE);
620 break;
621
622 case IDS_CAT_TOOLS:
623 UpdateApplicationsList(ENUM_CAT_TOOLS);
624 break;
625
626 case IDS_CAT_VIDEO:
627 UpdateApplicationsList(ENUM_CAT_VIDEO);
628 break;
629 }
630 }
631 }
632 break;
633
634 case LVN_KEYDOWN:
635 {
636 LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN) lParam;
637
638 if (pnkd->hdr.hwndFrom == hListView)
639 {
640 INT ItemIndex = (INT) SendMessage(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
641
642 if (pnkd->wVKey == VK_UP) ItemIndex -= 1;
643 if (pnkd->wVKey == VK_DOWN) ItemIndex += 1;
644
645 if (IS_INSTALLED_ENUM(SelectedEnumType))
646 ShowInstalledAppInfo(ItemIndex);
647 if (IS_AVAILABLE_ENUM(SelectedEnumType))
648 ShowAvailableAppInfo(ItemIndex);
649 }
650 }
651 break;
652
653 case LVN_COLUMNCLICK:
654 {
655 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
656
657 (VOID) ListView_SortItems(hListView, ListViewCompareFunc, pnmv->iSubItem);
658 bAscending = !bAscending;
659 }
660 break;
661
662 case NM_CLICK:
663 if (data->hwndFrom == hListView)
664 {
665 if (IS_INSTALLED_ENUM(SelectedEnumType))
666 ShowInstalledAppInfo(-1);
667 if (IS_AVAILABLE_ENUM(SelectedEnumType))
668 ShowAvailableAppInfo(-1);
669 }
670 break;
671
672 case NM_RCLICK:
673 if (data->hwndFrom == hListView)
674 ShowPopupMenu(hListView, IDR_APPLICATIONMENU);
675 break;
676
677 case EN_LINK:
678 RichEditOnLink(hwnd, (ENLINK*)lParam);
679 break;
680
681 case TTN_GETDISPINFO:
682 ToolBarOnGetDispInfo((LPTOOLTIPTEXT)lParam);
683 break;
684 }
685 }
686 break;
687
688 case WM_PAINT:
689 break;
690
691 case WM_SIZE:
692 {
693 if ((GetClientWindowHeight(hMainWnd) - GetWindowHeight(hStatusBar) - SPLIT_WIDTH) < GetHSplitterPos())
694 {
695 INT NewSplitPos = GetClientWindowHeight(hwnd) - 100 - GetWindowHeight(hStatusBar) - SPLIT_WIDTH;
696 if (NewSplitPos > GetWindowHeight(hToolBar) + SPLIT_WIDTH)
697 SetHSplitterPos(NewSplitPos);
698 }
699
700 MainWndOnSize(hwnd, wParam, lParam);
701 }
702 break;
703
704 case WM_SIZING:
705 {
706 int RichEditHeight = GetWindowHeight(hRichEdit);
707 LPRECT pRect = (LPRECT)lParam;
708
709 while (RichEditHeight <= 100)
710 {
711 if (GetHSplitterPos() - 1 < GetWindowHeight(hToolBar) + GetWindowHeight(hListView) + SPLIT_WIDTH)
712 break;
713 SetHSplitterPos(GetHSplitterPos() - 1);
714 RichEditHeight++;
715 }
716
717 if (pRect->right-pRect->left < 565)
718 pRect->right = pRect->left + 565;
719
720 if (pRect->bottom-pRect->top < 300)
721 pRect->bottom = pRect->top + 300;
722 return TRUE;
723 }
724
725 case WM_SYSCOLORCHANGE:
726 {
727 /* Forward WM_SYSCOLORCHANGE to common controls */
728 SendMessage(hListView, WM_SYSCOLORCHANGE, 0, 0);
729 SendMessage(hTreeView, WM_SYSCOLORCHANGE, 0, 0);
730 SendMessage(hToolBar, WM_SYSCOLORCHANGE, 0, 0);
731 SendMessageW(hRichEdit, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
732 }
733 break;
734
735 case WM_DESTROY:
736 {
737 ShowWindow(hwnd, SW_HIDE);
738 SaveSettings(hwnd);
739
740 FreeLogs();
741
742 if (IS_AVAILABLE_ENUM(SelectedEnumType))
743 FreeAvailableAppList();
744 if (IS_INSTALLED_ENUM(SelectedEnumType))
745 FreeInstalledAppList();
746 if (hImageTreeView) ImageList_Destroy(hImageTreeView);
747
748 PostQuitMessage(0);
749 return 0;
750 }
751 break;
752 }
753
754 return DefWindowProc(hwnd, Msg, wParam, lParam);
755 }
756
757 int WINAPI
758 wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
759 {
760 WNDCLASSEXW WndClass = {0};
761 WCHAR szWindowClass[] = L"ROSAPPMGR";
762 WCHAR szWindowName[MAX_STR_LEN];
763 WCHAR szErrorText[MAX_STR_LEN];
764 HANDLE hMutex = NULL;
765 MSG Msg;
766
767 switch (GetUserDefaultUILanguage())
768 {
769 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
770 SetProcessDefaultLayout(LAYOUT_RTL);
771 break;
772
773 default:
774 break;
775 }
776
777 hInst = hInstance;
778
779 if (!IsUserAnAdmin())
780 {
781 LoadStringW(hInst, IDS_USER_NOT_ADMIN, szErrorText, sizeof(szErrorText) / sizeof(WCHAR));
782 MessageBox(0, szErrorText, NULL, MB_OK | MB_ICONWARNING);
783 return 1;
784 }
785
786 hMutex = CreateMutexW(NULL, FALSE, szWindowClass);
787 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
788 {
789 /* If already started, it is found its window */
790 HWND hWindow = FindWindowW(szWindowClass, NULL);
791
792 /* Activate window */
793 ShowWindow(hWindow, SW_SHOWNORMAL);
794 SetForegroundWindow(hWindow);
795 return 1;
796 }
797
798 if (!LoadSettings())
799 {
800 FillDefaultSettings(&SettingsInfo);
801 }
802
803 InitLogs();
804
805 InitCommonControls();
806
807 /* Create the window */
808 WndClass.cbSize = sizeof(WNDCLASSEXW);
809 WndClass.lpszClassName = szWindowClass;
810 WndClass.lpfnWndProc = MainWindowProc;
811 WndClass.hInstance = hInstance;
812 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
813 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
814 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
815 WndClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
816
817 if (RegisterClassExW(&WndClass) == (ATOM)0) goto Exit;
818
819 LoadStringW(hInst, IDS_APPTITLE, szWindowName, sizeof(szWindowName) / sizeof(WCHAR));
820
821 hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
822 szWindowClass,
823 szWindowName,
824 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
825 CW_USEDEFAULT,
826 CW_USEDEFAULT,
827 680,
828 450,
829 NULL,
830 NULL,
831 hInstance,
832 NULL);
833
834 if (!hMainWnd) goto Exit;
835
836 /* Show it */
837 ShowWindow(hMainWnd, SW_SHOW);
838 UpdateWindow(hMainWnd);
839
840 /* Message Loop */
841 while (GetMessage(&Msg, NULL, 0, 0))
842 {
843 TranslateMessage(&Msg);
844 DispatchMessage(&Msg);
845 }
846
847 Exit:
848 if (hMutex) CloseHandle(hMutex);
849
850 return 0;
851 }