User the user-specific date format instead of a hard-coded one.
[reactos.git] / reactos / dll / cpl / appwiz-new / appwiz.c
1 /*
2 *
3 * PROJECT: ReactOS Software Control Panel
4 * FILE: dll/cpl/appwiz/appwiz.c
5 * PURPOSE: ReactOS Software Control Panel
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 * UPDATE HISTORY:
8 * 02-09-2008 Created
9 */
10
11 #include "appwiz.h"
12
13 WCHAR* DescriptionHeadline = L"";
14 WCHAR* DescriptionText = L"";
15 HBITMAP hUnderline;
16 WCHAR Strings[2][256];
17 HICON hSearchIcon;
18 HTREEITEM hRootItem; // First item in actions list
19 HFONT hMainFont;
20 HIMAGELIST hImageAppList; // Image list for programs list
21 BOOL bAscending = TRUE; // Sorting programs list
22
23 HDC BackbufferHdc = NULL;
24 HBITMAP BackbufferBmp = NULL;
25
26
27 VOID
28 ShowMessage(WCHAR* title, WCHAR* message)
29 {
30 DescriptionHeadline = title;
31 DescriptionText = message;
32 InvalidateRect(hMainWnd,NULL,TRUE);
33 UpdateWindow(hMainWnd);
34 }
35
36 static VOID
37 DrawBitmap(HDC hdc, int x, int y, HBITMAP hBmp)
38 {
39 BITMAP bm;
40 HDC hdcMem = CreateCompatibleDC(hdc);
41
42 SelectObject(hdcMem, hBmp);
43 GetObject(hBmp, sizeof(bm), &bm);
44 TransparentBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, 0xFFFFFF);
45
46 DeleteDC(hdcMem);
47 }
48
49 static VOID
50 DrawDescription(HDC hdc, RECT DescriptionRect)
51 {
52 int i;
53 HFONT Font;
54 RECT Rect = {DescriptionRect.left+5, DescriptionRect.top+5, DescriptionRect.right-2, DescriptionRect.top+22};
55
56 // Backgroud
57 Rectangle(hdc, DescriptionRect.left, DescriptionRect.top, DescriptionRect.right, DescriptionRect.bottom);
58
59 // Underline
60 for (i=DescriptionRect.left+1;i<DescriptionRect.right-1;i++)
61 DrawBitmap(hdc, i, DescriptionRect.top+22, hUnderline); // less code then stretching ;)
62
63 // Headline
64 Font = CreateFont(-14, 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
65 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Arial");
66 SelectObject(hdc, Font);
67 DrawText(hdc, DescriptionHeadline, lstrlen(DescriptionHeadline), &Rect, DT_SINGLELINE|DT_NOPREFIX);
68 DeleteObject(Font);
69
70 // Description
71 Font = CreateFont(-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
72 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Arial");
73 SelectObject(hdc, Font);
74 Rect.top += 35;
75 Rect.bottom = DescriptionRect.bottom-2;
76 DrawText(hdc, DescriptionText, lstrlen(DescriptionText), &Rect, DT_WORDBREAK|DT_NOPREFIX); // ToDo: Call TabbedTextOut to draw a nice table
77 DeleteObject(Font);
78 }
79
80 static VOID
81 ResizeControl(HWND hwnd, int x1, int y1, int x2, int y2)
82 {
83 MoveWindow(hwnd, x1, y1, x2-x1, y2-y1, TRUE);
84 }
85
86 /*
87 AddListColumn - adding column items to Application list
88 */
89 static VOID
90 AddListColumn(VOID)
91 {
92 LV_COLUMN column;
93 RECT rect;
94 WCHAR szBuf[MAX_PATH];
95
96 GetClientRect(hMainWnd, &rect);
97 ZeroMemory(&column, sizeof(LV_COLUMN));
98 column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
99 column.fmt = LVCFMT_LEFT;
100 column.iSubItem = 0;
101 LoadString(hApplet, IDS_LIST_TITLE, szBuf, sizeof(szBuf) / sizeof(WCHAR));
102 column.pszText = szBuf;
103 column.cx = 320;
104 (void)ListView_InsertColumn(hAppList, 0, &column);
105
106 column.cx = 75;
107 column.iSubItem = 1;
108 LoadString(hApplet, IDS_LAST_USED, szBuf, sizeof(szBuf) / sizeof(WCHAR));
109 column.pszText = szBuf;
110 (void)ListView_InsertColumn(hAppList,1,&column);
111
112 column.cx = 70;
113 column.iSubItem = 2;
114 column.fmt = LVCFMT_RIGHT;
115 LoadString(hApplet, IDS_SIZE_TITLE, szBuf, sizeof(szBuf) / sizeof(WCHAR));
116 column.pszText = szBuf;
117 (void)ListView_InsertColumn(hAppList,2,&column);
118 }
119
120 static VOID
121 AddTreeViewItems(VOID)
122 {
123 HIMAGELIST hImageList;
124 WCHAR szBuf[1024];
125 int Index[2];
126 TV_INSERTSTRUCTW Insert;
127
128 hImageList = ImageList_Create(16, 16, ILC_COLORDDB, 1, 1);
129 SendMessageW(hActList, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList);
130
131 Index[0] = ImageList_Add(hImageList, LoadBitmap(hApplet, MAKEINTRESOURCE(IDB_SELECT)), NULL);
132 Index[1] = ImageList_Add(hImageList, LoadBitmap(hApplet, MAKEINTRESOURCE(IDB_ICON)), NULL);
133
134 // Insert items to Actions List
135 ZeroMemory(&Insert, sizeof(TV_INSERTSTRUCT));
136 Insert.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
137 Insert.hInsertAfter = TVI_LAST;
138 Insert.hParent = TVI_ROOT;
139 Insert.item.iSelectedImage = Index[0];
140
141 Insert.item.lParam = 0;
142 LoadString(hApplet, IDS_PROGANDUPDATES, szBuf, sizeof(szBuf) / sizeof(WCHAR));
143 Insert.item.pszText = szBuf;
144 Insert.item.iImage = Index[1];
145 hRootItem = TreeView_InsertItem(hActList, &Insert);
146
147 Insert.item.lParam = 1;
148 LoadString(hApplet, IDS_PROGRAMS_ONLY, szBuf, sizeof(szBuf) / sizeof(WCHAR));
149 Insert.item.pszText = szBuf;
150 Insert.item.iImage = Index[1];
151 (VOID) TreeView_InsertItem(hActList, &Insert);
152
153 Insert.item.lParam = 2;
154 LoadString(hApplet, IDS_UPDATES_ONLY, szBuf, sizeof(szBuf) / sizeof(WCHAR));
155 Insert.item.pszText = szBuf;
156 Insert.item.iImage = Index[1];
157 (VOID) TreeView_InsertItem(hActList, &Insert);
158 // Select first item
159 (VOID) TreeView_SelectItem(hActList, hRootItem);
160 }
161
162 /*
163 InitControls - function for init all controls on main window
164 */
165 static VOID
166 InitControls(VOID)
167 {
168 WCHAR szBuf[1024];
169
170 hMainFont = CreateFont(-11 , 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
171 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Arial");
172
173 hActList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEWW, L"",
174 WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS,
175 0, 0, 0, 0, hMainWnd, NULL, hApplet, NULL);
176
177 hAppList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEWW, L"",
178 WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_SORTASCENDING|LVS_REPORT,
179 0, 0, 0, 0, hMainWnd, NULL, hApplet, NULL);
180
181 (VOID) ListView_SetExtendedListViewStyle(hAppList, LVS_EX_FULLROWSELECT);
182
183 LoadString(hApplet, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
184 hSearch = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", szBuf, WS_CHILD|WS_VISIBLE|WS_BORDER|ES_LEFT,
185 0, 0, 0, 0, hMainWnd, NULL, hApplet, NULL);
186 SendMessage(hSearch, WM_SETFONT, (WPARAM)hMainFont, 0);
187 // Remove button
188 LoadString(hApplet, IDS_REMOVE_BTN, szBuf, sizeof(szBuf) / sizeof(WCHAR));
189 hRemoveBtn = CreateWindowEx(0, L"BUTTON", szBuf, WS_CHILD|WS_VISIBLE|WS_DISABLED|BS_TEXT,
190 0, 0, 0, 0, hMainWnd, NULL, hApplet, NULL);
191 SendMessage(hRemoveBtn, WM_SETFONT, (WPARAM)hMainFont, 0);
192 // Modify button
193 LoadString(hApplet, IDS_MODIFY_BTN, szBuf, sizeof(szBuf) / sizeof(WCHAR));
194 hModifyBtn = CreateWindowEx(0, L"BUTTON", szBuf, WS_CHILD|WS_VISIBLE|WS_DISABLED|BS_TEXT,
195 0, 0, 0, 0, hMainWnd, NULL, hApplet, NULL);
196 SendMessage(hModifyBtn, WM_SETFONT, (WPARAM)hMainFont, 0);
197
198 hUnderline = LoadBitmap(hApplet, MAKEINTRESOURCE(IDB_UNDERLINE));
199 hSearchIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_SEARCH));
200
201 AddListColumn();
202 AddTreeViewItems();
203 }
204
205 /*
206 GetARPInfo - Getting information from ARP cache
207 Input: szName - Application Name
208 Output: szPath - Path to image file
209 szSize - Application size
210 szLastUsed - Last used time
211 */
212 static VOID
213 GetARPInfo(LPCWSTR szName, LPWSTR szPath, LPWSTR szSize, LPWSTR szLastUsed)
214 {
215 APPARPINFO aai = {0};
216 DWORD dwSize = sizeof(aai), dwType = REG_BINARY;
217 SYSTEMTIME systime, localtime;
218 WCHAR szBuf[MAX_PATH];
219 HKEY hKey;
220
221 swprintf(szBuf, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Management\\ARPCache\\%s", szName);
222 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf,
223 0, KEY_READ, &hKey) == ERROR_SUCCESS)
224 {
225 ZeroMemory(&aai, sizeof(APPARPINFO));
226 if ((RegQueryValueEx(hKey, L"SlowInfoCache", NULL, &dwType, (LPBYTE)&aai, &dwSize) == ERROR_SUCCESS) &&
227 (aai.Size == sizeof(APPARPINFO)))
228 {
229 // Getting path to image
230 wcscpy(szPath, aai.ImagePath);
231
232 // Getting application size
233 if (aai.AppSize < (ULONGLONG) 2000000000)
234 {
235 swprintf(szSize, L"%.2f", (float)aai.AppSize/(1024*1024));
236 }
237 else wcscpy(szSize,L"---");
238
239 // Getting last used
240 if (FileTimeToSystemTime(&aai.LastUsed, &systime))
241 {
242 if (SystemTimeToTzSpecificLocalTime(NULL, &systime, &localtime))
243 {
244 if (((int)localtime.wYear > 1900) && ((int)localtime.wYear < 3000))
245 {
246 GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &localtime,
247 NULL, szLastUsed, 256);
248 }
249 else wcscpy(szLastUsed,L"---");
250 }
251 else wcscpy(szLastUsed,L"---");
252 }
253 else wcscpy(szLastUsed,L"---");
254 }
255 else
256 {
257 wcscpy(szPath,L"---");
258 wcscpy(szSize,L"---");
259 wcscpy(szLastUsed,L"---");
260 }
261 }
262 RegCloseKey(hKey);
263 }
264
265 /*
266 AddItemToList - create application list
267
268 hSubKey - handle to the sub key for adding to LPARAM
269 szDisplayName - display name
270 ItemIndex - item index
271 AppName - application name (for getting ARPCache info)
272 */
273 static VOID
274 AddItemToList(LPARAM hSubKey, LPWSTR szDisplayName, INT ItemIndex, LPWSTR AppName)
275 {
276 int index;
277 HICON hIcon = NULL;
278 LV_ITEM listItem;
279 WCHAR IconPath[MAX_PATH], AppSize[256], LastUsed[256];
280 int iIndex;
281
282 GetARPInfo(AppName, IconPath, AppSize, LastUsed);
283
284 if (GetFileAttributes(IconPath) != 0xFFFFFFFF)
285 {
286 // FIXME: This function not getting 32-bits icon
287 ExtractIconEx(IconPath, 0, NULL, &hIcon, 1);
288 }
289
290 if (hIcon == NULL)
291 {
292 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
293 }
294 index = ImageList_AddIcon(hImageAppList, hIcon);
295 DestroyIcon(hIcon);
296
297 ZeroMemory(&listItem, sizeof(LV_ITEM));
298 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
299 listItem.pszText = (LPTSTR)szDisplayName;
300 listItem.lParam = (LPARAM)hSubKey;
301 listItem.iItem = (int)ItemIndex;
302 listItem.iImage = index;
303 iIndex = ListView_InsertItem(hAppList, &listItem);
304 ListView_SetItemText(hAppList, iIndex, 1, LastUsed);
305 ListView_SetItemText(hAppList, iIndex, 2, AppSize);
306 }
307
308 /*
309 ShowMode:
310 if ShowMode = 0 - programs and updates
311 if ShowMode = 1 - show programs only
312 if ShowMode = 2 - show updates only
313 */
314 static VOID
315 FillSoftwareList(INT ShowMode)
316 {
317 WCHAR pszName[MAX_PATH];
318 WCHAR pszDisplayName[MAX_PATH];
319 WCHAR pszParentKeyName[MAX_PATH];
320 FILETIME FileTime;
321 HKEY hKey;
322 HKEY hSubKey;
323 DWORD dwType;
324 DWORD dwSize = MAX_PATH;
325 DWORD dwValue = 0;
326 BOOL bIsUpdate = FALSE;
327 BOOL bIsSystemComponent = FALSE;
328 INT ItemIndex = 0;
329 DEVMODE pDevMode;
330 int ColorDepth;
331
332 (VOID) ImageList_Destroy(hImageAppList);
333 (VOID) ListView_DeleteAllItems(hAppList);
334
335 pDevMode.dmSize = sizeof(DEVMODE);
336 pDevMode.dmDriverExtra = 0;
337 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode);
338 switch (pDevMode.dmBitsPerPel)
339 {
340 case 32: ColorDepth = ILC_COLOR32; break;
341 case 24: ColorDepth = ILC_COLOR24; break;
342 case 16: ColorDepth = ILC_COLOR16; break;
343 case 8: ColorDepth = ILC_COLOR8; break;
344 case 4: ColorDepth = ILC_COLOR4; break;
345 default: ColorDepth = ILC_COLOR; break;
346 }
347
348 hImageAppList = ImageList_Create(16, 16, ColorDepth | ILC_MASK, 0, 1);
349 SendMessage(hAppList, WM_SETREDRAW, FALSE, 0);
350
351 if (RegOpenKey(HKEY_LOCAL_MACHINE,
352 L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
353 &hKey) != ERROR_SUCCESS)
354 {
355 WCHAR Buf[256];
356
357 LoadString(hApplet, IDS_UNABLEOPEN_UNINSTKEY, Buf, sizeof(Buf) / sizeof(WCHAR));
358 MessageBox(hMainWnd, Buf, NULL, MB_ICONWARNING);
359 return;
360 }
361
362 ItemIndex = 0;
363 dwSize = MAX_PATH;
364 while (RegEnumKeyEx(hKey, ItemIndex, pszName, &dwSize, NULL, NULL, NULL, &FileTime) == ERROR_SUCCESS)
365 {
366 if (RegOpenKey(hKey,pszName,&hSubKey) == ERROR_SUCCESS)
367 {
368 dwType = REG_DWORD;
369 dwSize = sizeof(DWORD);
370 if (RegQueryValueEx(hSubKey, L"SystemComponent",
371 NULL, &dwType,
372 (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
373 {
374 bIsSystemComponent = (dwValue == 0x1);
375 }
376 else
377 {
378 bIsSystemComponent = FALSE;
379 }
380
381 dwType = REG_SZ;
382 dwSize = MAX_PATH;
383 bIsUpdate = (RegQueryValueEx(hSubKey, L"ParentKeyName",
384 NULL, &dwType,
385 (LPBYTE)pszParentKeyName,
386 &dwSize) == ERROR_SUCCESS);
387 dwSize = MAX_PATH;
388 if (RegQueryValueEx(hSubKey, L"DisplayName",
389 NULL, &dwType,
390 (LPBYTE)pszDisplayName,
391 &dwSize) == ERROR_SUCCESS)
392 {
393 if ((ShowMode < 0)||(ShowMode > 2)) ShowMode = 0;
394 if (!bIsSystemComponent)
395 {
396 if (ShowMode == 0)
397 {
398 AddItemToList((LPARAM)hSubKey, (LPWSTR)pszDisplayName, ItemIndex, pszName);
399 }
400 if ((ShowMode == 1)&&(!bIsUpdate))
401 {
402 AddItemToList((LPARAM)hSubKey, (LPWSTR)pszDisplayName, ItemIndex, pszName);
403 }
404 if ((ShowMode == 2)&&(bIsUpdate))
405 {
406 AddItemToList((LPARAM)hSubKey, (LPWSTR)pszDisplayName, ItemIndex, pszName);
407 }
408 }
409 }
410 }
411
412 dwSize = MAX_PATH;
413 ItemIndex++;
414 }
415
416 (VOID) ListView_SetImageList(hAppList, hImageAppList, LVSIL_SMALL);
417 SendMessage(hAppList, WM_SETREDRAW, TRUE, 0);
418 RegCloseKey(hSubKey);
419 RegCloseKey(hKey);
420 }
421
422 static BOOL
423 GetAppString(LPCWSTR lpKeyName, LPWSTR lpString)
424 {
425 HKEY hKey;
426 INT nIndex;
427 DWORD dwSize;
428 DWORD dwType = REG_SZ;
429
430 nIndex = (INT)SendMessage(hAppList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED);
431 if (nIndex != -1)
432 {
433 LVITEM item;
434
435 ZeroMemory(&item, sizeof(LVITEM));
436 item.mask = LVIF_PARAM;
437 item.iItem = nIndex;
438 (VOID) ListView_GetItem(hAppList,&item);
439 hKey = (HKEY)item.lParam;
440
441 if (RegQueryValueEx(hKey, lpKeyName, NULL, &dwType,
442 (LPBYTE)lpString, &dwSize) == ERROR_SUCCESS)
443 {
444 return TRUE;
445 }
446 }
447 return FALSE;
448 }
449
450 static VOID
451 CallUninstall(VOID)
452 {
453 INT nIndex;
454 HKEY hKey;
455 DWORD dwType, dwRet;
456 WCHAR pszUninstallString[MAX_PATH];
457 DWORD dwSize;
458 MSG msg;
459
460 nIndex = (INT)SendMessage(hAppList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED);
461 if (nIndex != -1)
462 {
463 LVITEM item;
464
465 ZeroMemory(&item, sizeof(LVITEM));
466 item.mask = LVIF_PARAM;
467 item.iItem = nIndex;
468 (VOID) ListView_GetItem(hAppList,&item);
469 hKey = (HKEY)item.lParam;
470
471 dwType = REG_SZ;
472 dwSize = MAX_PATH;
473 if (RegQueryValueEx(hKey, L"UninstallString", NULL, &dwType,
474 (LPBYTE)pszUninstallString, &dwSize) == ERROR_SUCCESS)
475 {
476 STARTUPINFO si;
477 PROCESS_INFORMATION pi;
478
479 ZeroMemory(&si, sizeof(si));
480 si.cb = sizeof(si);
481 si.wShowWindow = SW_SHOW;
482 if (CreateProcess(NULL,pszUninstallString,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
483 {
484 CloseHandle(pi.hThread);
485 EnableWindow(hMainWnd, FALSE);
486
487 for (;;)
488 {
489 dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS);
490 if (dwRet == WAIT_OBJECT_0 + 1)
491 {
492 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
493 {
494 TranslateMessage(&msg);
495 DispatchMessage(&msg);
496 }
497 }
498 else if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED)
499 break;
500 }
501 CloseHandle(pi.hProcess);
502
503 EnableWindow(hMainWnd, TRUE);
504 // Disable all buttons
505 EnableWindow(hRemoveBtn,FALSE);
506 EnableWindow(hModifyBtn,FALSE);
507 // Update software list
508 FillSoftwareList(0);
509 SetActiveWindow(hMainWnd);
510 }
511 }
512 else
513 {
514 WCHAR szBuf[256];
515
516 LoadString(hApplet, IDS_UNABLEREAD_UNINSTSTR, szBuf, sizeof(szBuf) / sizeof(WCHAR));
517 MessageBox(hMainWnd, szBuf, NULL, MB_ICONWARNING);
518 }
519 }
520 }
521
522 static VOID
523 ShowPopupMenu(HWND hwndDlg, INT xPos, INT yPos)
524 {
525 INT nIndex;
526 nIndex = (INT)SendMessage(hAppList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED);
527 if ( nIndex != -1)
528 {
529 POINT pt;
530 RECT lvRect;
531 HMENU hMenu;
532
533 GetCursorPos(&pt);
534
535 GetWindowRect(hAppList, &lvRect);
536 if (PtInRect(&lvRect, pt))
537 {
538 hMenu = GetSubMenu(LoadMenu(hApplet, MAKEINTRESOURCE(IDR_POPUP_APP)),0);
539 TrackPopupMenuEx(hMenu, TPM_RIGHTBUTTON, xPos, yPos, hwndDlg, NULL);
540 DestroyMenu(hMenu);
541 }
542 }
543 }
544
545 static VOID
546 GetAppInfo(LPWSTR lpInfo)
547 {
548 WCHAR szBuf[1024], szDesc[1024];
549 INT iIndex;
550 HKEY hKey;
551
552 iIndex = SendMessage(hAppList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
553 if (iIndex != -1)
554 {
555 LVITEM item;
556 DWORD dwSize = 2048;
557
558 ZeroMemory(&item, sizeof(LVITEM));
559 item.mask = LVIF_PARAM;
560 item.iItem = iIndex;
561 (VOID) ListView_GetItem(hAppList,&item);
562 hKey = (HKEY)item.lParam;
563
564 wcscpy(lpInfo,L"\0");
565 if (RegQueryValueEx(hKey, L"Publisher", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
566 {
567 LoadString(hApplet, IDS_INF_PUBLISHER, szDesc, sizeof(szDesc) / sizeof(WCHAR));
568 //wcscat(lpInfo, szDesc);
569 swprintf(lpInfo, L"%s%s\n", szDesc, szBuf);
570 }
571 if (RegQueryValueEx(hKey, L"RegOwner", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
572 {
573 LoadString(hApplet, IDS_INF_REG_OWNER, szDesc, sizeof(szDesc) / sizeof(WCHAR));
574 wcscat(lpInfo, szDesc);
575 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
576 }
577 if (RegQueryValueEx(hKey, L"ProductID", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
578 {
579 LoadString(hApplet, IDS_INF_PRODUCT_ID, szDesc, sizeof(szDesc) / sizeof(WCHAR));
580 wcscat(lpInfo, szDesc);
581 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
582 }
583 if (RegQueryValueEx(hKey, L"DisplayVersion", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
584 {
585 LoadString(hApplet, IDS_INF_VERSION, szDesc, sizeof(szDesc) / sizeof(WCHAR));
586 wcscat(lpInfo, szDesc);
587 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
588 }
589 if (RegQueryValueEx(hKey, L"Contact", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
590 {
591 LoadString(hApplet, IDS_INF_CONTACT, szDesc, sizeof(szDesc) / sizeof(WCHAR));
592 wcscat(lpInfo, szDesc);
593 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
594 }
595 if (RegQueryValueEx(hKey, L"HelpLink", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
596 {
597 LoadString(hApplet, IDS_INF_SUP_INFO, szDesc, sizeof(szDesc) / sizeof(WCHAR));
598 wcscat(lpInfo, szDesc);
599 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
600 }
601 if (RegQueryValueEx(hKey, L"HelpTelephone", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
602 {
603 LoadString(hApplet, IDS_INF_SUP_PHONE, szDesc, sizeof(szDesc) / sizeof(WCHAR));
604 wcscat(lpInfo, szDesc);
605 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
606 }
607 if (RegQueryValueEx(hKey, L"URLUpdateInfo", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
608 {
609 LoadString(hApplet, IDS_INF_PRODUCT_UPD, szDesc, sizeof(szDesc) / sizeof(WCHAR));
610 wcscat(lpInfo, szDesc);
611 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
612 }
613 if (RegQueryValueEx(hKey, L"Readme", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
614 {
615 LoadString(hApplet, IDS_INF_README, szDesc, sizeof(szDesc) / sizeof(WCHAR));
616 wcscat(lpInfo, szDesc);
617 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
618 }
619 if (RegQueryValueEx(hKey, L"Comments", NULL, NULL, (LPBYTE)szBuf, &dwSize) == ERROR_SUCCESS)
620 {
621 LoadString(hApplet, IDS_INF_COMMENTS, szDesc, sizeof(szDesc) / sizeof(WCHAR));
622 wcscat(lpInfo, szDesc);
623 swprintf(lpInfo,L"%s%s\n", lpInfo, szBuf);
624 }
625 if (wcslen(lpInfo) < 10)
626 {
627 LoadString(hApplet, IDS_NO_INFORMATION, szDesc, sizeof(szDesc) / sizeof(WCHAR));
628 wcscpy(lpInfo, szDesc);
629 }
630 }
631 }
632
633 static VOID
634 ShowAppInfo(VOID)
635 {
636 WCHAR Info[2048], szBuf[1024];
637
638 if (-1 != (INT) SendMessage(hAppList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED))
639 {
640 GetAppInfo(Info);
641 ListView_GetItemText(hAppList, SendMessage(hAppList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED), 0, szBuf, sizeof(szBuf));
642 ShowMessage(szBuf, Info);
643 }
644 }
645
646 static VOID
647 GetListItemText(LPARAM lParam1, LPARAM lParam2, INT iSubItem, LPWSTR Item1, LPWSTR Item2)
648 {
649 LVFINDINFO find;
650 INT iIndex;
651
652 find.flags = LVFI_PARAM;
653
654 find.lParam = lParam1;
655 iIndex = ListView_FindItem(hAppList, -1, &find);
656 ListView_GetItemText(hAppList, iIndex, iSubItem, Item1, sizeof(Item1));
657
658 find.lParam = lParam2;
659 iIndex = ListView_FindItem(hAppList, -1, &find);
660 ListView_GetItemText(hAppList, iIndex, iSubItem, Item2, sizeof(Item2));
661 }
662
663 static INT CALLBACK
664 CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
665 {
666 WCHAR szItem1[MAX_PATH], szItem2[MAX_PATH];
667
668 switch ((INT)lParamSort)
669 {
670 case 0: // Name
671 {
672 GetListItemText(lParam1, lParam2, 0, szItem1, szItem2);
673 if (bAscending == TRUE)
674 return wcscmp(szItem2, szItem1);
675 else
676 return wcscmp(szItem1, szItem2);
677 }
678 case 1: // Date
679 GetListItemText(lParam1, lParam2, 1, szItem1, szItem2);
680 if (bAscending == TRUE)
681 return wcscmp(szItem2, szItem1);
682 else
683 return wcscmp(szItem1, szItem2);
684 case 2: // Size
685 {
686 // FIXME: No correct sorting by application size
687 INT Size1, Size2;
688
689 GetListItemText(lParam1, lParam2, 2, szItem1, szItem2);
690 if (wcscmp(szItem1, L"---") == 0) wcscpy(szItem1, L"0");
691 if (wcscmp(szItem2, L"---") == 0) wcscpy(szItem2, L"0");
692 Size1 = _wtoi(szItem1);
693 Size2 = _wtoi(szItem2);
694 if (Size1 < Size2)
695 {
696 return (bAscending ? -1 : 1);
697 }
698 else if (Size1 == Size2)
699 {
700 return 0;
701 }
702 else if (Size1 > Size2)
703 {
704 return (bAscending ? 1 : -1);
705 }
706 }
707 }
708
709 return 0;
710 }
711
712 static BOOL
713 LoadSettings(VOID)
714 {
715 HKEY hKey;
716 DWORD dwSize;
717 BOOL Ret;
718
719 if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\ReactOS\\AppWiz", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
720 {
721 dwSize = sizeof(APPWIZSETTINGS);
722 if (RegQueryValueEx(hKey, L"Settings", NULL, NULL, (LPBYTE)&AppWizSettings, &dwSize) == ERROR_SUCCESS)
723 {
724 Ret = (AppWizSettings.Size == sizeof(APPWIZSETTINGS));
725 }
726 else Ret = FALSE;
727 }
728 else Ret = FALSE;
729
730 RegCloseKey(hKey);
731 return Ret;
732 }
733
734 static BOOL
735 SaveSettings(VOID)
736 {
737 HKEY hKey;
738 BOOL Ret;
739
740 if (RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\ReactOS\\AppWiz", 0, NULL,
741 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
742 {
743 AppWizSettings.Size = sizeof(APPWIZSETTINGS);
744 Ret = (RegSetValueEx(hKey, L"Settings", 0, REG_BINARY, (LPBYTE)&AppWizSettings, sizeof(APPWIZSETTINGS)) == ERROR_SUCCESS);
745 }
746 else Ret = FALSE;
747
748 RegCloseKey(hKey);
749 return Ret;
750 }
751
752 static void UpdateBitmap(HWND hWnd, RECT WndRect, RECT DescriptionRect)
753 {
754 HDC hdc = GetDC(hWnd);
755
756 if (!BackbufferHdc)
757 BackbufferHdc = CreateCompatibleDC(hdc);
758
759 if (BackbufferBmp)
760 DeleteObject(BackbufferBmp);
761
762 BackbufferBmp = CreateCompatibleBitmap(hdc, WndRect.right, WndRect.bottom);
763
764 SelectObject(BackbufferHdc, BackbufferBmp);
765 FillRect(BackbufferHdc, &WndRect, (HBRUSH)COLOR_APPWORKSPACE);
766 DrawIconEx(BackbufferHdc, 153, 1, hSearchIcon, 24, 24, 0, NULL, DI_NORMAL|DI_COMPAT);
767 DrawDescription(BackbufferHdc, DescriptionRect);
768
769 ReleaseDC(hWnd, hdc);
770 }
771
772 static LRESULT CALLBACK
773 WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
774 {
775 static RECT DescriptionRect;
776 static RECT AppRect;
777 WCHAR szBuf[1024];
778
779 switch (Message)
780 {
781 case WM_CREATE:
782 {
783 hMainWnd = hwnd;
784 MoveWindow(hMainWnd, AppWizSettings.Left, AppWizSettings.Top,
785 AppWizSettings.Right - AppWizSettings.Left,
786 AppWizSettings.Bottom - AppWizSettings.Top, TRUE);
787 if (AppWizSettings.Maximized) ShowWindow(hMainWnd, SW_MAXIMIZE);
788 ShowMessage(Strings[0],Strings[1]); // Welcome message
789 InitControls();
790 }
791 break;
792 case WM_COMMAND:
793 {
794 switch (LOWORD(wParam))
795 {
796 case ID_APP_REMOVE:
797 CallUninstall();
798 break;
799 }
800 if(HIWORD(wParam) == BN_CLICKED)
801 {
802 if (lParam == (LPARAM)hRemoveBtn)
803 {
804 CallUninstall();
805 }
806 }
807 if (lParam == (LPARAM)hSearch)
808 {
809 switch (HIWORD(wParam))
810 {
811 case EN_SETFOCUS:
812 {
813 WCHAR Tmp[1024];
814
815 LoadString(hApplet, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
816 GetWindowText(hSearch, Tmp, 1024);
817 if (wcscmp(szBuf, Tmp) == 0) SetWindowText(hSearch, L"");
818 }
819 break;
820 case EN_KILLFOCUS:
821 {
822 GetWindowText(hSearch, szBuf, 1024);
823 if (wcslen(szBuf) < 1)
824 {
825 LoadString(hApplet, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
826 SetWindowText(hSearch, szBuf);
827 }
828 }
829 break;
830 case EN_CHANGE:
831 break;
832 }
833 }
834 }
835 break;
836 case WM_PAINT:
837 {
838 PAINTSTRUCT ps;
839 HDC hdc = BeginPaint(hwnd, &ps);
840 BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, BackbufferHdc, 0, 0, SRCCOPY);
841 EndPaint(hwnd, &ps);
842 }
843 break;
844 case WM_NOTIFY:
845 {
846 LPNMHDR data = (LPNMHDR)lParam;
847
848 switch (data->code)
849 {
850 case TVN_SELCHANGED:
851 if(data->hwndFrom == hActList)
852 {
853 // Add items to programs list
854 FillSoftwareList(((LPNMTREEVIEW)lParam)->itemNew.lParam);
855 // Set default titile and message
856 ShowMessage(Strings[0], Strings[1]);
857 // Disable all buttons
858 EnableWindow(hRemoveBtn, FALSE);
859 EnableWindow(hModifyBtn, FALSE);
860 }
861 break;
862 case NM_CLICK:
863 if(data->hwndFrom == hAppList)
864 {
865 if (-1 != (INT) SendMessage(hAppList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED))
866 {
867 EnableWindow(hRemoveBtn, TRUE);
868 if (GetAppString(L"ModifyPath", NULL))
869 EnableWindow(hModifyBtn, TRUE);
870 }
871 ShowAppInfo();
872 UpdateBitmap(hwnd, AppRect, DescriptionRect);
873 InvalidateRect(hwnd, &DescriptionRect, FALSE);
874 }
875 break;
876 case NM_DBLCLK:
877 if(data->hwndFrom == hAppList)
878 {
879 if (-1 != (INT) SendMessage(hAppList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED))
880 {
881 CallUninstall();
882 }
883 }
884 break;
885 case LVN_COLUMNCLICK:
886 {
887 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
888 (VOID) ListView_SortItems(hAppList, CompareFunc, pnmv->iSubItem);
889 bAscending = !bAscending;
890 }
891 break;
892 }
893 }
894 break;
895 case WM_SIZING:
896 {
897 LPRECT pRect = (LPRECT)lParam;
898 if (pRect->right-pRect->left < 520)
899 pRect->right = pRect->left + 520;
900
901 if (pRect->bottom-pRect->top < 400)
902 pRect->bottom = pRect->top + 400;
903 }
904 break;
905 case WM_SIZE:
906 {
907 RECT Rect = {1, HIWORD(lParam)-178, LOWORD(lParam)-1, HIWORD(lParam)-1};
908 SetRect(&AppRect, 0, 0, LOWORD(lParam)-1, HIWORD(lParam)-1);
909 DescriptionRect = Rect;
910
911 // Actions list
912 ResizeControl(hActList, 0, 1, 150, HIWORD(lParam)-180);
913
914 // Applications list
915 ResizeControl(hAppList, 152, 25, LOWORD(lParam), HIWORD(lParam)-180);
916
917 // Search Edit
918 ResizeControl(hSearch, 180, 1, LOWORD(lParam), 25);
919
920 // Buttons
921 MoveWindow(hRemoveBtn, LOWORD(lParam)-105, HIWORD(lParam)-30, 100, 25, TRUE); // Remove button
922 MoveWindow(hModifyBtn, LOWORD(lParam)-208, HIWORD(lParam)-30, 100, 25, TRUE); // Modify button
923
924 (VOID) ListView_SetColumnWidth(hAppList, 0, LOWORD(lParam)-330);
925
926 // Update title and info
927 ShowAppInfo();
928 UpdateBitmap(hwnd, AppRect, DescriptionRect);
929 InvalidateRect(hwnd, &DescriptionRect, FALSE);
930 }
931 break;
932 case WM_ACTIVATEAPP:
933 ShowAppInfo();
934 break;
935 case WM_CONTEXTMENU:
936 {
937 // Show popup menu for programs list
938 ShowPopupMenu(hwnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
939 }
940 break;
941 case WM_DESTROY:
942 {
943 WINDOWPLACEMENT wp;
944
945 // Save settings
946 ShowWindow(hMainWnd, SW_HIDE);
947 wp.length = sizeof(WINDOWPLACEMENT);
948 GetWindowPlacement(hMainWnd, &wp);
949 AppWizSettings.Left = wp.rcNormalPosition.left;
950 AppWizSettings.Top = wp.rcNormalPosition.top;
951 AppWizSettings.Right = wp.rcNormalPosition.right;
952 AppWizSettings.Bottom = wp.rcNormalPosition.bottom;
953 AppWizSettings.Maximized = (IsZoomed(hMainWnd) || (wp.flags & WPF_RESTORETOMAXIMIZED));
954 SaveSettings();
955 // Destroy all and quit
956 if (BackbufferHdc)
957 DeleteDC(BackbufferHdc);
958 if (BackbufferBmp)
959 DeleteObject(BackbufferBmp);
960 DeleteObject(hMainFont);
961 DeleteObject(hSearchIcon);
962 PostQuitMessage(0);
963 }
964 break;
965 }
966 return DefWindowProc(hwnd, Message, wParam, lParam);
967 }
968
969 static VOID
970 InitSettings(VOID)
971 {
972 if (!LoadSettings())
973 {
974 AppWizSettings.Maximized = FALSE;
975 AppWizSettings.Left = 0;
976 AppWizSettings.Top = 0;
977 AppWizSettings.Right = 520;
978 AppWizSettings.Bottom = 400;
979 }
980 }
981
982 static INT
983 MainWindowCreate(VOID)
984 {
985 WNDCLASS WndClass = {0};
986 MSG msg;
987 WCHAR szBuf[256];
988
989 // Load welcome strings
990 LoadString(hApplet, IDS_WELCOME_TITLE, Strings[0], sizeof(szBuf) / sizeof(WCHAR));
991 LoadString(hApplet, IDS_WELCOME_MSG, Strings[1], sizeof(szBuf) / sizeof(WCHAR));
992
993 InitSettings();
994
995 // Create the window
996 WndClass.lpszClassName = L"rosappwiz";
997 WndClass.lpfnWndProc = (WNDPROC)WndProc;
998 WndClass.hInstance = hApplet;
999 WndClass.style = CS_HREDRAW | CS_VREDRAW;
1000 WndClass.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM));
1001 WndClass.hCursor = LoadCursor(hApplet, IDC_ARROW);
1002 WndClass.hbrBackground = (HBRUSH)COLOR_BTNFACE + 1;
1003
1004 if (!RegisterClass(&WndClass)) return 0;
1005
1006 LoadString(hApplet, IDS_CPLSYSTEMNAME, szBuf, 256);
1007 hMainWnd = CreateWindow(L"rosappwiz", szBuf,
1008 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE | WS_CAPTION,
1009 CW_USEDEFAULT, CW_USEDEFAULT,
1010 0, 0, NULL, NULL, hApplet, NULL);
1011
1012 // Show it
1013 ShowWindow(hMainWnd, SW_SHOW);
1014 UpdateWindow(hMainWnd);
1015
1016 // Message Loop
1017 while(GetMessage(&msg,NULL,0,0))
1018 {
1019 TranslateMessage(&msg);
1020 DispatchMessage(&msg);
1021 }
1022
1023 return 0;
1024 }
1025
1026 /* Control Panel Callback */
1027 LONG CALLBACK
1028 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
1029 {
1030 CPLINFO *CPlInfo;
1031 DWORD i;
1032
1033 UNREFERENCED_PARAMETER(hwndCPl);
1034
1035 i = (DWORD)lParam1;
1036 switch (uMsg)
1037 {
1038 case CPL_INIT:
1039 return TRUE;
1040
1041 case CPL_GETCOUNT:
1042 return 1;
1043
1044 case CPL_INQUIRE:
1045 CPlInfo = (CPLINFO*)lParam2;
1046 CPlInfo->lData = 0;
1047 CPlInfo->idIcon = IDI_CPLSYSTEM;
1048 CPlInfo->idName = IDS_CPLSYSTEMNAME;
1049 CPlInfo->idInfo = IDS_CPLSYSTEMDESCRIPTION;
1050 break;
1051
1052 case CPL_DBLCLK:
1053 MainWindowCreate();
1054 break;
1055 }
1056
1057 return FALSE;
1058 }
1059
1060
1061 BOOL WINAPI
1062 DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
1063 {
1064 UNREFERENCED_PARAMETER(lpvReserved);
1065
1066 switch (dwReason)
1067 {
1068 case DLL_PROCESS_ATTACH:
1069 case DLL_THREAD_ATTACH:
1070 CoInitialize(NULL);
1071 hApplet = hinstDLL;
1072 break;
1073 }
1074
1075 return TRUE;
1076 }