diff --git a/dlls/appwiz.cpl/En.rc b/dlls/appwiz.cpl/En.rc index 1abc78808f5..fde9fa16b93 100644 --- a/dlls/appwiz.cpl/En.rc +++ b/dlls/appwiz.cpl/En.rc @@ -27,6 +27,8 @@ STRINGTABLE IDS_CPL_DESC, "Allows you to install new software, or remove existing software from your computer." IDS_TAB1_TITLE, "Applications" + IDS_UNINSTALL_FAILED, "Unable to execute the uninstaller, '%s'. Do you want to remove the uninstall entry for this program from the registry?" + IDS_COLUMN_NAME, "Name" IDS_COLUMN_PUBLISHER, "Publisher" IDS_COLUMN_VERSION, "Version" diff --git a/dlls/appwiz.cpl/appwiz.c b/dlls/appwiz.cpl/appwiz.c index 445e5ba0d92..fa4d573603b 100644 --- a/dlls/appwiz.cpl/appwiz.c +++ b/dlls/appwiz.cpl/appwiz.c @@ -371,6 +371,61 @@ static void UpdateButtons(HWND hWnd) EnableWindow(GetDlgItem(hWnd, IDC_SUPPORT_INFO), sel); } +/****************************************************************************** + * Name : UninstallProgram + * Description: Executes the specified program's installer. + * Parameters : id - the internal ID of the installer to remove + */ +static void UninstallProgram(int id) +{ + APPINFO *iter; + STARTUPINFOW si; + PROCESS_INFORMATION info; + WCHAR errormsg[MAX_STRING_LEN]; + WCHAR sUninstallFailed[MAX_STRING_LEN]; + HKEY hkey; + BOOL res; + + LoadStringW(hInst, IDS_UNINSTALL_FAILED, sUninstallFailed, + sizeof(sUninstallFailed) / sizeof(sUninstallFailed[0])); + + for (iter = AppInfo; iter; iter = iter->next) + { + if (iter->id == id) + { + TRACE("Uninstalling %s (%s)\n", wine_dbgstr_w(iter->title), + wine_dbgstr_w(iter->path)); + + memset(&si, 0, sizeof(STARTUPINFOW)); + si.cb = sizeof(STARTUPINFOW); + si.wShowWindow = SW_NORMAL; + res = CreateProcessW(NULL, iter->path, NULL, NULL, FALSE, 0, NULL, + NULL, &si, &info); + + if (res) + { + /* wait for the process to exit */ + WaitForSingleObject(info.hProcess, INFINITE); + } + else + { + wsprintfW(errormsg, sUninstallFailed, iter->path); + + if (MessageBoxW(0, errormsg, iter->title, MB_YESNO | + MB_ICONQUESTION) == IDYES) + { + /* delete the application's uninstall entry */ + RegOpenKeyExW(iter->regroot, PathUninstallW, 0, KEY_READ, &hkey); + RegDeleteKeyW(hkey, iter->regkey); + RegCloseKey(hkey); + } + } + + break; + } + } +} + /* Definition of column headers for AddListViewColumns function */ typedef struct AppWizColumn { int width; @@ -494,8 +549,10 @@ static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hIm */ static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + int selitem; static HIMAGELIST hImageList; LPNMHDR nmh; + LVITEMW lvItem; switch(msg) { @@ -530,6 +587,30 @@ static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar break; } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_ADDREMOVE: + selitem = SendDlgItemMessageW(hWnd, IDL_PROGRAMS, + LVM_GETNEXTITEM, -1, LVNI_FOCUSED|LVNI_SELECTED); + + if (selitem != -1) + { + lvItem.iItem = selitem; + lvItem.mask = LVIF_PARAM; + + if (SendDlgItemMessageW(hWnd, IDL_PROGRAMS, LVM_GETITEMW, + 0, (LPARAM) &lvItem)) + UninstallProgram(lvItem.lParam); + } + + hImageList = ResetApplicationList(FALSE, hWnd, hImageList); + + break; + } + return TRUE; } diff --git a/dlls/appwiz.cpl/res.h b/dlls/appwiz.cpl/res.h index 64b4a5bce5e..2aff5caf251 100644 --- a/dlls/appwiz.cpl/res.h +++ b/dlls/appwiz.cpl/res.h @@ -38,6 +38,7 @@ #define IDS_CPL_TITLE 1 #define IDS_CPL_DESC 2 #define IDS_TAB1_TITLE 3 +#define IDS_UNINSTALL_FAILED 4 #define IDS_COLUMN_NAME 6 #define IDS_COLUMN_PUBLISHER 7 #define IDS_COLUMN_VERSION 8