rsaenh/tests: Fix a test failure on W2K and below.
[wine/wine64.git] / dlls / appwiz.cpl / appwiz.c
blobb5a722f8b593fa5025467a032c2c77c6409e17ea
1 /*
2 * Add/Remove Programs applet
3 * Partially based on Wine Uninstaller
5 * Copyright 2000 Andreas Mohr
6 * Copyright 2004 Hannu Valtonen
7 * Copyright 2005 Jonathan Ernst
8 * Copyright 2001-2002, 2008 Owen Rudge
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSUNION
28 #include "config.h"
29 #include "wine/port.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <windef.h>
38 #include <winbase.h>
39 #include <winuser.h>
40 #include <wingdi.h>
41 #include <winreg.h>
42 #include <shellapi.h>
43 #include <commctrl.h>
44 #include <cpl.h>
46 #include "res.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(appwizcpl);
50 /* define a maximum length for various buffers we use */
51 #define MAX_STRING_LEN 1024
53 typedef struct APPINFO {
54 int id;
56 LPWSTR title;
57 LPWSTR path;
59 LPWSTR icon;
60 int iconIdx;
62 LPWSTR publisher;
63 LPWSTR version;
65 HKEY regroot;
66 WCHAR regkey[MAX_STRING_LEN];
68 struct APPINFO *next;
69 } APPINFO;
71 static struct APPINFO *AppInfo = NULL;
72 static HINSTANCE hInst;
74 /* names of registry keys */
75 static const WCHAR BackSlashW[] = { '\\', 0 };
76 static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
77 static const WCHAR DisplayIconW[] = {'D','i','s','p','l','a','y','I','c','o','n',0};
78 static const WCHAR DisplayVersionW[] = {'D','i','s','p','l','a','y','V','e','r',
79 's','i','o','n',0};
80 static const WCHAR PublisherW[] = {'P','u','b','l','i','s','h','e','r',0};
81 static const WCHAR ContactW[] = {'C','o','n','t','a','c','t',0};
82 static const WCHAR HelpLinkW[] = {'H','e','l','p','L','i','n','k',0};
83 static const WCHAR HelpTelephoneW[] = {'H','e','l','p','T','e','l','e','p','h',
84 'o','n','e',0};
85 static const WCHAR ReadmeW[] = {'R','e','a','d','m','e',0};
86 static const WCHAR URLUpdateInfoW[] = {'U','R','L','U','p','d','a','t','e','I',
87 'n','f','o',0};
88 static const WCHAR CommentsW[] = {'C','o','m','m','e','n','t','s',0};
89 static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l',
90 'S','t','r','i','n','g',0};
92 static const WCHAR PathUninstallW[] = {
93 'S','o','f','t','w','a','r','e','\\',
94 'M','i','c','r','o','s','o','f','t','\\',
95 'W','i','n','d','o','w','s','\\',
96 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
97 'U','n','i','n','s','t','a','l','l',0 };
99 /******************************************************************************
100 * Name : DllMain
101 * Description: Entry point for DLL file
103 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
104 LPVOID lpvReserved)
106 TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
108 switch (fdwReason)
110 case DLL_PROCESS_ATTACH:
111 hInst = hinstDLL;
112 break;
114 return TRUE;
117 /******************************************************************************
118 * Name : FreeAppInfo
119 * Description: Frees memory used by an AppInfo structure, and any children.
121 static void FreeAppInfo(APPINFO *info)
123 while (info)
125 APPINFO *next_info = info->next;
127 HeapFree(GetProcessHeap(), 0, info->title);
128 HeapFree(GetProcessHeap(), 0, info->path);
129 HeapFree(GetProcessHeap(), 0, info->icon);
130 HeapFree(GetProcessHeap(), 0, info->publisher);
131 HeapFree(GetProcessHeap(), 0, info->version);
132 HeapFree(GetProcessHeap(), 0, info);
133 info = next_info;
137 /******************************************************************************
138 * Name : ReadApplicationsFromRegistry
139 * Description: Creates a linked list of uninstallable applications from the
140 * registry.
141 * Parameters : root - Which registry root to read from (HKCU/HKLM)
142 * Returns : TRUE if successful, FALSE otherwise
144 static BOOL ReadApplicationsFromRegistry(HKEY root)
146 HKEY hkeyUninst, hkeyApp;
147 int i, id = 0;
148 DWORD sizeOfSubKeyName, displen, uninstlen;
149 WCHAR subKeyName[256];
150 WCHAR key_app[MAX_STRING_LEN];
151 WCHAR *p;
152 APPINFO *iter = AppInfo;
153 LPWSTR iconPtr;
154 BOOL ret = FALSE;
156 if (RegOpenKeyExW(root, PathUninstallW, 0, KEY_READ, &hkeyUninst) !=
157 ERROR_SUCCESS)
158 return FALSE;
160 lstrcpyW(key_app, PathUninstallW);
161 lstrcatW(key_app, BackSlashW);
162 p = key_app+lstrlenW(PathUninstallW)+1;
164 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
166 if (iter)
168 /* find the end of the list */
169 for (iter = AppInfo; iter->next; iter = iter->next);
172 for (i = 0; RegEnumKeyExW(hkeyUninst, i, subKeyName, &sizeOfSubKeyName, NULL,
173 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS; ++i)
175 lstrcpyW(p, subKeyName);
176 RegOpenKeyExW(root, key_app, 0, KEY_READ, &hkeyApp);
178 displen = 0;
179 uninstlen = 0;
181 if ((RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen) ==
182 ERROR_SUCCESS) && (RegQueryValueExW(hkeyApp, UninstallCommandlineW,
183 0, 0, NULL, &uninstlen) == ERROR_SUCCESS))
185 /* if we already have iter, allocate the next entry */
186 if (iter)
188 iter->next = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
189 sizeof(struct APPINFO));
191 if (!iter->next)
192 goto err;
194 iter = iter->next;
196 else
198 /* if not, start the list */
199 iter = AppInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
200 sizeof(struct APPINFO));
202 if (!iter)
203 goto err;
206 iter->title = HeapAlloc(GetProcessHeap(), 0, displen);
208 if (!iter->title)
209 goto err;
211 RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)iter->title,
212 &displen);
214 /* now get DisplayIcon */
215 displen = 0;
216 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, NULL, &displen);
218 if (displen == 0)
219 iter->icon = 0;
220 else
222 iter->icon = HeapAlloc(GetProcessHeap(), 0, displen);
224 if (!iter->icon)
225 goto err;
227 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, (LPBYTE)iter->icon,
228 &displen);
230 /* separate the index from the icon name, if supplied */
231 iconPtr = strchrW(iter->icon, ',');
233 if (iconPtr)
235 *iconPtr++ = 0;
236 iter->iconIdx = atoiW(iconPtr);
240 iter->path = HeapAlloc(GetProcessHeap(), 0, uninstlen);
242 if (!iter->path)
243 goto err;
245 RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0,
246 (LPBYTE)iter->path, &uninstlen);
248 /* publisher, version */
249 if (RegQueryValueExW(hkeyApp, PublisherW, 0, 0, NULL, &displen) ==
250 ERROR_SUCCESS)
252 iter->publisher = HeapAlloc(GetProcessHeap(), 0, displen);
254 if (!iter->publisher)
255 goto err;
257 RegQueryValueExW(hkeyApp, PublisherW, 0, 0, (LPBYTE)iter->publisher,
258 &displen);
261 if (RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, NULL, &displen) ==
262 ERROR_SUCCESS)
264 iter->version = HeapAlloc(GetProcessHeap(), 0, displen);
266 if (!iter->version)
267 goto err;
269 RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, (LPBYTE)iter->version,
270 &displen);
273 /* registry key */
274 iter->regroot = root;
275 lstrcpyW(iter->regkey, subKeyName);
277 iter->id = id++;
280 RegCloseKey(hkeyApp);
281 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
284 ret = TRUE;
285 goto end;
287 err:
288 RegCloseKey(hkeyApp);
289 FreeAppInfo(iter);
291 end:
292 RegCloseKey(hkeyUninst);
293 return ret;
297 /******************************************************************************
298 * Name : AddApplicationsToList
299 * Description: Populates the list box with applications.
300 * Parameters : hWnd - Handle of the dialog box
302 static void AddApplicationsToList(HWND hWnd, HIMAGELIST hList)
304 APPINFO *iter = AppInfo;
305 LVITEMW lvItem;
306 HICON hIcon;
307 int index;
309 while (iter)
311 /* get the icon */
312 index = 0;
314 if (iter->icon)
316 if (ExtractIconExW(iter->icon, iter->iconIdx, NULL, &hIcon, 1) == 1)
318 index = ImageList_AddIcon(hList, hIcon);
319 DestroyIcon(hIcon);
323 lvItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
324 lvItem.iItem = iter->id;
325 lvItem.iSubItem = 0;
326 lvItem.pszText = iter->title;
327 lvItem.iImage = index;
328 lvItem.lParam = iter->id;
330 index = ListView_InsertItemW(hWnd, &lvItem);
332 /* now add the subitems (columns) */
333 ListView_SetItemTextW(hWnd, index, 1, iter->publisher);
334 ListView_SetItemTextW(hWnd, index, 2, iter->version);
336 iter = iter->next;
340 /******************************************************************************
341 * Name : RemoveItemsFromList
342 * Description: Clears the application list box.
343 * Parameters : hWnd - Handle of the dialog box
345 static void RemoveItemsFromList(HWND hWnd)
347 SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_DELETEALLITEMS, 0, 0);
350 /******************************************************************************
351 * Name : EmptyList
352 * Description: Frees memory used by the application linked list.
354 static inline void EmptyList(void)
356 FreeAppInfo(AppInfo);
357 AppInfo = NULL;
360 /******************************************************************************
361 * Name : UpdateButtons
362 * Description: Enables/disables the Add/Remove button depending on current
363 * selection in list box.
364 * Parameters : hWnd - Handle of the dialog box
366 static void UpdateButtons(HWND hWnd)
368 BOOL sel = ListView_GetSelectedCount(GetDlgItem(hWnd, IDL_PROGRAMS)) != 0;
370 EnableWindow(GetDlgItem(hWnd, IDC_ADDREMOVE), sel);
371 EnableWindow(GetDlgItem(hWnd, IDC_SUPPORT_INFO), sel);
374 /******************************************************************************
375 * Name : UninstallProgram
376 * Description: Executes the specified program's installer.
377 * Parameters : id - the internal ID of the installer to remove
379 static void UninstallProgram(int id)
381 APPINFO *iter;
382 STARTUPINFOW si;
383 PROCESS_INFORMATION info;
384 WCHAR errormsg[MAX_STRING_LEN];
385 WCHAR sUninstallFailed[MAX_STRING_LEN];
386 HKEY hkey;
387 BOOL res;
389 LoadStringW(hInst, IDS_UNINSTALL_FAILED, sUninstallFailed,
390 sizeof(sUninstallFailed) / sizeof(sUninstallFailed[0]));
392 for (iter = AppInfo; iter; iter = iter->next)
394 if (iter->id == id)
396 TRACE("Uninstalling %s (%s)\n", wine_dbgstr_w(iter->title),
397 wine_dbgstr_w(iter->path));
399 memset(&si, 0, sizeof(STARTUPINFOW));
400 si.cb = sizeof(STARTUPINFOW);
401 si.wShowWindow = SW_NORMAL;
402 res = CreateProcessW(NULL, iter->path, NULL, NULL, FALSE, 0, NULL,
403 NULL, &si, &info);
405 if (res)
407 CloseHandle(info.hThread);
409 /* wait for the process to exit */
410 WaitForSingleObject(info.hProcess, INFINITE);
411 CloseHandle(info.hProcess);
413 else
415 wsprintfW(errormsg, sUninstallFailed, iter->path);
417 if (MessageBoxW(0, errormsg, iter->title, MB_YESNO |
418 MB_ICONQUESTION) == IDYES)
420 /* delete the application's uninstall entry */
421 RegOpenKeyExW(iter->regroot, PathUninstallW, 0, KEY_READ, &hkey);
422 RegDeleteKeyW(hkey, iter->regkey);
423 RegCloseKey(hkey);
427 break;
432 /**********************************************************************************
433 * Name : SetInfoDialogText
434 * Description: Sets the text of a label in a window, based upon a registry entry
435 * or string passed to the function.
436 * Parameters : hKey - registry entry to read from, NULL if not reading
437 * from registry
438 * lpKeyName - key to read from, or string to check if hKey is NULL
439 * lpAltMessage - alternative message if entry not found
440 * hWnd - handle of dialog box
441 * iDlgItem - ID of label in dialog box
443 static void SetInfoDialogText(HKEY hKey, LPWSTR lpKeyName, LPWSTR lpAltMessage,
444 HWND hWnd, int iDlgItem)
446 WCHAR buf[MAX_STRING_LEN];
447 DWORD buflen;
448 HWND hWndDlgItem;
450 hWndDlgItem = GetDlgItem(hWnd, iDlgItem);
452 /* if hKey is null, lpKeyName contains the string we want to check */
453 if (hKey == NULL)
455 if ((lpKeyName) && (lstrlenW(lpKeyName) > 0))
456 SetWindowTextW(hWndDlgItem, lpKeyName);
457 else
458 SetWindowTextW(hWndDlgItem, lpAltMessage);
460 else
462 buflen = MAX_STRING_LEN;
464 if ((RegQueryValueExW(hKey, lpKeyName, 0, 0, (LPBYTE) buf, &buflen) ==
465 ERROR_SUCCESS) && (lstrlenW(buf) > 0))
466 SetWindowTextW(hWndDlgItem, buf);
467 else
468 SetWindowTextW(hWndDlgItem, lpAltMessage);
472 /******************************************************************************
473 * Name : SupportInfoDlgProc
474 * Description: Callback procedure for support info dialog
475 * Parameters : hWnd - hWnd of the window
476 * msg - reason for calling function
477 * wParam - additional parameter
478 * lParam - additional parameter
479 * Returns : Dependant on message
481 static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
483 APPINFO *iter;
484 HKEY hkey;
485 WCHAR oldtitle[MAX_STRING_LEN];
486 WCHAR buf[MAX_STRING_LEN];
487 WCHAR key[MAX_STRING_LEN];
488 WCHAR notfound[MAX_STRING_LEN];
490 switch(msg)
492 case WM_INITDIALOG:
493 for (iter = AppInfo; iter; iter = iter->next)
495 if (iter->id == (int) lParam)
497 lstrcpyW(key, PathUninstallW);
498 lstrcatW(key, BackSlashW);
499 lstrcatW(key, iter->regkey);
501 /* check the application's registry entries */
502 RegOpenKeyExW(iter->regroot, key, 0, KEY_READ, &hkey);
504 /* Load our "not specified" string */
505 LoadStringW(hInst, IDS_NOT_SPECIFIED, notfound,
506 sizeof(notfound) / sizeof(notfound[0]));
508 /* Update the data for items already read into the structure */
509 SetInfoDialogText(NULL, iter->publisher, notfound, hWnd,
510 IDC_INFO_PUBLISHER);
511 SetInfoDialogText(NULL, iter->version, notfound, hWnd,
512 IDC_INFO_VERSION);
514 /* And now update the data for those items in the registry */
515 SetInfoDialogText(hkey, (LPWSTR) ContactW, notfound, hWnd,
516 IDC_INFO_CONTACT);
517 SetInfoDialogText(hkey, (LPWSTR) HelpLinkW, notfound, hWnd,
518 IDC_INFO_SUPPORT);
519 SetInfoDialogText(hkey, (LPWSTR) HelpTelephoneW, notfound, hWnd,
520 IDC_INFO_PHONE);
521 SetInfoDialogText(hkey, (LPWSTR) ReadmeW, notfound, hWnd,
522 IDC_INFO_README);
523 SetInfoDialogText(hkey, (LPWSTR) URLUpdateInfoW, notfound, hWnd,
524 IDC_INFO_UPDATES);
525 SetInfoDialogText(hkey, (LPWSTR) CommentsW, notfound, hWnd,
526 IDC_INFO_COMMENTS);
528 /* Update the main label with the app name */
529 if (GetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), oldtitle,
530 MAX_STRING_LEN) != 0)
532 wsprintfW(buf, oldtitle, iter->title);
533 SetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), buf);
536 RegCloseKey(hkey);
538 break;
542 return TRUE;
544 case WM_DESTROY:
545 return 0;
547 case WM_COMMAND:
548 switch (LOWORD(wParam))
550 case IDOK:
551 EndDialog(hWnd, TRUE);
552 break;
556 return TRUE;
559 return FALSE;
562 /******************************************************************************
563 * Name : SupportInfo
564 * Description: Displays the Support Information dialog
565 * Parameters : hWnd - Handle of the main dialog
566 * id - ID of the application to display information for
568 static void SupportInfo(HWND hWnd, int id)
570 DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_INFO), hWnd, (DLGPROC)
571 SupportInfoDlgProc, (LPARAM) id);
574 /* Definition of column headers for AddListViewColumns function */
575 typedef struct AppWizColumn {
576 int width;
577 int fmt;
578 int title;
579 } AppWizColumn;
581 static const AppWizColumn columns[] = {
582 {200, LVCFMT_LEFT, IDS_COLUMN_NAME},
583 {150, LVCFMT_LEFT, IDS_COLUMN_PUBLISHER},
584 {100, LVCFMT_LEFT, IDS_COLUMN_VERSION},
587 /******************************************************************************
588 * Name : AddListViewColumns
589 * Description: Adds column headers to the list view control.
590 * Parameters : hWnd - Handle of the list view control.
591 * Returns : TRUE if completed successfully, FALSE otherwise.
593 static BOOL AddListViewColumns(HWND hWnd)
595 WCHAR buf[MAX_STRING_LEN];
596 LVCOLUMNW lvc;
597 UINT i;
599 lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
601 /* Add the columns */
602 for (i = 0; i < sizeof(columns) / sizeof(columns[0]); i++)
604 lvc.iSubItem = i;
605 lvc.pszText = buf;
607 /* set width and format */
608 lvc.cx = columns[i].width;
609 lvc.fmt = columns[i].fmt;
611 LoadStringW(hInst, columns[i].title, buf, sizeof(buf) / sizeof(buf[0]));
613 if (ListView_InsertColumnW(hWnd, i, &lvc) == -1)
614 return FALSE;
617 return TRUE;
620 /******************************************************************************
621 * Name : AddListViewImageList
622 * Description: Creates an ImageList for the list view control.
623 * Parameters : hWnd - Handle of the list view control.
624 * Returns : Handle of the image list.
626 static HIMAGELIST AddListViewImageList(HWND hWnd)
628 HIMAGELIST hSmall;
629 HICON hDefaultIcon;
631 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
632 ILC_MASK, 1, 1);
634 /* Add default icon to image list */
635 hDefaultIcon = LoadIconW(hInst, MAKEINTRESOURCEW(ICO_MAIN));
636 ImageList_AddIcon(hSmall, hDefaultIcon);
637 DestroyIcon(hDefaultIcon);
639 (void) ListView_SetImageList(hWnd, hSmall, LVSIL_SMALL);
641 return hSmall;
644 /******************************************************************************
645 * Name : ResetApplicationList
646 * Description: Empties the app list, if need be, and recreates it.
647 * Parameters : bFirstRun - TRUE if this is the first time this is run, FALSE otherwise
648 * hWnd - handle of the dialog box
649 * hImageList - handle of the image list
650 * Returns : New handle of the image list.
652 static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hImageList)
654 HWND hWndListView;
656 hWndListView = GetDlgItem(hWnd, IDL_PROGRAMS);
658 /* if first run, create the image list and add the listview columns */
659 if (bFirstRun)
661 if (!AddListViewColumns(hWndListView))
662 return NULL;
664 else /* we need to remove the existing things first */
666 RemoveItemsFromList(hWnd);
667 ImageList_Destroy(hImageList);
669 /* reset the list, since it's probably changed if the uninstallation was
670 successful */
671 EmptyList();
674 /* now create the image list and add the applications to the listview */
675 hImageList = AddListViewImageList(hWndListView);
677 ReadApplicationsFromRegistry(HKEY_LOCAL_MACHINE);
678 ReadApplicationsFromRegistry(HKEY_CURRENT_USER);
680 AddApplicationsToList(hWndListView, hImageList);
681 UpdateButtons(hWnd);
683 return(hImageList);
686 /******************************************************************************
687 * Name : MainDlgProc
688 * Description: Callback procedure for main tab
689 * Parameters : hWnd - hWnd of the window
690 * msg - reason for calling function
691 * wParam - additional parameter
692 * lParam - additional parameter
693 * Returns : Dependant on message
695 static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
697 int selitem;
698 static HIMAGELIST hImageList;
699 LPNMHDR nmh;
700 LVITEMW lvItem;
702 switch(msg)
704 case WM_INITDIALOG:
705 hImageList = ResetApplicationList(TRUE, hWnd, hImageList);
707 if (!hImageList)
708 return FALSE;
710 return TRUE;
712 case WM_DESTROY:
713 RemoveItemsFromList(hWnd);
714 ImageList_Destroy(hImageList);
716 EmptyList();
718 return 0;
720 case WM_NOTIFY:
721 nmh = (LPNMHDR) lParam;
723 switch (nmh->idFrom)
725 case IDL_PROGRAMS:
726 switch (nmh->code)
728 case LVN_ITEMCHANGED:
729 UpdateButtons(hWnd);
730 break;
732 break;
735 return TRUE;
737 case WM_COMMAND:
738 switch (LOWORD(wParam))
740 case IDC_ADDREMOVE:
741 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
742 LVM_GETNEXTITEM, -1, LVNI_FOCUSED|LVNI_SELECTED);
744 if (selitem != -1)
746 lvItem.iItem = selitem;
747 lvItem.mask = LVIF_PARAM;
749 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
750 0, (LPARAM) &lvItem))
751 UninstallProgram(lvItem.lParam);
754 hImageList = ResetApplicationList(FALSE, hWnd, hImageList);
756 break;
758 case IDC_SUPPORT_INFO:
759 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
760 LVM_GETNEXTITEM, -1, LVNI_FOCUSED | LVNI_SELECTED);
762 if (selitem != -1)
764 lvItem.iItem = selitem;
765 lvItem.mask = LVIF_PARAM;
767 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
768 0, (LPARAM) &lvItem))
769 SupportInfo(hWnd, lvItem.lParam);
772 break;
775 return TRUE;
778 return FALSE;
781 /******************************************************************************
782 * Name : StartApplet
783 * Description: Main routine for applet
784 * Parameters : hWnd - hWnd of the Control Panel
786 static void StartApplet(HWND hWnd)
788 PROPSHEETPAGEW psp;
789 PROPSHEETHEADERW psh;
790 WCHAR tab_title[MAX_STRING_LEN], app_title[MAX_STRING_LEN];
792 /* Load the strings we will use */
793 LoadStringW(hInst, IDS_TAB1_TITLE, tab_title, sizeof(tab_title) / sizeof(tab_title[0]));
794 LoadStringW(hInst, IDS_CPL_TITLE, app_title, sizeof(app_title) / sizeof(app_title[0]));
796 /* Fill out the PROPSHEETPAGE */
797 psp.dwSize = sizeof (PROPSHEETPAGEW);
798 psp.dwFlags = PSP_USETITLE;
799 psp.hInstance = hInst;
800 psp.u.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN);
801 psp.u2.pszIcon = NULL;
802 psp.pfnDlgProc = (DLGPROC) MainDlgProc;
803 psp.pszTitle = tab_title;
804 psp.lParam = 0;
806 /* Fill out the PROPSHEETHEADER */
807 psh.dwSize = sizeof (PROPSHEETHEADERW);
808 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID;
809 psh.hwndParent = hWnd;
810 psh.hInstance = hInst;
811 psh.u.pszIcon = NULL;
812 psh.pszCaption = app_title;
813 psh.nPages = 1;
814 psh.u3.ppsp = &psp;
815 psh.pfnCallback = NULL;
816 psh.u2.nStartPage = 0;
818 /* Display the property sheet */
819 PropertySheetW (&psh);
822 /******************************************************************************
823 * Name : CPlApplet
824 * Description: Entry point for Control Panel applets
825 * Parameters : hwndCPL - hWnd of the Control Panel
826 * message - reason for calling function
827 * lParam1 - additional parameter
828 * lParam2 - additional parameter
829 * Returns : Dependant on message
831 LONG CALLBACK CPlApplet(HWND hwndCPL, UINT message, LPARAM lParam1, LPARAM lParam2)
833 INITCOMMONCONTROLSEX iccEx;
835 switch (message)
837 case CPL_INIT:
838 iccEx.dwSize = sizeof(iccEx);
839 iccEx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES;
841 InitCommonControlsEx(&iccEx);
843 return TRUE;
845 case CPL_GETCOUNT:
846 return 1;
848 case CPL_INQUIRE:
850 CPLINFO *appletInfo = (CPLINFO *) lParam2;
852 appletInfo->idIcon = ICO_MAIN;
853 appletInfo->idName = IDS_CPL_TITLE;
854 appletInfo->idInfo = IDS_CPL_DESC;
855 appletInfo->lData = 0;
857 break;
860 case CPL_DBLCLK:
861 StartApplet(hwndCPL);
862 break;
865 return FALSE;