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