Use a dialog instead of a normal window.
This commit is contained in:
parent
99615021fb
commit
9b4b9ce88f
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Uninstaller (English Resources)
|
||||
*
|
||||
* Copyright 2005 Jonathan Ernst
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
IDD_UNINSTALLER DIALOG DISCARDABLE 0, 0, 330, 160
|
||||
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Wine Application Uninstaller"
|
||||
FONT 10, "MS Sans Serif"
|
||||
BEGIN
|
||||
LTEXT "Please select the application you wish to uninstall:",IDC_PLEASESELECT,10,10,250,14
|
||||
LISTBOX IDC_LIST,10,43,250,106,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "&Uninstall",IDC_UNINSTALL,270,48,50,14
|
||||
PUSHBUTTON "&About",IDC_ABOUT,270,65,50,14
|
||||
PUSHBUTTON "&Exit",IDC_EXIT,270,81,50,14
|
||||
END
|
||||
|
||||
|
||||
STRINGTABLE DISCARDABLE {
|
||||
IDS_APPNAME, "Wine Application Unsinstaller"
|
||||
IDS_ABOUT, "Wine Application Uninstaller (C) 2005 by Andreas Mohr, Hannu Valtonen and Jonathan Ernst."
|
||||
IDS_ABOUTTITLE, "About Unsinstaller"
|
||||
IDS_REGISTRYKEYNOTAVAILABLE, "Uninstall registry key not available (yet), nothing to do !"
|
||||
IDS_UNINSTALLFAILED, "Execution of uninstall command '%s' failed, perhaps due to missing executable.\r\nDo you want to remove the uninstall entry from the registry ?"
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* Q&D Uninstaller (main.c)
|
||||
* Uninstaller
|
||||
*
|
||||
* Copyright 2000 Andreas Mohr <andi@lisas.de>
|
||||
* Copyright 2004 Hannu Valtonen <Hannu.Valtonen@hut.fi>
|
||||
* Copyright 2000 Andreas Mohr
|
||||
* Copyright 2004 Hannu Valtonen
|
||||
* Copyright 2005 Jonathan Ernst
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -22,100 +23,90 @@
|
|||
* - add search box for locating entries quickly
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
#include "main.h"
|
||||
#include "resource.h"
|
||||
#include "regstr.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(uninstaller);
|
||||
|
||||
/* Work around a Wine bug which defines handles as UINT rather than LPVOID */
|
||||
#ifdef WINE_STRICT
|
||||
#define NULL_HANDLE NULL
|
||||
#else
|
||||
#define NULL_HANDLE 0
|
||||
#endif
|
||||
|
||||
/* use multi-select listbox */
|
||||
#undef USE_MULTIPLESEL
|
||||
|
||||
/* Delete uninstall registry key after execution.
|
||||
* This is probably a bad idea, because it's the
|
||||
* uninstall program that is supposed to do that.
|
||||
*/
|
||||
#undef DEL_REG_KEY
|
||||
|
||||
char appname[18];
|
||||
|
||||
static char about_string[] =
|
||||
"Wine Application Uninstaller (C) 2004 by Andreas Mohr <andi@lisas.de> and Hannu Valtonen <Hannu.Valtonen@hut.fi>";
|
||||
static char program_description[] =
|
||||
"Please select the application you wish to uninstall:";
|
||||
|
||||
typedef struct {
|
||||
char *key;
|
||||
WCHAR *key;
|
||||
WCHAR *descr;
|
||||
char *command;
|
||||
WCHAR *command;
|
||||
int active;
|
||||
} uninst_entry;
|
||||
static uninst_entry *entries = NULL;
|
||||
static unsigned int numentries = 0;
|
||||
static int list_need_update = 1;
|
||||
static int oldsel = -1;
|
||||
static WCHAR sAppName[MAX_STRING_LEN];
|
||||
static WCHAR sAboutTitle[MAX_STRING_LEN];
|
||||
static WCHAR sAbout[MAX_STRING_LEN];
|
||||
static WCHAR sRegistryKeyNotAvailable[MAX_STRING_LEN];
|
||||
static WCHAR sUninstallFailed[MAX_STRING_LEN];
|
||||
|
||||
uninst_entry *entries = NULL;
|
||||
static int FetchUninstallInformation(void);
|
||||
static void UninstallProgram(void);
|
||||
static void UpdateList(HWND hList);
|
||||
static int cmp_by_name(const void *a, const void *b);
|
||||
static INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
unsigned int numentries = 0;
|
||||
int list_need_update = 1;
|
||||
int oldsel = -1;
|
||||
|
||||
struct {
|
||||
DWORD style;
|
||||
LPCSTR text;
|
||||
HWND hwnd;
|
||||
} button[] =
|
||||
{
|
||||
{ BS_PUSHBUTTON, "Add/Remove", 0 },
|
||||
{ BS_PUSHBUTTON, "About", 0 },
|
||||
{ BS_PUSHBUTTON, "Exit", 0 }
|
||||
};
|
||||
static const WCHAR BackSlashW[] = { '\\', 0 };
|
||||
static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
|
||||
static const WCHAR PathUninstallW[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\',
|
||||
'W','i','n','d','o','w','s','\\',
|
||||
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
||||
'U','n','i','n','s','t','a','l','l',0 };
|
||||
static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
|
||||
|
||||
#define NUM (sizeof(button)/sizeof(button[0]))
|
||||
|
||||
int FetchUninstallInformation(void);
|
||||
void UninstallProgram(void);
|
||||
|
||||
void ListUninstallPrograms(void)
|
||||
/**
|
||||
* Used to output program list when used with --list
|
||||
*/
|
||||
static void ListUninstallPrograms(void)
|
||||
{
|
||||
unsigned int i;
|
||||
int len;
|
||||
int lenDescr, lenKey;
|
||||
char *descr;
|
||||
char *key;
|
||||
|
||||
if (! FetchUninstallInformation())
|
||||
return;
|
||||
|
||||
for (i=0; i < numentries; i++)
|
||||
{
|
||||
len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL);
|
||||
descr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL);
|
||||
printf("%s|||%s\n", entries[i].key, descr);
|
||||
lenDescr = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL);
|
||||
lenKey = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].key, -1, NULL, 0, NULL, NULL);
|
||||
descr = HeapAlloc(GetProcessHeap(), 0, lenDescr);
|
||||
key = HeapAlloc(GetProcessHeap(), 0, lenKey);
|
||||
WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, lenDescr, NULL, NULL);
|
||||
WideCharToMultiByte(CP_UNIXCP, 0, entries[i].key, -1, key, lenKey, NULL, NULL);
|
||||
printf("%s|||%s\n", key, descr);
|
||||
HeapFree(GetProcessHeap(), 0, descr);
|
||||
HeapFree(GetProcessHeap(), 0, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RemoveSpecificProgram(char *name)
|
||||
static void RemoveSpecificProgram(WCHAR *nameW)
|
||||
{
|
||||
unsigned int i;
|
||||
int lenName;
|
||||
char *name;
|
||||
|
||||
if (! FetchUninstallInformation())
|
||||
return;
|
||||
|
||||
for (i=0; i < numentries; i++)
|
||||
{
|
||||
if (strcmp(entries[i].key, name) == 0)
|
||||
if (lstrcmpW(entries[i].key, nameW) == 0)
|
||||
{
|
||||
entries[i].active++;
|
||||
break;
|
||||
|
@ -126,30 +117,34 @@ void RemoveSpecificProgram(char *name)
|
|||
UninstallProgram();
|
||||
else
|
||||
{
|
||||
lenName = WideCharToMultiByte(CP_UNIXCP, 0, nameW, -1, NULL, 0, NULL, NULL);
|
||||
name = HeapAlloc(GetProcessHeap(), 0, lenName);
|
||||
WideCharToMultiByte(CP_UNIXCP, 0, nameW, -1, name, lenName, NULL, NULL);
|
||||
fprintf(stderr, "Error: could not match application [%s]\n", name);
|
||||
HeapFree(GetProcessHeap(), 0, name);
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[])
|
||||
|
||||
int wmain(int argc, WCHAR *argv[])
|
||||
{
|
||||
MSG msg;
|
||||
WNDCLASS wc;
|
||||
HWND hWnd;
|
||||
LPSTR token = NULL;
|
||||
LPCWSTR token = NULL;
|
||||
HINSTANCE hInst = GetModuleHandleW(0);
|
||||
static const WCHAR listW[] = { '-','-','l','i','s','t',0 };
|
||||
static const WCHAR removeW[] = { '-','-','r','e','m','o','v','e',0 };
|
||||
int i = 1;
|
||||
HINSTANCE hInst = NULL;
|
||||
|
||||
while( i<argc )
|
||||
{
|
||||
token = argv[i++];
|
||||
|
||||
|
||||
/* Handle requests just to list the applications */
|
||||
if( !lstrcmpA( token, "--list" ) )
|
||||
if( !lstrcmpW( token, listW ) )
|
||||
{
|
||||
ListUninstallPrograms();
|
||||
return 0;
|
||||
}
|
||||
else if( !lstrcmpA( token, "--remove" ) )
|
||||
else if( !lstrcmpW( token, removeW ) )
|
||||
{
|
||||
if( i >= argc )
|
||||
{
|
||||
|
@ -162,303 +157,208 @@ int main( int argc, char *argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
WINE_ERR( "unknown option %s\n",token);
|
||||
WINE_ERR( "unknown option %s\n",wine_dbgstr_w(token));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
|
||||
/* Load MessageBox's strings */
|
||||
LoadStringW(hInst, IDS_APPNAME, sAppName, sizeof(sAppName)/sizeof(WCHAR));
|
||||
LoadStringW(hInst, IDS_ABOUTTITLE, sAboutTitle, sizeof(sAboutTitle)/sizeof(WCHAR));
|
||||
LoadStringW(hInst, IDS_ABOUT, sAbout, sizeof(sAbout)/sizeof(WCHAR));
|
||||
LoadStringW(hInst, IDS_REGISTRYKEYNOTAVAILABLE, sRegistryKeyNotAvailable, sizeof(sRegistryKeyNotAvailable)/sizeof(WCHAR));
|
||||
LoadStringW(hInst, IDS_UNINSTALLFAILED, sUninstallFailed, sizeof(sUninstallFailed)/sizeof(WCHAR));
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = MainProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInst;
|
||||
wc.hIcon = LoadIcon( hInst, appname );
|
||||
wc.hCursor = LoadCursor( NULL_HANDLE, IDI_APPLICATION );
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = appname;
|
||||
|
||||
if (!RegisterClass(&wc)) exit(1);
|
||||
hWnd = CreateWindow( appname, "Wine Application Uninstaller",
|
||||
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
NULL_HANDLE, NULL_HANDLE, hInst, NULL );
|
||||
|
||||
if (!hWnd) exit(1);
|
||||
|
||||
ShowWindow( hWnd, SW_SHOW );
|
||||
UpdateWindow( hWnd );
|
||||
|
||||
while( GetMessage(&msg, NULL_HANDLE, 0, 0) ) {
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
return msg.wParam;
|
||||
return DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_UNINSTALLER), NULL, DlgProc);
|
||||
}
|
||||
|
||||
int cmp_by_name(const void *a, const void *b)
|
||||
|
||||
/**
|
||||
* Used to sort entries by name.
|
||||
*/
|
||||
static int cmp_by_name(const void *a, const void *b)
|
||||
{
|
||||
return lstrcmpiW(((const uninst_entry *)a)->descr, ((const uninst_entry *)b)->descr);
|
||||
}
|
||||
|
||||
int FetchUninstallInformation(void)
|
||||
|
||||
/**
|
||||
* Fetch informations from the uninstall key.
|
||||
*/
|
||||
static int FetchUninstallInformation(void)
|
||||
{
|
||||
HKEY hkeyUninst, hkeyApp;
|
||||
int i;
|
||||
DWORD sizeOfSubKeyName, displen, uninstlen;
|
||||
char subKeyName[256];
|
||||
char key_app[1024];
|
||||
char *p;
|
||||
|
||||
WCHAR subKeyName[256];
|
||||
WCHAR key_app[1024];
|
||||
WCHAR *p;
|
||||
|
||||
numentries = 0;
|
||||
oldsel = -1;
|
||||
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
|
||||
0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS )
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninstallW, 0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS)
|
||||
{
|
||||
MessageBox(0, "Uninstall registry key not available (yet), nothing to do !", appname, MB_OK);
|
||||
return 0;
|
||||
MessageBoxW(0, sRegistryKeyNotAvailable, sAppName, MB_OK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!entries)
|
||||
entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry));
|
||||
entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry));
|
||||
|
||||
strcpy(key_app, REGSTR_PATH_UNINSTALL);
|
||||
strcat(key_app, "\\");
|
||||
p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1;
|
||||
lstrcpyW(key_app, PathUninstallW);
|
||||
lstrcatW(key_app, BackSlashW);
|
||||
p = key_app+lstrlenW(PathUninstallW)+1;
|
||||
|
||||
sizeOfSubKeyName = 255;
|
||||
for ( i=0;
|
||||
RegEnumKeyExA( hkeyUninst, i, subKeyName, &sizeOfSubKeyName,
|
||||
NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS;
|
||||
++i )
|
||||
for (i=0; RegEnumKeyExW( hkeyUninst, i, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS; ++i)
|
||||
{
|
||||
static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
|
||||
|
||||
strcpy(p, subKeyName);
|
||||
RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);
|
||||
|
||||
if ( (RegQueryValueExW(hkeyApp, DisplayNameW,
|
||||
0, 0, NULL, &displen) == ERROR_SUCCESS)
|
||||
&& (RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE,
|
||||
0, 0, NULL, &uninstlen) == ERROR_SUCCESS) )
|
||||
{
|
||||
numentries++;
|
||||
entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
|
||||
entries[numentries-1].key =
|
||||
HeapAlloc(GetProcessHeap(), 0, strlen(subKeyName)+1);
|
||||
strcpy(entries[numentries-1].key, subKeyName);
|
||||
entries[numentries-1].descr =
|
||||
HeapAlloc(GetProcessHeap(), 0, displen);
|
||||
RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0,
|
||||
(LPBYTE)entries[numentries-1].descr, &displen);
|
||||
entries[numentries-1].command =
|
||||
HeapAlloc(GetProcessHeap(), 0, uninstlen);
|
||||
entries[numentries-1].active = 0;
|
||||
RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE, 0, 0,
|
||||
entries[numentries-1].command, &uninstlen);
|
||||
WINE_TRACE("allocated entry #%d: %s (%s), %s\n",
|
||||
numentries, entries[numentries-1].key,
|
||||
wine_dbgstr_w(entries[numentries-1].descr),
|
||||
entries[numentries-1].command);
|
||||
}
|
||||
RegCloseKey(hkeyApp);
|
||||
|
||||
sizeOfSubKeyName = 255;
|
||||
lstrcpyW(p, subKeyName);
|
||||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);
|
||||
if ((RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen) == ERROR_SUCCESS)
|
||||
&& (RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, NULL, &uninstlen) == ERROR_SUCCESS))
|
||||
{
|
||||
numentries++;
|
||||
entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
|
||||
entries[numentries-1].key = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(subKeyName)+1)*sizeof(WCHAR));
|
||||
lstrcpyW(entries[numentries-1].key, subKeyName);
|
||||
entries[numentries-1].descr = HeapAlloc(GetProcessHeap(), 0, displen);
|
||||
RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)entries[numentries-1].descr, &displen);
|
||||
entries[numentries-1].command = HeapAlloc(GetProcessHeap(), 0, uninstlen);
|
||||
entries[numentries-1].active = 0;
|
||||
RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, (LPBYTE)entries[numentries-1].command, &uninstlen);
|
||||
WINE_TRACE("allocated entry #%d: %s (%s), %s\n",
|
||||
numentries, wine_dbgstr_w(entries[numentries-1].key), wine_dbgstr_w(entries[numentries-1].descr), wine_dbgstr_w(entries[numentries-1].command));
|
||||
}
|
||||
RegCloseKey(hkeyApp);
|
||||
sizeOfSubKeyName = 255;
|
||||
}
|
||||
qsort(entries, numentries, sizeof(uninst_entry), cmp_by_name);
|
||||
RegCloseKey(hkeyUninst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UninstallProgram(void)
|
||||
|
||||
static void UninstallProgram(void)
|
||||
{
|
||||
unsigned int i;
|
||||
char errormsg[1024];
|
||||
WCHAR errormsg[1024];
|
||||
BOOL res;
|
||||
STARTUPINFO si;
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION info;
|
||||
DWORD exit_code;
|
||||
#ifdef DEL_REG_KEY
|
||||
HKEY hkey;
|
||||
#endif
|
||||
|
||||
for (i=0; i < numentries; i++)
|
||||
{
|
||||
if (!(entries[i].active)) /* don't uninstall this one */
|
||||
continue;
|
||||
WINE_TRACE("uninstalling %s\n", wine_dbgstr_w(entries[i].descr));
|
||||
memset(&si, 0, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.wShowWindow = SW_NORMAL;
|
||||
res = CreateProcess(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
|
||||
if (res)
|
||||
{ /* wait for the process to exit */
|
||||
WaitForSingleObject(info.hProcess, INFINITE);
|
||||
res = GetExitCodeProcess(info.hProcess, &exit_code);
|
||||
WINE_TRACE("%d: %08lx\n", res, exit_code);
|
||||
#ifdef DEL_REG_KEY
|
||||
/* delete the application's uninstall entry */
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
|
||||
0, KEY_READ, &hkey) == ERROR_SUCCESS)
|
||||
{
|
||||
RegDeleteKey(hkey, entries[i].key);
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errormsg, "Execution of uninstall command '%s' failed, perhaps due to missing executable.", entries[i].command);
|
||||
MessageBox(0, errormsg, appname, MB_OK);
|
||||
}
|
||||
if (!(entries[i].active)) /* don't uninstall this one */
|
||||
continue;
|
||||
WINE_TRACE("uninstalling %s\n", wine_dbgstr_w(entries[i].descr));
|
||||
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||
si.cb = sizeof(STARTUPINFOW);
|
||||
si.wShowWindow = SW_NORMAL;
|
||||
res = CreateProcessW(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
|
||||
if (res)
|
||||
{ /* wait for the process to exit */
|
||||
WaitForSingleObject(info.hProcess, INFINITE);
|
||||
res = GetExitCodeProcess(info.hProcess, &exit_code);
|
||||
WINE_TRACE("%d: %08lx\n", res, exit_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintfW(errormsg, sUninstallFailed, entries[i].command);
|
||||
if(MessageBoxW(0, errormsg, sAppName, MB_YESNO | MB_ICONQUESTION)==IDYES)
|
||||
{
|
||||
/* delete the application's uninstall entry */
|
||||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninstallW, 0, KEY_READ, &hkey);
|
||||
RegDeleteKeyW(hkey, entries[i].key);
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
WINE_TRACE("finished uninstall phase.\n");
|
||||
list_need_update = 1;
|
||||
}
|
||||
|
||||
LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
static INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HFONT static_font, listbox_font;
|
||||
TEXTMETRICW tm;
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
TEXTMETRIC tm;
|
||||
unsigned int i;
|
||||
int cxChar, cyChar, y, bx, maxx, maxy, wx, wy;
|
||||
static HWND hwndList = 0, static_text = 0;
|
||||
DWORD style;
|
||||
RECT rect;
|
||||
|
||||
switch( msg ) {
|
||||
case WM_CREATE:
|
||||
{
|
||||
hdc = GetDC(hWnd);
|
||||
GetTextMetrics(hdc, &tm);
|
||||
static_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 600, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
|
||||
listbox_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
|
||||
cxChar = tm.tmAveCharWidth;
|
||||
cyChar = tm.tmHeight + tm.tmExternalLeading;
|
||||
ReleaseDC(hWnd, hdc);
|
||||
/* FIXME: implement sorting and use LBS_SORT here ! */
|
||||
style = (WS_CHILD|WS_VISIBLE|LBS_STANDARD) & ~LBS_SORT;
|
||||
#ifdef USE_MULTIPLESEL
|
||||
style |= LBS_MULTIPLESEL;
|
||||
#endif
|
||||
bx = maxx = cxChar * 3;
|
||||
y = maxy = cyChar * 1;
|
||||
static_text = CreateWindow("static", program_description,
|
||||
WS_CHILD|WS_VISIBLE|SS_LEFT,
|
||||
maxx, maxy,
|
||||
cxChar * sizeof(program_description), cyChar * 1,
|
||||
hWnd, (HMENU)1,
|
||||
((LPCREATESTRUCT)lParam)->hInstance, NULL);
|
||||
SendMessage(static_text, WM_SETFONT, (WPARAM)static_font, MAKELPARAM(FALSE, 0));
|
||||
maxy += cyChar * 2; /*static text + distance */
|
||||
hwndList = CreateWindow("listbox", NULL,
|
||||
style,
|
||||
maxx, maxy,
|
||||
cxChar * 50 + GetSystemMetrics(SM_CXVSCROLL), cyChar * 10,
|
||||
hWnd, (HMENU) 1,
|
||||
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
|
||||
SendMessage(hwndList, WM_SETFONT, (WPARAM)listbox_font, MAKELPARAM(FALSE, 0));
|
||||
GetWindowRect(hwndList, &rect);
|
||||
maxx += (rect.right - rect.left)*1.1;
|
||||
maxy += (rect.bottom - rect.top)*1.1;
|
||||
wx = 20*cxChar;
|
||||
wy = 7*cyChar/4;
|
||||
y = cyChar * 3;
|
||||
for (i=0; i < NUM; i++)
|
||||
{
|
||||
button[i].hwnd = CreateWindow("button", button[i].text,
|
||||
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
|
||||
maxx, y,
|
||||
wx, wy,
|
||||
hWnd, (HMENU)i,
|
||||
((LPCREATESTRUCT)lParam)->hInstance, NULL);
|
||||
if (!button[i].hwnd)
|
||||
PostQuitMessage(0);
|
||||
y += 2*cyChar;
|
||||
}
|
||||
maxx += wx + cxChar * 4;
|
||||
maxy += cyChar * 2; /* window border */
|
||||
SetWindowPos( hWnd, 0,
|
||||
0, 0, maxx, maxy,
|
||||
SWP_NOMOVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
if (list_need_update)
|
||||
{
|
||||
int prevsel;
|
||||
prevsel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
|
||||
if (!(FetchUninstallInformation()))
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
|
||||
SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
|
||||
for (i=0; i < numentries; i++)
|
||||
{
|
||||
WINE_TRACE("adding %s\n", wine_dbgstr_w(entries[i].descr));
|
||||
SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
|
||||
}
|
||||
WINE_TRACE("setting prevsel %d\n", prevsel);
|
||||
if (prevsel != -1)
|
||||
SendMessage(hwndList, LB_SETCURSEL, prevsel, 0 );
|
||||
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
|
||||
list_need_update = 0;
|
||||
}
|
||||
EndPaint( hWnd, &ps );
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage( 0 );
|
||||
return 0;
|
||||
|
||||
case WM_COMMAND:
|
||||
if ((HWND)lParam == hwndList)
|
||||
{
|
||||
if (HIWORD(wParam) == LBN_SELCHANGE)
|
||||
{
|
||||
int sel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
|
||||
|
||||
#ifndef USE_MULTIPLESEL
|
||||
if (oldsel != -1)
|
||||
{
|
||||
entries[oldsel].active ^= 1; /* toggle */
|
||||
WINE_TRACE("toggling %d old %s\n", entries[oldsel].active,
|
||||
wine_dbgstr_w(entries[oldsel].descr));
|
||||
}
|
||||
#endif
|
||||
entries[sel].active ^= 1; /* toggle */
|
||||
WINE_TRACE("toggling %d %s\n", entries[sel].active,
|
||||
wine_dbgstr_w(entries[oldsel].descr));
|
||||
oldsel = sel;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((HWND)lParam == button[0].hwnd) /* Uninstall button */
|
||||
{
|
||||
UninstallProgram();
|
||||
|
||||
InvalidateRect(hWnd, NULL, TRUE);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
}
|
||||
else
|
||||
if ((HWND)lParam == button[1].hwnd) /* About button */
|
||||
MessageBox(0, about_string, "About Wine Application Uninstaller", MB_OK);
|
||||
else
|
||||
if ((HWND)lParam == button[2].hwnd) /* Exit button */
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
HWND hList = GetDlgItem(hwnd, IDC_LIST);
|
||||
switch(Message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
hdc = GetDC(hwnd);
|
||||
GetTextMetricsW(hdc, &tm);
|
||||
UpdateList(hList);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_UNINSTALL:
|
||||
{
|
||||
int count = SendMessageW(hList, LB_GETSELCOUNT, 0, 0);
|
||||
if(count != 0)
|
||||
{
|
||||
UninstallProgram();
|
||||
UpdateList(hList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDC_LIST:
|
||||
if (HIWORD(wParam) == LBN_SELCHANGE)
|
||||
{
|
||||
int sel = SendMessageW(hList, LB_GETCURSEL, 0, 0);
|
||||
if (oldsel != -1)
|
||||
{
|
||||
entries[oldsel].active ^= 1; /* toggle */
|
||||
WINE_TRACE("toggling %d old %s\n", entries[oldsel].active,
|
||||
wine_dbgstr_w(entries[oldsel].descr));
|
||||
}
|
||||
entries[sel].active ^= 1; /* toggle */
|
||||
WINE_TRACE("toggling %d %s\n", entries[sel].active,
|
||||
wine_dbgstr_w(entries[oldsel].descr));
|
||||
oldsel = sel;
|
||||
}
|
||||
break;
|
||||
case IDC_ABOUT:
|
||||
MessageBoxW(0, sAbout, sAboutTitle, MB_OK);
|
||||
break;
|
||||
case IDC_EXIT:
|
||||
EndDialog(hwnd, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void UpdateList(HWND hList)
|
||||
{
|
||||
unsigned int i;
|
||||
if (list_need_update)
|
||||
{
|
||||
int prevsel;
|
||||
prevsel = SendMessageW(hList, LB_GETCURSEL, 0, 0);
|
||||
if (!(FetchUninstallInformation()))
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
return;
|
||||
}
|
||||
SendMessageW(hList, LB_RESETCONTENT, 0, 0);
|
||||
SendMessageW(hList, WM_SETREDRAW, FALSE, 0);
|
||||
for (i=0; i < numentries; i++)
|
||||
{
|
||||
WINE_TRACE("adding %s\n", wine_dbgstr_w(entries[i].descr));
|
||||
SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
|
||||
}
|
||||
WINE_TRACE("setting prevsel %d\n", prevsel);
|
||||
if (prevsel != -1)
|
||||
SendMessageW(hList, LB_SETCURSEL, prevsel, 0 );
|
||||
SendMessageW(hList, WM_SETREDRAW, TRUE, 0);
|
||||
list_need_update = 0;
|
||||
}
|
||||
|
||||
return( DefWindowProc( hWnd, msg, wParam, lParam ));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright 2000 Andreas Mohr <andi@lisas.de>
|
||||
* Uninstaller resource definitions
|
||||
*
|
||||
* Copyright 2005 Jonathan Ernst
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -16,8 +18,16 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define IDS_APPNAME 1101
|
||||
|
||||
LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#define IDD_UNINSTALLER 101
|
||||
#define IDC_FILTER 1001
|
||||
#define IDC_LIST 1002
|
||||
#define IDC_UNINSTALL 1003
|
||||
#define IDC_ABOUT 1004
|
||||
#define IDC_EXIT 1005
|
||||
#define IDC_PLEASESELECT 1006
|
||||
#define IDS_APPNAME 1007
|
||||
#define IDS_ABOUT 1008
|
||||
#define IDS_ABOUTTITLE 1009
|
||||
#define IDS_REGISTRYKEYNOTAVAILABLE 1010
|
||||
#define IDS_UNINSTALLFAILED 1011
|
||||
#define MAX_STRING_LEN 255
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright 2003 Vincent Béron
|
||||
* Copyright 2003 Ivan Leo Puoti
|
||||
* Copyright 2004 David Kredba
|
||||
* Copyright 2005 Jonathan Ernst
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -22,7 +23,8 @@
|
|||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "main.h"
|
||||
#include "resource.h"
|
||||
#include "En.rc"
|
||||
|
||||
/* BINRES uninstaller.ico */
|
||||
UNINSTALLER ICON MOVEABLE uninstaller.ico
|
||||
|
@ -76,66 +78,3 @@ UNINSTALLER ICON MOVEABLE uninstaller.ico
|
|||
'00 03 C0 00 00 03 C0 00 00 0F C0 00 00 07 C0 00'
|
||||
'00 03 80 00 00 31 1F FF FF F8 3F FF FF FC'
|
||||
} */
|
||||
|
||||
/* Czech Resources */
|
||||
LANGUAGE LANG_CZECH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Deinstalátor"
|
||||
|
||||
}
|
||||
/* End of Czech Resources */
|
||||
|
||||
/* English-US Resources */
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Uninstaller"
|
||||
|
||||
}
|
||||
/* End of English-US Resources */
|
||||
|
||||
/* French Resources */
|
||||
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Désinstalleur"
|
||||
|
||||
}
|
||||
/* End of French Resources */
|
||||
|
||||
/* German Resources */
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Uninstaller"
|
||||
|
||||
}
|
||||
/* End of German Resources */
|
||||
|
||||
/* Italian Resources */
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Disinstallatore"
|
||||
|
||||
}
|
||||
/* End of Italian Resources */
|
||||
|
||||
/* Portuguese Resources */
|
||||
LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Desinstalador"
|
||||
|
||||
}
|
||||
/* End of Portuguese Resources */
|
||||
|
||||
/* Spanish Resources */
|
||||
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
|
||||
|
||||
STRINGTABLE {
|
||||
IDS_APPNAME, "Desinstalador"
|
||||
|
||||
}
|
||||
/* End of Spanish Resources */
|
||||
|
|
Loading…
Reference in New Issue