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
29 #include "wine/port.h"
45 #include "wine/unicode.h"
46 #include "wine/list.h"
47 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(appwizcpl);
53 /* define a maximum length for various buffers we use */
54 #define MAX_STRING_LEN 1024
56 typedef struct APPINFO
72 WCHAR regkey[MAX_STRING_LEN];
75 static struct list app_list = LIST_INIT( app_list );
78 static WCHAR btnRemove[MAX_STRING_LEN];
79 static WCHAR btnModifyRemove[MAX_STRING_LEN];
81 static const WCHAR openW[] = {'o','p','e','n',0};
83 /* names of registry keys */
84 static const WCHAR BackSlashW[] = { '\\', 0 };
85 static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
86 static const WCHAR DisplayIconW[] = {'D','i','s','p','l','a','y','I','c','o','n',0};
87 static const WCHAR DisplayVersionW[] = {'D','i','s','p','l','a','y','V','e','r',
89 static const WCHAR PublisherW[] = {'P','u','b','l','i','s','h','e','r',0};
90 static const WCHAR ContactW[] = {'C','o','n','t','a','c','t',0};
91 static const WCHAR HelpLinkW[] = {'H','e','l','p','L','i','n','k',0};
92 static const WCHAR HelpTelephoneW[] = {'H','e','l','p','T','e','l','e','p','h',
94 static const WCHAR ModifyPathW[] = {'M','o','d','i','f','y','P','a','t','h',0};
95 static const WCHAR NoModifyW[] = {'N','o','M','o','d','i','f','y',0};
96 static const WCHAR ReadmeW[] = {'R','e','a','d','m','e',0};
97 static const WCHAR URLUpdateInfoW[] = {'U','R','L','U','p','d','a','t','e','I',
99 static const WCHAR CommentsW[] = {'C','o','m','m','e','n','t','s',0};
100 static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l',
101 'S','t','r','i','n','g',0};
102 static const WCHAR WindowsInstallerW[] = {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
103 static const WCHAR SystemComponentW[] = {'S','y','s','t','e','m','C','o','m','p','o','n','e','n','t',0};
105 static const WCHAR PathUninstallW[] = {
106 'S','o','f','t','w','a','r','e','\\',
107 'M','i','c','r','o','s','o','f','t','\\',
108 'W','i','n','d','o','w','s','\\',
109 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
110 'U','n','i','n','s','t','a','l','l',0 };
112 /******************************************************************************
114 * Description: Entry point for DLL file
116 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
119 TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
123 case DLL_PROCESS_ATTACH:
130 /******************************************************************************
132 * Description: Frees memory used by an AppInfo structure, and any children.
134 static void FreeAppInfo(APPINFO *info)
136 HeapFree(GetProcessHeap(), 0, info->title);
137 HeapFree(GetProcessHeap(), 0, info->path);
138 HeapFree(GetProcessHeap(), 0, info->path_modify);
139 HeapFree(GetProcessHeap(), 0, info->icon);
140 HeapFree(GetProcessHeap(), 0, info->publisher);
141 HeapFree(GetProcessHeap(), 0, info->version);
142 HeapFree(GetProcessHeap(), 0, info);
145 /******************************************************************************
146 * Name : ReadApplicationsFromRegistry
147 * Description: Creates a linked list of uninstallable applications from the
149 * Parameters : root - Which registry root to read from
150 * Returns : TRUE if successful, FALSE otherwise
152 static BOOL ReadApplicationsFromRegistry(HKEY root)
156 DWORD sizeOfSubKeyName, displen, uninstlen;
157 DWORD dwNoModify, dwType, value, size;
158 WCHAR subKeyName[256];
160 APPINFO *info = NULL;
163 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
165 for (i = 0; RegEnumKeyExW(root, i, subKeyName, &sizeOfSubKeyName, NULL,
166 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS; ++i)
168 RegOpenKeyExW(root, subKeyName, 0, KEY_READ, &hkeyApp);
169 size = sizeof(value);
170 if (!RegQueryValueExW(hkeyApp, SystemComponentW, NULL, &dwType, (LPBYTE)&value, &size)
171 && dwType == REG_DWORD && value == 1)
173 RegCloseKey(hkeyApp);
174 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
179 if (!RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen))
181 size = sizeof(value);
182 if (!RegQueryValueExW(hkeyApp, WindowsInstallerW, NULL, &dwType, (LPBYTE)&value, &size)
183 && dwType == REG_DWORD && value == 1)
185 static const WCHAR fmtW[] = {'m','s','i','e','x','e','c',' ','/','x','%','s',0};
186 int len = lstrlenW(fmtW) + lstrlenW(subKeyName);
188 if (!(command = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto err;
189 wsprintfW(command, fmtW, subKeyName);
191 else if (!RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, NULL, &uninstlen))
193 if (!(command = HeapAlloc(GetProcessHeap(), 0, uninstlen))) goto err;
194 RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, (LPBYTE)command, &uninstlen);
198 RegCloseKey(hkeyApp);
199 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
203 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct APPINFO));
206 info->title = HeapAlloc(GetProcessHeap(), 0, displen);
211 RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)info->title,
214 /* now get DisplayIcon */
216 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, NULL, &displen);
222 info->icon = HeapAlloc(GetProcessHeap(), 0, displen);
227 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, (LPBYTE)info->icon,
230 /* separate the index from the icon name, if supplied */
231 iconPtr = strchrW(info->icon, ',');
236 info->iconIdx = atoiW(iconPtr);
240 /* publisher, version */
241 if (RegQueryValueExW(hkeyApp, PublisherW, 0, 0, NULL, &displen) ==
244 info->publisher = HeapAlloc(GetProcessHeap(), 0, displen);
246 if (!info->publisher)
249 RegQueryValueExW(hkeyApp, PublisherW, 0, 0, (LPBYTE)info->publisher,
253 if (RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, NULL, &displen) ==
256 info->version = HeapAlloc(GetProcessHeap(), 0, displen);
261 RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, (LPBYTE)info->version,
265 /* Check if NoModify is set */
268 displen = sizeof(DWORD);
270 if (RegQueryValueExW(hkeyApp, NoModifyW, NULL, &dwType, (LPBYTE)&dwNoModify, &displen)
276 /* Some installers incorrectly create a REG_SZ instead of a REG_DWORD */
277 if (dwType == REG_SZ)
278 dwNoModify = (*(BYTE *)&dwNoModify == '1');
280 /* Fetch the modify path */
283 size = sizeof(value);
284 if (!RegQueryValueExW(hkeyApp, WindowsInstallerW, NULL, &dwType, (LPBYTE)&value, &size)
285 && dwType == REG_DWORD && value == 1)
287 static const WCHAR fmtW[] = {'m','s','i','e','x','e','c',' ','/','i','%','s',0};
288 int len = lstrlenW(fmtW) + lstrlenW(subKeyName);
290 if (!(info->path_modify = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto err;
291 wsprintfW(info->path_modify, fmtW, subKeyName);
293 else if (!RegQueryValueExW(hkeyApp, ModifyPathW, 0, 0, NULL, &displen))
295 if (!(info->path_modify = HeapAlloc(GetProcessHeap(), 0, displen))) goto err;
296 RegQueryValueExW(hkeyApp, ModifyPathW, 0, 0, (LPBYTE)info->path_modify, &displen);
301 info->regroot = root;
302 lstrcpyW(info->regkey, subKeyName);
303 info->path = command;
306 list_add_tail( &app_list, &info->entry );
309 RegCloseKey(hkeyApp);
310 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
315 RegCloseKey(hkeyApp);
316 if (info) FreeAppInfo(info);
317 HeapFree(GetProcessHeap(), 0, command);
322 /******************************************************************************
323 * Name : AddApplicationsToList
324 * Description: Populates the list box with applications.
325 * Parameters : hWnd - Handle of the dialog box
327 static void AddApplicationsToList(HWND hWnd, HIMAGELIST hList)
334 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
336 if (!iter->title[0]) continue;
343 if (ExtractIconExW(iter->icon, iter->iconIdx, NULL, &hIcon, 1) == 1)
345 index = ImageList_AddIcon(hList, hIcon);
350 lvItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
351 lvItem.iItem = iter->id;
353 lvItem.pszText = iter->title;
354 lvItem.iImage = index;
355 lvItem.lParam = iter->id;
357 index = ListView_InsertItemW(hWnd, &lvItem);
359 /* now add the subitems (columns) */
360 ListView_SetItemTextW(hWnd, index, 1, iter->publisher);
361 ListView_SetItemTextW(hWnd, index, 2, iter->version);
365 /******************************************************************************
366 * Name : RemoveItemsFromList
367 * Description: Clears the application list box.
368 * Parameters : hWnd - Handle of the dialog box
370 static void RemoveItemsFromList(HWND hWnd)
372 SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_DELETEALLITEMS, 0, 0);
375 /******************************************************************************
377 * Description: Frees memory used by the application linked list.
379 static inline void EmptyList(void)
381 APPINFO *info, *next;
382 LIST_FOR_EACH_ENTRY_SAFE( info, next, &app_list, APPINFO, entry )
384 list_remove( &info->entry );
389 /******************************************************************************
390 * Name : UpdateButtons
391 * Description: Enables/disables the Add/Remove button depending on current
392 * selection in list box.
393 * Parameters : hWnd - Handle of the dialog box
395 static void UpdateButtons(HWND hWnd)
399 LRESULT selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETNEXTITEM, -1,
400 LVNI_FOCUSED | LVNI_SELECTED);
401 BOOL enable_modify = FALSE;
405 lvItem.iItem = selitem;
406 lvItem.mask = LVIF_PARAM;
408 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW, 0, (LPARAM) &lvItem))
410 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
412 if (iter->id == lvItem.lParam)
414 /* Decide whether to display Modify/Remove as one button or two */
415 enable_modify = (iter->path_modify != NULL);
417 /* Update title as appropriate */
418 if (iter->path_modify == NULL)
419 SetWindowTextW(GetDlgItem(hWnd, IDC_ADDREMOVE), btnModifyRemove);
421 SetWindowTextW(GetDlgItem(hWnd, IDC_ADDREMOVE), btnRemove);
429 /* Enable/disable other buttons if necessary */
430 EnableWindow(GetDlgItem(hWnd, IDC_ADDREMOVE), (selitem != -1));
431 EnableWindow(GetDlgItem(hWnd, IDC_SUPPORT_INFO), (selitem != -1));
432 EnableWindow(GetDlgItem(hWnd, IDC_MODIFY), enable_modify);
435 /******************************************************************************
436 * Name : InstallProgram
437 * Description: Search for potential Installer and execute it.
438 * Parameters : hWnd - Handle of the dialog box
440 static void InstallProgram(HWND hWnd)
442 static const WCHAR filters[] = {'%','s','%','c','*','i','n','s','t','a','l','*','.','e','x','e',';','*','s','e','t','u','p','*','.','e','x','e',';','*','.','m','s','i','%','c','%','s','%','c','*','.','e','x','e','%','c','%','s','%','c','*','.','*','%','c',0}
445 WCHAR titleW[MAX_STRING_LEN];
446 WCHAR filter_installs[MAX_STRING_LEN];
447 WCHAR filter_programs[MAX_STRING_LEN];
448 WCHAR filter_all[MAX_STRING_LEN];
449 WCHAR FilterBufferW[MAX_PATH];
450 WCHAR FileNameBufferW[MAX_PATH];
452 LoadStringW(hInst, IDS_CPL_TITLE, titleW, sizeof(titleW)/sizeof(WCHAR));
453 LoadStringW(hInst, IDS_FILTER_INSTALLS, filter_installs, sizeof(filter_installs)/sizeof(WCHAR));
454 LoadStringW(hInst, IDS_FILTER_PROGRAMS, filter_programs, sizeof(filter_programs)/sizeof(WCHAR));
455 LoadStringW(hInst, IDS_FILTER_ALL, filter_all, sizeof(filter_all)/sizeof(WCHAR));
457 snprintfW( FilterBufferW, MAX_PATH, filters, filter_installs, 0, 0,
458 filter_programs, 0, 0, filter_all, 0, 0 );
459 memset(&ofn, 0, sizeof(OPENFILENAMEW));
460 ofn.lStructSize = sizeof(OPENFILENAMEW);
461 ofn.hwndOwner = hWnd;
462 ofn.hInstance = hInst;
463 ofn.lpstrFilter = FilterBufferW;
464 ofn.nFilterIndex = 0;
465 ofn.lpstrFile = FileNameBufferW;
466 ofn.nMaxFile = MAX_PATH;
467 ofn.lpstrFileTitle = NULL;
468 ofn.nMaxFileTitle = 0;
469 ofn.lpstrTitle = titleW;
470 ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLESIZING;
471 FileNameBufferW[0] = 0;
473 if (GetOpenFileNameW(&ofn))
475 SHELLEXECUTEINFOW sei;
476 memset(&sei, 0, sizeof(sei));
477 sei.cbSize = sizeof(sei);
479 sei.nShow = SW_SHOWDEFAULT;
480 sei.fMask = SEE_MASK_NO_CONSOLE;
481 sei.lpFile = ofn.lpstrFile;
483 ShellExecuteExW(&sei);
487 /******************************************************************************
488 * Name : UninstallProgram
489 * Description: Executes the specified program's installer.
490 * Parameters : id - the internal ID of the installer to remove
491 * Parameters : button - ID of button pressed (Modify or Remove)
493 static void UninstallProgram(int id, DWORD button)
497 PROCESS_INFORMATION info;
498 WCHAR errormsg[MAX_STRING_LEN];
499 WCHAR sUninstallFailed[MAX_STRING_LEN];
503 LoadStringW(hInst, IDS_UNINSTALL_FAILED, sUninstallFailed,
504 sizeof(sUninstallFailed) / sizeof(sUninstallFailed[0]));
506 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
510 TRACE("Uninstalling %s (%s)\n", wine_dbgstr_w(iter->title),
511 wine_dbgstr_w(iter->path));
513 memset(&si, 0, sizeof(STARTUPINFOW));
514 si.cb = sizeof(STARTUPINFOW);
515 si.wShowWindow = SW_NORMAL;
517 res = CreateProcessW(NULL, (button == IDC_MODIFY) ? iter->path_modify : iter->path,
518 NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
522 CloseHandle(info.hThread);
524 /* wait for the process to exit */
525 WaitForSingleObject(info.hProcess, INFINITE);
526 CloseHandle(info.hProcess);
530 wsprintfW(errormsg, sUninstallFailed, iter->path);
532 if (MessageBoxW(0, errormsg, iter->title, MB_YESNO |
533 MB_ICONQUESTION) == IDYES)
535 /* delete the application's uninstall entry */
536 RegOpenKeyExW(iter->regroot, PathUninstallW, 0, KEY_READ, &hkey);
537 RegDeleteKeyW(hkey, iter->regkey);
547 /**********************************************************************************
548 * Name : SetInfoDialogText
549 * Description: Sets the text of a label in a window, based upon a registry entry
550 * or string passed to the function.
551 * Parameters : hKey - registry entry to read from, NULL if not reading
553 * lpKeyName - key to read from, or string to check if hKey is NULL
554 * lpAltMessage - alternative message if entry not found
555 * hWnd - handle of dialog box
556 * iDlgItem - ID of label in dialog box
558 static void SetInfoDialogText(HKEY hKey, LPCWSTR lpKeyName, LPCWSTR lpAltMessage,
559 HWND hWnd, int iDlgItem)
561 WCHAR buf[MAX_STRING_LEN];
565 hWndDlgItem = GetDlgItem(hWnd, iDlgItem);
567 /* if hKey is null, lpKeyName contains the string we want to check */
570 if ((lpKeyName) && (lstrlenW(lpKeyName) > 0))
571 SetWindowTextW(hWndDlgItem, lpKeyName);
573 SetWindowTextW(hWndDlgItem, lpAltMessage);
577 buflen = MAX_STRING_LEN;
579 if ((RegQueryValueExW(hKey, lpKeyName, 0, 0, (LPBYTE) buf, &buflen) ==
580 ERROR_SUCCESS) && (lstrlenW(buf) > 0))
581 SetWindowTextW(hWndDlgItem, buf);
583 SetWindowTextW(hWndDlgItem, lpAltMessage);
587 /******************************************************************************
588 * Name : SupportInfoDlgProc
589 * Description: Callback procedure for support info dialog
590 * Parameters : hWnd - hWnd of the window
591 * msg - reason for calling function
592 * wParam - additional parameter
593 * lParam - additional parameter
594 * Returns : Depends on the message
596 static INT_PTR CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
600 WCHAR oldtitle[MAX_STRING_LEN];
601 WCHAR buf[MAX_STRING_LEN];
602 WCHAR key[MAX_STRING_LEN];
603 WCHAR notfound[MAX_STRING_LEN];
608 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
610 if (iter->id == (int) lParam)
612 lstrcpyW(key, PathUninstallW);
613 lstrcatW(key, BackSlashW);
614 lstrcatW(key, iter->regkey);
616 /* check the application's registry entries */
617 RegOpenKeyExW(iter->regroot, key, 0, KEY_READ, &hkey);
619 /* Load our "not specified" string */
620 LoadStringW(hInst, IDS_NOT_SPECIFIED, notfound,
621 sizeof(notfound) / sizeof(notfound[0]));
623 /* Update the data for items already read into the structure */
624 SetInfoDialogText(NULL, iter->publisher, notfound, hWnd,
626 SetInfoDialogText(NULL, iter->version, notfound, hWnd,
629 /* And now update the data for those items in the registry */
630 SetInfoDialogText(hkey, ContactW, notfound, hWnd,
632 SetInfoDialogText(hkey, HelpLinkW, notfound, hWnd,
634 SetInfoDialogText(hkey, HelpTelephoneW, notfound, hWnd,
636 SetInfoDialogText(hkey, ReadmeW, notfound, hWnd,
638 SetInfoDialogText(hkey, URLUpdateInfoW, notfound, hWnd,
640 SetInfoDialogText(hkey, CommentsW, notfound, hWnd,
643 /* Update the main label with the app name */
644 if (GetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), oldtitle,
645 MAX_STRING_LEN) != 0)
647 wsprintfW(buf, oldtitle, iter->title);
648 SetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), buf);
663 switch (LOWORD(wParam))
666 EndDialog(hWnd, TRUE);
677 /******************************************************************************
679 * Description: Displays the Support Information dialog
680 * Parameters : hWnd - Handle of the main dialog
681 * id - ID of the application to display information for
683 static void SupportInfo(HWND hWnd, int id)
685 DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_INFO), hWnd, SupportInfoDlgProc, id);
688 /* Definition of column headers for AddListViewColumns function */
689 typedef struct AppWizColumn {
695 static const AppWizColumn columns[] = {
696 {200, LVCFMT_LEFT, IDS_COLUMN_NAME},
697 {150, LVCFMT_LEFT, IDS_COLUMN_PUBLISHER},
698 {100, LVCFMT_LEFT, IDS_COLUMN_VERSION},
701 /******************************************************************************
702 * Name : AddListViewColumns
703 * Description: Adds column headers to the list view control.
704 * Parameters : hWnd - Handle of the list view control.
705 * Returns : TRUE if completed successfully, FALSE otherwise.
707 static BOOL AddListViewColumns(HWND hWnd)
709 WCHAR buf[MAX_STRING_LEN];
713 lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
715 /* Add the columns */
716 for (i = 0; i < sizeof(columns) / sizeof(columns[0]); i++)
721 /* set width and format */
722 lvc.cx = columns[i].width;
723 lvc.fmt = columns[i].fmt;
725 LoadStringW(hInst, columns[i].title, buf, sizeof(buf) / sizeof(buf[0]));
727 if (ListView_InsertColumnW(hWnd, i, &lvc) == -1)
734 /******************************************************************************
735 * Name : AddListViewImageList
736 * Description: Creates an ImageList for the list view control.
737 * Parameters : hWnd - Handle of the list view control.
738 * Returns : Handle of the image list.
740 static HIMAGELIST AddListViewImageList(HWND hWnd)
745 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
746 ILC_COLOR32 | ILC_MASK, 1, 1);
748 /* Add default icon to image list */
749 hDefaultIcon = LoadIconW(hInst, MAKEINTRESOURCEW(ICO_MAIN));
750 ImageList_AddIcon(hSmall, hDefaultIcon);
751 DestroyIcon(hDefaultIcon);
753 SendMessageW(hWnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)hSmall);
758 /******************************************************************************
759 * Name : ResetApplicationList
760 * Description: Empties the app list, if need be, and recreates it.
761 * Parameters : bFirstRun - TRUE if this is the first time this is run, FALSE otherwise
762 * hWnd - handle of the dialog box
763 * hImageList - handle of the image list
764 * Returns : New handle of the image list.
766 static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hImageList)
768 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
772 hWndListView = GetDlgItem(hWnd, IDL_PROGRAMS);
774 /* if first run, create the image list and add the listview columns */
777 if (!AddListViewColumns(hWndListView))
780 else /* we need to remove the existing things first */
782 RemoveItemsFromList(hWnd);
783 ImageList_Destroy(hImageList);
785 /* reset the list, since it's probably changed if the uninstallation was
790 /* now create the image list and add the applications to the listview */
791 hImageList = AddListViewImageList(hWndListView);
793 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninstallW, 0, KEY_READ, &hkey))
795 ReadApplicationsFromRegistry(hkey);
799 !RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninstallW, 0, KEY_READ|KEY_WOW64_32KEY, &hkey))
801 ReadApplicationsFromRegistry(hkey);
804 if (!RegOpenKeyExW(HKEY_CURRENT_USER, PathUninstallW, 0, KEY_READ, &hkey))
806 ReadApplicationsFromRegistry(hkey);
810 AddApplicationsToList(hWndListView, hImageList);
816 /******************************************************************************
818 * Description: Callback procedure for main tab
819 * Parameters : hWnd - hWnd of the window
820 * msg - reason for calling function
821 * wParam - additional parameter
822 * lParam - additional parameter
823 * Returns : Depends on the message
825 static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
828 static HIMAGELIST hImageList;
835 hImageList = ResetApplicationList(TRUE, hWnd, hImageList);
843 RemoveItemsFromList(hWnd);
844 ImageList_Destroy(hImageList);
851 nmh = (LPNMHDR) lParam;
858 case LVN_ITEMCHANGED:
868 switch (LOWORD(wParam))
871 InstallProgram(hWnd);
876 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
877 LVM_GETNEXTITEM, -1, LVNI_FOCUSED|LVNI_SELECTED);
881 lvItem.iItem = selitem;
882 lvItem.mask = LVIF_PARAM;
884 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
885 0, (LPARAM) &lvItem))
886 UninstallProgram(lvItem.lParam, LOWORD(wParam));
889 hImageList = ResetApplicationList(FALSE, hWnd, hImageList);
893 case IDC_SUPPORT_INFO:
894 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
895 LVM_GETNEXTITEM, -1, LVNI_FOCUSED | LVNI_SELECTED);
899 lvItem.iItem = selitem;
900 lvItem.mask = LVIF_PARAM;
902 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
903 0, (LPARAM) &lvItem))
904 SupportInfo(hWnd, lvItem.lParam);
916 static int CALLBACK propsheet_callback( HWND hwnd, UINT msg, LPARAM lparam )
920 case PSCB_INITIALIZED:
921 SendMessageW( hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW( hInst, MAKEINTRESOURCEW(ICO_MAIN) ));
927 /******************************************************************************
929 * Description: Main routine for applet
930 * Parameters : hWnd - hWnd of the Control Panel
932 static void StartApplet(HWND hWnd)
935 PROPSHEETHEADERW psh;
936 WCHAR tab_title[MAX_STRING_LEN], app_title[MAX_STRING_LEN];
938 /* Load the strings we will use */
939 LoadStringW(hInst, IDS_TAB1_TITLE, tab_title, sizeof(tab_title) / sizeof(tab_title[0]));
940 LoadStringW(hInst, IDS_CPL_TITLE, app_title, sizeof(app_title) / sizeof(app_title[0]));
941 LoadStringW(hInst, IDS_REMOVE, btnRemove, sizeof(btnRemove) / sizeof(btnRemove[0]));
942 LoadStringW(hInst, IDS_MODIFY_REMOVE, btnModifyRemove, sizeof(btnModifyRemove) / sizeof(btnModifyRemove[0]));
944 /* Fill out the PROPSHEETPAGE */
945 psp.dwSize = sizeof (PROPSHEETPAGEW);
946 psp.dwFlags = PSP_USETITLE;
947 psp.hInstance = hInst;
948 psp.u.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN);
949 psp.u2.pszIcon = NULL;
950 psp.pfnDlgProc = MainDlgProc;
951 psp.pszTitle = tab_title;
954 /* Fill out the PROPSHEETHEADER */
955 psh.dwSize = sizeof (PROPSHEETHEADERW);
956 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
957 psh.hwndParent = hWnd;
958 psh.hInstance = hInst;
959 psh.u.pszIcon = MAKEINTRESOURCEW(ICO_MAIN);
960 psh.pszCaption = app_title;
963 psh.pfnCallback = propsheet_callback;
964 psh.u2.nStartPage = 0;
966 /* Display the property sheet */
967 PropertySheetW (&psh);
970 static LONG start_params(const WCHAR *params)
972 static const WCHAR install_geckoW[] = {'i','n','s','t','a','l','l','_','g','e','c','k','o',0};
973 static const WCHAR install_monoW[] = {'i','n','s','t','a','l','l','_','m','o','n','o',0};
978 if(!strcmpW(params, install_geckoW)) {
979 install_addon(ADDON_GECKO);
983 if(!strcmpW(params, install_monoW)) {
984 install_addon(ADDON_MONO);
988 WARN("unknown param %s\n", debugstr_w(params));
992 /******************************************************************************
994 * Description: Entry point for Control Panel applets
995 * Parameters : hwndCPL - hWnd of the Control Panel
996 * message - reason for calling function
997 * lParam1 - additional parameter
998 * lParam2 - additional parameter
999 * Returns : Depends on the message
1001 LONG CALLBACK CPlApplet(HWND hwndCPL, UINT message, LPARAM lParam1, LPARAM lParam2)
1003 INITCOMMONCONTROLSEX iccEx;
1008 iccEx.dwSize = sizeof(iccEx);
1009 iccEx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES | ICC_LINK_CLASS;
1011 InitCommonControlsEx(&iccEx);
1018 case CPL_STARTWPARMSW:
1019 return start_params((const WCHAR *)lParam2);
1023 CPLINFO *appletInfo = (CPLINFO *) lParam2;
1025 appletInfo->idIcon = ICO_MAIN;
1026 appletInfo->idName = IDS_CPL_TITLE;
1027 appletInfo->idInfo = IDS_CPL_DESC;
1028 appletInfo->lData = 0;
1034 StartApplet(hwndCPL);