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};
104 static const WCHAR PathUninstallW[] = {
105 'S','o','f','t','w','a','r','e','\\',
106 'M','i','c','r','o','s','o','f','t','\\',
107 'W','i','n','d','o','w','s','\\',
108 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
109 'U','n','i','n','s','t','a','l','l',0 };
111 /******************************************************************************
113 * Description: Entry point for DLL file
115 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
118 TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
122 case DLL_PROCESS_ATTACH:
129 /******************************************************************************
131 * Description: Frees memory used by an AppInfo structure, and any children.
133 static void FreeAppInfo(APPINFO *info)
135 HeapFree(GetProcessHeap(), 0, info->title);
136 HeapFree(GetProcessHeap(), 0, info->path);
137 HeapFree(GetProcessHeap(), 0, info->path_modify);
138 HeapFree(GetProcessHeap(), 0, info->icon);
139 HeapFree(GetProcessHeap(), 0, info->publisher);
140 HeapFree(GetProcessHeap(), 0, info->version);
141 HeapFree(GetProcessHeap(), 0, info);
144 /******************************************************************************
145 * Name : ReadApplicationsFromRegistry
146 * Description: Creates a linked list of uninstallable applications from the
148 * Parameters : root - Which registry root to read from (HKCU/HKLM)
149 * Returns : TRUE if successful, FALSE otherwise
151 static BOOL ReadApplicationsFromRegistry(HKEY root)
153 HKEY hkeyUninst, hkeyApp;
155 DWORD sizeOfSubKeyName, displen, uninstlen;
156 DWORD dwNoModify, dwType, value;
157 WCHAR subKeyName[256];
158 WCHAR key_app[MAX_STRING_LEN];
160 APPINFO *info = NULL;
164 if (RegOpenKeyExW(root, PathUninstallW, 0, KEY_READ, &hkeyUninst) !=
168 lstrcpyW(key_app, PathUninstallW);
169 lstrcatW(key_app, BackSlashW);
170 p = key_app+lstrlenW(PathUninstallW)+1;
172 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
174 for (i = 0; RegEnumKeyExW(hkeyUninst, i, subKeyName, &sizeOfSubKeyName, NULL,
175 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS; ++i)
177 lstrcpyW(p, subKeyName);
178 RegOpenKeyExW(root, key_app, 0, KEY_READ, &hkeyApp);
182 if (!RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen))
184 if (!RegQueryValueExW(hkeyApp, WindowsInstallerW, NULL, &dwType, NULL, &value)
185 && dwType == REG_DWORD && value == 1)
187 static const WCHAR fmtW[] = {'m','s','i','e','x','e','c',' ','/','x','%','s',0};
188 int len = lstrlenW(fmtW) + lstrlenW(subKeyName);
190 if (!(command = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto err;
191 wsprintfW(command, fmtW, subKeyName);
193 else if (!RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, NULL, &uninstlen))
195 if (!(command = HeapAlloc(GetProcessHeap(), 0, uninstlen))) goto err;
196 RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, (LPBYTE)command, &uninstlen);
200 RegCloseKey(hkeyApp);
201 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
205 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct APPINFO));
208 info->title = HeapAlloc(GetProcessHeap(), 0, displen);
213 RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)info->title,
216 /* now get DisplayIcon */
218 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, NULL, &displen);
224 info->icon = HeapAlloc(GetProcessHeap(), 0, displen);
229 RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, (LPBYTE)info->icon,
232 /* separate the index from the icon name, if supplied */
233 iconPtr = strchrW(info->icon, ',');
238 info->iconIdx = atoiW(iconPtr);
242 /* publisher, version */
243 if (RegQueryValueExW(hkeyApp, PublisherW, 0, 0, NULL, &displen) ==
246 info->publisher = HeapAlloc(GetProcessHeap(), 0, displen);
248 if (!info->publisher)
251 RegQueryValueExW(hkeyApp, PublisherW, 0, 0, (LPBYTE)info->publisher,
255 if (RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, NULL, &displen) ==
258 info->version = HeapAlloc(GetProcessHeap(), 0, displen);
263 RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, (LPBYTE)info->version,
267 /* Check if NoModify is set */
270 displen = sizeof(DWORD);
272 if (RegQueryValueExW(hkeyApp, NoModifyW, NULL, &dwType, (LPBYTE)&dwNoModify, &displen)
278 /* Some installers incorrectly create a REG_SZ instead of a REG_DWORD */
279 if (dwType == REG_SZ)
280 dwNoModify = (*(BYTE *)&dwNoModify == '1');
282 /* Fetch the modify path */
285 if (!RegQueryValueExW(hkeyApp, WindowsInstallerW, NULL, &dwType, NULL, &value)
286 && dwType == REG_DWORD && value == 1)
288 static const WCHAR fmtW[] = {'m','s','i','e','x','e','c',' ','/','i','%','s',0};
289 int len = lstrlenW(fmtW) + lstrlenW(subKeyName);
291 if (!(info->path_modify = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto err;
292 wsprintfW(info->path_modify, fmtW, subKeyName);
294 else if (!RegQueryValueExW(hkeyApp, ModifyPathW, 0, 0, NULL, &displen))
296 if (!(info->path_modify = HeapAlloc(GetProcessHeap(), 0, displen))) goto err;
297 RegQueryValueExW(hkeyApp, ModifyPathW, 0, 0, (LPBYTE)info->path_modify, &displen);
302 info->regroot = root;
303 lstrcpyW(info->regkey, subKeyName);
304 info->path = command;
307 list_add_tail( &app_list, &info->entry );
310 RegCloseKey(hkeyApp);
311 sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]);
318 RegCloseKey(hkeyApp);
319 if (info) FreeAppInfo(info);
322 RegCloseKey(hkeyUninst);
327 /******************************************************************************
328 * Name : AddApplicationsToList
329 * Description: Populates the list box with applications.
330 * Parameters : hWnd - Handle of the dialog box
332 static void AddApplicationsToList(HWND hWnd, HIMAGELIST hList)
339 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
341 if (!iter->title[0]) continue;
348 if (ExtractIconExW(iter->icon, iter->iconIdx, NULL, &hIcon, 1) == 1)
350 index = ImageList_AddIcon(hList, hIcon);
355 lvItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
356 lvItem.iItem = iter->id;
358 lvItem.pszText = iter->title;
359 lvItem.iImage = index;
360 lvItem.lParam = iter->id;
362 index = ListView_InsertItemW(hWnd, &lvItem);
364 /* now add the subitems (columns) */
365 ListView_SetItemTextW(hWnd, index, 1, iter->publisher);
366 ListView_SetItemTextW(hWnd, index, 2, iter->version);
370 /******************************************************************************
371 * Name : RemoveItemsFromList
372 * Description: Clears the application list box.
373 * Parameters : hWnd - Handle of the dialog box
375 static void RemoveItemsFromList(HWND hWnd)
377 SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_DELETEALLITEMS, 0, 0);
380 /******************************************************************************
382 * Description: Frees memory used by the application linked list.
384 static inline void EmptyList(void)
386 APPINFO *info, *next;
387 LIST_FOR_EACH_ENTRY_SAFE( info, next, &app_list, APPINFO, entry )
389 list_remove( &info->entry );
394 /******************************************************************************
395 * Name : UpdateButtons
396 * Description: Enables/disables the Add/Remove button depending on current
397 * selection in list box.
398 * Parameters : hWnd - Handle of the dialog box
400 static void UpdateButtons(HWND hWnd)
404 LRESULT selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETNEXTITEM, -1,
405 LVNI_FOCUSED | LVNI_SELECTED);
406 BOOL enable_modify = FALSE;
410 lvItem.iItem = selitem;
411 lvItem.mask = LVIF_PARAM;
413 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW, 0, (LPARAM) &lvItem))
415 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
417 if (iter->id == lvItem.lParam)
419 /* Decide whether to display Modify/Remove as one button or two */
420 enable_modify = (iter->path_modify != NULL);
422 /* Update title as appropriate */
423 if (iter->path_modify == NULL)
424 SetWindowTextW(GetDlgItem(hWnd, IDC_ADDREMOVE), btnModifyRemove);
426 SetWindowTextW(GetDlgItem(hWnd, IDC_ADDREMOVE), btnRemove);
434 /* Enable/disable other buttons if necessary */
435 EnableWindow(GetDlgItem(hWnd, IDC_ADDREMOVE), (selitem != -1));
436 EnableWindow(GetDlgItem(hWnd, IDC_SUPPORT_INFO), (selitem != -1));
437 EnableWindow(GetDlgItem(hWnd, IDC_MODIFY), enable_modify);
440 /******************************************************************************
441 * Name : InstallProgram
442 * Description: Search for potential Installer and execute it.
443 * Parameters : hWnd - Handle of the dialog box
445 static void InstallProgram(HWND hWnd)
448 WCHAR titleW[MAX_STRING_LEN];
449 WCHAR FilterBufferW[MAX_STRING_LEN];
450 WCHAR FileNameBufferW[MAX_PATH];
452 LoadStringW(hInst, IDS_CPL_TITLE, titleW, sizeof(titleW)/sizeof(WCHAR));
453 LoadStringW(hInst, IDS_INSTALL_FILTER, FilterBufferW, sizeof(FilterBufferW)/sizeof(WCHAR));
455 memset(&ofn, 0, sizeof(OPENFILENAMEW));
456 ofn.lStructSize = sizeof(OPENFILENAMEW);
457 ofn.hwndOwner = hWnd;
458 ofn.hInstance = hInst;
459 ofn.lpstrFilter = FilterBufferW;
460 ofn.nFilterIndex = 0;
461 ofn.lpstrFile = FileNameBufferW;
462 ofn.nMaxFile = MAX_PATH;
463 ofn.lpstrFileTitle = NULL;
464 ofn.nMaxFileTitle = 0;
465 ofn.lpstrTitle = titleW;
466 ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLESIZING;
467 FileNameBufferW[0] = 0;
469 if (GetOpenFileNameW(&ofn))
471 SHELLEXECUTEINFOW sei;
472 memset(&sei, 0, sizeof(sei));
473 sei.cbSize = sizeof(sei);
475 sei.nShow = SW_SHOWDEFAULT;
476 sei.fMask = SEE_MASK_NO_CONSOLE;
477 sei.lpFile = ofn.lpstrFile;
479 ShellExecuteExW(&sei);
483 /******************************************************************************
484 * Name : UninstallProgram
485 * Description: Executes the specified program's installer.
486 * Parameters : id - the internal ID of the installer to remove
487 * Parameters : button - ID of button pressed (Modify or Remove)
489 static void UninstallProgram(int id, DWORD button)
493 PROCESS_INFORMATION info;
494 WCHAR errormsg[MAX_STRING_LEN];
495 WCHAR sUninstallFailed[MAX_STRING_LEN];
499 LoadStringW(hInst, IDS_UNINSTALL_FAILED, sUninstallFailed,
500 sizeof(sUninstallFailed) / sizeof(sUninstallFailed[0]));
502 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
506 TRACE("Uninstalling %s (%s)\n", wine_dbgstr_w(iter->title),
507 wine_dbgstr_w(iter->path));
509 memset(&si, 0, sizeof(STARTUPINFOW));
510 si.cb = sizeof(STARTUPINFOW);
511 si.wShowWindow = SW_NORMAL;
513 res = CreateProcessW(NULL, (button == IDC_MODIFY) ? iter->path_modify : iter->path,
514 NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
518 CloseHandle(info.hThread);
520 /* wait for the process to exit */
521 WaitForSingleObject(info.hProcess, INFINITE);
522 CloseHandle(info.hProcess);
526 wsprintfW(errormsg, sUninstallFailed, iter->path);
528 if (MessageBoxW(0, errormsg, iter->title, MB_YESNO |
529 MB_ICONQUESTION) == IDYES)
531 /* delete the application's uninstall entry */
532 RegOpenKeyExW(iter->regroot, PathUninstallW, 0, KEY_READ, &hkey);
533 RegDeleteKeyW(hkey, iter->regkey);
543 /**********************************************************************************
544 * Name : SetInfoDialogText
545 * Description: Sets the text of a label in a window, based upon a registry entry
546 * or string passed to the function.
547 * Parameters : hKey - registry entry to read from, NULL if not reading
549 * lpKeyName - key to read from, or string to check if hKey is NULL
550 * lpAltMessage - alternative message if entry not found
551 * hWnd - handle of dialog box
552 * iDlgItem - ID of label in dialog box
554 static void SetInfoDialogText(HKEY hKey, LPCWSTR lpKeyName, LPCWSTR lpAltMessage,
555 HWND hWnd, int iDlgItem)
557 WCHAR buf[MAX_STRING_LEN];
561 hWndDlgItem = GetDlgItem(hWnd, iDlgItem);
563 /* if hKey is null, lpKeyName contains the string we want to check */
566 if ((lpKeyName) && (lstrlenW(lpKeyName) > 0))
567 SetWindowTextW(hWndDlgItem, lpKeyName);
569 SetWindowTextW(hWndDlgItem, lpAltMessage);
573 buflen = MAX_STRING_LEN;
575 if ((RegQueryValueExW(hKey, lpKeyName, 0, 0, (LPBYTE) buf, &buflen) ==
576 ERROR_SUCCESS) && (lstrlenW(buf) > 0))
577 SetWindowTextW(hWndDlgItem, buf);
579 SetWindowTextW(hWndDlgItem, lpAltMessage);
583 /******************************************************************************
584 * Name : SupportInfoDlgProc
585 * Description: Callback procedure for support info dialog
586 * Parameters : hWnd - hWnd of the window
587 * msg - reason for calling function
588 * wParam - additional parameter
589 * lParam - additional parameter
590 * Returns : Dependant on message
592 static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
596 WCHAR oldtitle[MAX_STRING_LEN];
597 WCHAR buf[MAX_STRING_LEN];
598 WCHAR key[MAX_STRING_LEN];
599 WCHAR notfound[MAX_STRING_LEN];
604 LIST_FOR_EACH_ENTRY( iter, &app_list, APPINFO, entry )
606 if (iter->id == (int) lParam)
608 lstrcpyW(key, PathUninstallW);
609 lstrcatW(key, BackSlashW);
610 lstrcatW(key, iter->regkey);
612 /* check the application's registry entries */
613 RegOpenKeyExW(iter->regroot, key, 0, KEY_READ, &hkey);
615 /* Load our "not specified" string */
616 LoadStringW(hInst, IDS_NOT_SPECIFIED, notfound,
617 sizeof(notfound) / sizeof(notfound[0]));
619 /* Update the data for items already read into the structure */
620 SetInfoDialogText(NULL, iter->publisher, notfound, hWnd,
622 SetInfoDialogText(NULL, iter->version, notfound, hWnd,
625 /* And now update the data for those items in the registry */
626 SetInfoDialogText(hkey, ContactW, notfound, hWnd,
628 SetInfoDialogText(hkey, HelpLinkW, notfound, hWnd,
630 SetInfoDialogText(hkey, HelpTelephoneW, notfound, hWnd,
632 SetInfoDialogText(hkey, ReadmeW, notfound, hWnd,
634 SetInfoDialogText(hkey, URLUpdateInfoW, notfound, hWnd,
636 SetInfoDialogText(hkey, CommentsW, notfound, hWnd,
639 /* Update the main label with the app name */
640 if (GetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), oldtitle,
641 MAX_STRING_LEN) != 0)
643 wsprintfW(buf, oldtitle, iter->title);
644 SetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), buf);
659 switch (LOWORD(wParam))
662 EndDialog(hWnd, TRUE);
673 /******************************************************************************
675 * Description: Displays the Support Information dialog
676 * Parameters : hWnd - Handle of the main dialog
677 * id - ID of the application to display information for
679 static void SupportInfo(HWND hWnd, int id)
681 DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_INFO), hWnd, (DLGPROC)
682 SupportInfoDlgProc, (LPARAM) id);
685 /* Definition of column headers for AddListViewColumns function */
686 typedef struct AppWizColumn {
692 static const AppWizColumn columns[] = {
693 {200, LVCFMT_LEFT, IDS_COLUMN_NAME},
694 {150, LVCFMT_LEFT, IDS_COLUMN_PUBLISHER},
695 {100, LVCFMT_LEFT, IDS_COLUMN_VERSION},
698 /******************************************************************************
699 * Name : AddListViewColumns
700 * Description: Adds column headers to the list view control.
701 * Parameters : hWnd - Handle of the list view control.
702 * Returns : TRUE if completed successfully, FALSE otherwise.
704 static BOOL AddListViewColumns(HWND hWnd)
706 WCHAR buf[MAX_STRING_LEN];
710 lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
712 /* Add the columns */
713 for (i = 0; i < sizeof(columns) / sizeof(columns[0]); i++)
718 /* set width and format */
719 lvc.cx = columns[i].width;
720 lvc.fmt = columns[i].fmt;
722 LoadStringW(hInst, columns[i].title, buf, sizeof(buf) / sizeof(buf[0]));
724 if (ListView_InsertColumnW(hWnd, i, &lvc) == -1)
731 /******************************************************************************
732 * Name : AddListViewImageList
733 * Description: Creates an ImageList for the list view control.
734 * Parameters : hWnd - Handle of the list view control.
735 * Returns : Handle of the image list.
737 static HIMAGELIST AddListViewImageList(HWND hWnd)
742 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
743 ILC_COLOR32 | ILC_MASK, 1, 1);
745 /* Add default icon to image list */
746 hDefaultIcon = LoadIconW(hInst, MAKEINTRESOURCEW(ICO_MAIN));
747 ImageList_AddIcon(hSmall, hDefaultIcon);
748 DestroyIcon(hDefaultIcon);
750 SendMessageW(hWnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)hSmall);
755 /******************************************************************************
756 * Name : ResetApplicationList
757 * Description: Empties the app list, if need be, and recreates it.
758 * Parameters : bFirstRun - TRUE if this is the first time this is run, FALSE otherwise
759 * hWnd - handle of the dialog box
760 * hImageList - handle of the image list
761 * Returns : New handle of the image list.
763 static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hImageList)
767 hWndListView = GetDlgItem(hWnd, IDL_PROGRAMS);
769 /* if first run, create the image list and add the listview columns */
772 if (!AddListViewColumns(hWndListView))
775 else /* we need to remove the existing things first */
777 RemoveItemsFromList(hWnd);
778 ImageList_Destroy(hImageList);
780 /* reset the list, since it's probably changed if the uninstallation was
785 /* now create the image list and add the applications to the listview */
786 hImageList = AddListViewImageList(hWndListView);
788 ReadApplicationsFromRegistry(HKEY_LOCAL_MACHINE);
789 ReadApplicationsFromRegistry(HKEY_CURRENT_USER);
791 AddApplicationsToList(hWndListView, hImageList);
797 /******************************************************************************
799 * Description: Callback procedure for main tab
800 * Parameters : hWnd - hWnd of the window
801 * msg - reason for calling function
802 * wParam - additional parameter
803 * lParam - additional parameter
804 * Returns : Dependant on message
806 static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
809 static HIMAGELIST hImageList;
816 hImageList = ResetApplicationList(TRUE, hWnd, hImageList);
824 RemoveItemsFromList(hWnd);
825 ImageList_Destroy(hImageList);
832 nmh = (LPNMHDR) lParam;
839 case LVN_ITEMCHANGED:
849 switch (LOWORD(wParam))
852 InstallProgram(hWnd);
857 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
858 LVM_GETNEXTITEM, -1, LVNI_FOCUSED|LVNI_SELECTED);
862 lvItem.iItem = selitem;
863 lvItem.mask = LVIF_PARAM;
865 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
866 0, (LPARAM) &lvItem))
867 UninstallProgram(lvItem.lParam, LOWORD(wParam));
870 hImageList = ResetApplicationList(FALSE, hWnd, hImageList);
874 case IDC_SUPPORT_INFO:
875 selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS,
876 LVM_GETNEXTITEM, -1, LVNI_FOCUSED | LVNI_SELECTED);
880 lvItem.iItem = selitem;
881 lvItem.mask = LVIF_PARAM;
883 if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW,
884 0, (LPARAM) &lvItem))
885 SupportInfo(hWnd, lvItem.lParam);
897 static int CALLBACK propsheet_callback( HWND hwnd, UINT msg, LPARAM lparam )
901 case PSCB_INITIALIZED:
902 SendMessageW( hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW( hInst, MAKEINTRESOURCEW(ICO_MAIN) ));
908 /******************************************************************************
910 * Description: Main routine for applet
911 * Parameters : hWnd - hWnd of the Control Panel
913 static void StartApplet(HWND hWnd)
916 PROPSHEETHEADERW psh;
917 WCHAR tab_title[MAX_STRING_LEN], app_title[MAX_STRING_LEN];
919 /* Load the strings we will use */
920 LoadStringW(hInst, IDS_TAB1_TITLE, tab_title, sizeof(tab_title) / sizeof(tab_title[0]));
921 LoadStringW(hInst, IDS_CPL_TITLE, app_title, sizeof(app_title) / sizeof(app_title[0]));
922 LoadStringW(hInst, IDS_REMOVE, btnRemove, sizeof(btnRemove) / sizeof(btnRemove[0]));
923 LoadStringW(hInst, IDS_MODIFY_REMOVE, btnModifyRemove, sizeof(btnModifyRemove) / sizeof(btnModifyRemove[0]));
925 /* Fill out the PROPSHEETPAGE */
926 psp.dwSize = sizeof (PROPSHEETPAGEW);
927 psp.dwFlags = PSP_USETITLE;
928 psp.hInstance = hInst;
929 psp.u.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN);
930 psp.u2.pszIcon = NULL;
931 psp.pfnDlgProc = (DLGPROC) MainDlgProc;
932 psp.pszTitle = tab_title;
935 /* Fill out the PROPSHEETHEADER */
936 psh.dwSize = sizeof (PROPSHEETHEADERW);
937 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
938 psh.hwndParent = hWnd;
939 psh.hInstance = hInst;
940 psh.u.pszIcon = MAKEINTRESOURCEW(ICO_MAIN);
941 psh.pszCaption = app_title;
944 psh.pfnCallback = propsheet_callback;
945 psh.u2.nStartPage = 0;
947 /* Display the property sheet */
948 PropertySheetW (&psh);
951 static LONG start_params(const WCHAR *params)
953 static const WCHAR install_geckoW[] = {'i','n','s','t','a','l','l','_','g','e','c','k','o',0};
958 if(!strcmpW(params, install_geckoW)) {
959 install_wine_gecko();
963 WARN("unknown param %s\n", debugstr_w(params));
967 /******************************************************************************
969 * Description: Entry point for Control Panel applets
970 * Parameters : hwndCPL - hWnd of the Control Panel
971 * message - reason for calling function
972 * lParam1 - additional parameter
973 * lParam2 - additional parameter
974 * Returns : Dependant on message
976 LONG CALLBACK CPlApplet(HWND hwndCPL, UINT message, LPARAM lParam1, LPARAM lParam2)
978 INITCOMMONCONTROLSEX iccEx;
983 iccEx.dwSize = sizeof(iccEx);
984 iccEx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES;
986 InitCommonControlsEx(&iccEx);
993 case CPL_STARTWPARMSW:
994 return start_params((const WCHAR *)lParam2);
998 CPLINFO *appletInfo = (CPLINFO *) lParam2;
1000 appletInfo->idIcon = ICO_MAIN;
1001 appletInfo->idName = IDS_CPL_TITLE;
1002 appletInfo->idInfo = IDS_CPL_DESC;
1003 appletInfo->lData = 0;
1009 StartApplet(hwndCPL);