appwiz.cpl: Gather extra information for Support Info dialog.
[wine/multimedia.git] / dlls / appwiz.cpl / appwiz.c
blob44bf3b24bddda124312bbe952c271b28c16fbaca
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 /* wait for the process to exit */
408 WaitForSingleObject(info.hProcess, INFINITE);
410 else
412 wsprintfW(errormsg, sUninstallFailed, iter->path);
414 if (MessageBoxW(0, errormsg, iter->title, MB_YESNO |
415 MB_ICONQUESTION) == IDYES)
417 /* delete the application's uninstall entry */
418 RegOpenKeyExW(iter->regroot, PathUninstallW, 0, KEY_READ, &hkey);
419 RegDeleteKeyW(hkey, iter->regkey);
420 RegCloseKey(hkey);
424 break;
429 /**********************************************************************************
430 * Name : SetInfoDialogText
431 * Description: Sets the text of a label in a window, based upon a registry entry
432 * or string passed to the function.
433 * Parameters : hKey - registry entry to read from, NULL if not reading
434 * from registry
435 * lpKeyName - key to read from, or string to check if hKey is NULL
436 * lpAltMessage - alternative message if entry not found
437 * hWnd - handle of dialog box
438 * iDlgItem - ID of label in dialog box
440 static void SetInfoDialogText(HKEY hKey, LPWSTR lpKeyName, LPWSTR lpAltMessage,
441 HWND hWnd, int iDlgItem)
443 WCHAR buf[MAX_STRING_LEN];
444 DWORD buflen;
445 HWND hWndDlgItem;
447 hWndDlgItem = GetDlgItem(hWnd, iDlgItem);
449 /* if hKey is null, lpKeyName contains the string we want to check */
450 if (hKey == NULL)
452 if ((lpKeyName) && (lstrlenW(lpKeyName) > 0))
453 SetWindowTextW(hWndDlgItem, lpKeyName);
454 else
455 SetWindowTextW(hWndDlgItem, lpAltMessage);
457 else
459 buflen = MAX_STRING_LEN;
461 if ((RegQueryValueExW(hKey, lpKeyName, 0, 0, (LPBYTE) buf, &buflen) ==
462 ERROR_SUCCESS) && (lstrlenW(buf) > 0))
463 SetWindowTextW(hWndDlgItem, buf);
464 else
465 SetWindowTextW(hWndDlgItem, lpAltMessage);
469 /******************************************************************************
470 * Name : SupportInfoDlgProc
471 * Description: Callback procedure for support info dialog
472 * Parameters : hWnd - hWnd of the window
473 * msg - reason for calling function
474 * wParam - additional parameter
475 * lParam - additional parameter
476 * Returns : Dependant on message
478 static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
480 APPINFO *iter;
481 HKEY hkey;
482 WCHAR oldtitle[MAX_STRING_LEN];
483 WCHAR buf[MAX_STRING_LEN];
484 WCHAR key[MAX_STRING_LEN];
485 WCHAR notfound[MAX_STRING_LEN];
487 switch(msg)
489 case WM_INITDIALOG:
490 for (iter = AppInfo; iter; iter = iter->next)
492 if (iter->id == (int) lParam)
494 lstrcpyW(key, PathUninstallW);
495 lstrcatW(key, BackSlashW);
496 lstrcatW(key, iter->regkey);
498 /* check the application's registry entries */
499 RegOpenKeyExW(iter->regroot, key, 0, KEY_READ, &hkey);
501 /* Load our "not specified" string */
502 LoadStringW(hInst, IDS_NOT_SPECIFIED, notfound,
503 sizeof(notfound) / sizeof(notfound[0]));
505 /* Update the data for items already read into the structure */
506 SetInfoDialogText(NULL, iter->publisher, notfound, hWnd,
507 IDC_INFO_PUBLISHER);
508 SetInfoDialogText(NULL, iter->version, notfound, hWnd,
509 IDC_INFO_VERSION);
511 /* And now update the data for those items in the registry */
512 SetInfoDialogText(hkey, (LPWSTR) ContactW, notfound, hWnd,
513 IDC_INFO_CONTACT);
514 SetInfoDialogText(hkey, (LPWSTR) HelpLinkW, notfound, hWnd,
515 IDC_INFO_SUPPORT);
516 SetInfoDialogText(hkey, (LPWSTR) HelpTelephoneW, notfound, hWnd,
517 IDC_INFO_PHONE);
518 SetInfoDialogText(hkey, (LPWSTR) ReadmeW, notfound, hWnd,
519 IDC_INFO_README);
520 SetInfoDialogText(hkey, (LPWSTR) URLUpdateInfoW, notfound, hWnd,
521 IDC_INFO_UPDATES);
522 SetInfoDialogText(hkey, (LPWSTR) CommentsW, notfound, hWnd,
523 IDC_INFO_COMMENTS);
525 /* Update the main label with the app name */
526 if (GetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), oldtitle,
527 MAX_STRING_LEN) != 0)
529 wsprintfW(buf, oldtitle, iter->title);
530 SetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), buf);
533 RegCloseKey(hkey);
535 break;
539 return TRUE;
541 case WM_DESTROY:
542 return 0;
544 case WM_COMMAND:
545 switch (LOWORD(wParam))
547 case IDOK:
548 EndDialog(hWnd, TRUE);
549 break;
553 return TRUE;
556 return FALSE;
559 /******************************************************************************
560 * Name : SupportInfo
561 * Description: Displays the Support Information dialog
562 * Parameters : hWnd - Handle of the main dialog
563 * id - ID of the application to display information for
565 static void SupportInfo(HWND hWnd, int id)
567 DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_INFO), hWnd, (DLGPROC)
568 SupportInfoDlgProc, (LPARAM) id);
571 /* Definition of column headers for AddListViewColumns function */
572 typedef struct AppWizColumn {
573 int width;
574 int fmt;
575 int title;
576 } AppWizColumn;
578 AppWizColumn columns[] = {
579 {200, LVCFMT_LEFT, IDS_COLUMN_NAME},
580 {150, LVCFMT_LEFT, IDS_COLUMN_PUBLISHER},
581 {100, LVCFMT_LEFT, IDS_COLUMN_VERSION},
584 /******************************************************************************
585 * Name : AddListViewColumns
586 * Description: Adds column headers to the list view control.
587 * Parameters : hWnd - Handle of the list view control.
588 * Returns : TRUE if completed successfully, FALSE otherwise.
590 static BOOL AddListViewColumns(HWND hWnd)
592 WCHAR buf[MAX_STRING_LEN];
593 LVCOLUMNW lvc;
594 UINT i;
596 lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
598 /* Add the columns */
599 for (i = 0; i < sizeof(columns) / sizeof(columns[0]); i++)
601 lvc.iSubItem = i;
602 lvc.pszText = buf;
604 /* set width and format */
605 lvc.cx = columns[i].width;
606 lvc.fmt = columns[i].fmt;
608 LoadStringW(hInst, columns[i].title, buf, sizeof(buf) / sizeof(buf[0]));
610 if (ListView_InsertColumnW(hWnd, i, &lvc) == -1)
611 return FALSE;
614 return TRUE;
617 /******************************************************************************
618 * Name : AddListViewImageList
619 * Description: Creates an ImageList for the list view control.
620 * Parameters : hWnd - Handle of the list view control.
621 * Returns : Handle of the image list.
623 static HIMAGELIST AddListViewImageList(HWND hWnd)
625 HIMAGELIST hSmall;
626 HICON hDefaultIcon;
628 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
629 ILC_MASK, 1, 1);
631 /* Add default icon to image list */
632 hDefaultIcon = LoadIconW(hInst, MAKEINTRESOURCEW(ICO_MAIN));
633 ImageList_AddIcon(hSmall, hDefaultIcon);
634 DestroyIcon(hDefaultIcon);
636 (void) ListView_SetImageList(hWnd, hSmall, LVSIL_SMALL);
638 return hSmall;
641 /******************************************************************************
642 * Name : ResetApplicationList
643 * Description: Empties the app list, if need be, and recreates it.
644 * Parameters : bFirstRun - TRUE if this is the first time this is run, FALSE otherwise
645 * hWnd - handle of the dialog box
646 * hImageList - handle of the image list
647 * Returns : New handle of the image list.
649 static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hImageList)
651 HWND hWndListView;
653 hWndListView = GetDlgItem(hWnd, IDL_PROGRAMS);
655 /* if first run, create the image list and add the listview columns */
656 if (bFirstRun)
658 if (!AddListViewColumns(hWndListView))
659 return NULL;
661 else /* we need to remove the existing things first */
663 RemoveItemsFromList(hWnd);
664 ImageList_Destroy(hImageList);
666 /* reset the list, since it's probably changed if the uninstallation was
667 successful */
668 EmptyList();
671 /* now create the image list and add the applications to the listview */
672 hImageList = AddListViewImageList(hWndListView);
674 ReadApplicationsFromRegistry(HKEY_LOCAL_MACHINE);
675 ReadApplicationsFromRegistry(HKEY_CURRENT_USER);
677 AddApplicationsToList(hWndListView, hImageList);
678 UpdateButtons(hWnd);
680 return(hImageList);
683 /******************************************************************************
684 * Name : MainDlgProc
685 * Description: Callback procedure for main tab
686 * Parameters : hWnd - hWnd of the window
687 * msg - reason for calling function
688 * wParam - additional parameter
689 * lParam - additional parameter
690 * Returns : Dependant on message
692 static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
694 int selitem;
695 static HIMAGELIST hImageList;
696 LPNMHDR nmh;
697 LVITEMW lvItem;
699 switch(msg)
701 case WM_INITDIALOG:
702 hImageList = ResetApplicationList(TRUE, hWnd, hImageList);
704 if (!hImageList)
705 return FALSE;
707 return TRUE;
709 case WM_DESTROY:
710 RemoveItemsFromList(hWnd);
711 ImageList_Destroy(hImageList);
713 EmptyList();
715 return 0;
717 case WM_NOTIFY:
718 nmh = (LPNMHDR) lParam;
720 switch (nmh->idFrom)
722 case IDL_PROGRAMS:
723 switch (nmh->code)
725 case LVN_ITEMCHANGED:
726 UpdateButtons(hWnd);
727 break;
729 break;
732 return TRUE;
734 case WM_COMMAND:
735 switch (LOWORD(wParam))
737 case IDC_ADDREMOVE:
738 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
739 LVM_GETNEXTITEM, -1, LVNI_FOCUSED|LVNI_SELECTED);
741 if (selitem != -1)
743 lvItem.iItem = selitem;
744 lvItem.mask = LVIF_PARAM;
746 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
747 0, (LPARAM) &lvItem))
748 UninstallProgram(lvItem.lParam);
751 hImageList = ResetApplicationList(FALSE, hWnd, hImageList);
753 break;
755 case IDC_SUPPORT_INFO:
756 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
757 LVM_GETNEXTITEM, -1, LVNI_FOCUSED | LVNI_SELECTED);
759 if (selitem != -1)
761 lvItem.iItem = selitem;
762 lvItem.mask = LVIF_PARAM;
764 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
765 0, (LPARAM) &lvItem))
766 SupportInfo(hWnd, lvItem.lParam);
769 break;
772 return TRUE;
775 return FALSE;
778 /******************************************************************************
779 * Name : StartApplet
780 * Description: Main routine for applet
781 * Parameters : hWnd - hWnd of the Control Panel
783 static void StartApplet(HWND hWnd)
785 PROPSHEETPAGEW psp;
786 PROPSHEETHEADERW psh;
787 WCHAR tab_title[MAX_STRING_LEN], app_title[MAX_STRING_LEN];
789 /* Load the strings we will use */
790 LoadStringW(hInst, IDS_TAB1_TITLE, tab_title, sizeof(tab_title) / sizeof(tab_title[0]));
791 LoadStringW(hInst, IDS_CPL_TITLE, app_title, sizeof(app_title) / sizeof(app_title[0]));
793 /* Fill out the PROPSHEETPAGE */
794 psp.dwSize = sizeof (PROPSHEETPAGEW);
795 psp.dwFlags = PSP_USETITLE;
796 psp.hInstance = hInst;
797 psp.u.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN);
798 psp.u2.pszIcon = NULL;
799 psp.pfnDlgProc = (DLGPROC) MainDlgProc;
800 psp.pszTitle = tab_title;
801 psp.lParam = 0;
803 /* Fill out the PROPSHEETHEADER */
804 psh.dwSize = sizeof (PROPSHEETHEADERW);
805 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID;
806 psh.hwndParent = hWnd;
807 psh.hInstance = hInst;
808 psh.u.pszIcon = NULL;
809 psh.pszCaption = app_title;
810 psh.nPages = 1;
811 psh.u3.ppsp = &psp;
812 psh.pfnCallback = NULL;
813 psh.u2.nStartPage = 0;
815 /* Display the property sheet */
816 PropertySheetW (&psh);
819 /******************************************************************************
820 * Name : CPlApplet
821 * Description: Entry point for Control Panel applets
822 * Parameters : hwndCPL - hWnd of the Control Panel
823 * message - reason for calling function
824 * lParam1 - additional parameter
825 * lParam2 - additional parameter
826 * Returns : Dependant on message
828 LONG CALLBACK CPlApplet(HWND hwndCPL, UINT message, LPARAM lParam1, LPARAM lParam2)
830 INITCOMMONCONTROLSEX iccEx;
832 switch (message)
834 case CPL_INIT:
835 iccEx.dwSize = sizeof(iccEx);
836 iccEx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES;
838 InitCommonControlsEx(&iccEx);
840 return TRUE;
842 case CPL_GETCOUNT:
843 return 1;
845 case CPL_INQUIRE:
847 CPLINFO *appletInfo = (CPLINFO *) lParam2;
849 appletInfo->idIcon = ICO_MAIN;
850 appletInfo->idName = IDS_CPL_TITLE;
851 appletInfo->idInfo = IDS_CPL_DESC;
852 appletInfo->lData = 0;
854 break;
857 case CPL_DBLCLK:
858 StartApplet(hwndCPL);
859 break;
862 return FALSE;