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