2 * Q&D Uninstaller (main.c)
4 * Copyright 2000 Andreas Mohr <andi@lisas.de>
5 * To be distributed under the Wine License
17 /* Work around a Wine bug which defines handles as UINT rather than LPVOID */
19 #define NULL_HANDLE NULL
26 #define DEBUG(x) fprintf(stderr,x)
31 /* use multi-select listbox */
32 #undef USE_MULTIPLESEL
34 /* Delete uninstall registry key after execution.
35 * This is probably a bad idea, because it's the
36 * uninstall program that is supposed to do that.
42 static char about_string[] =
43 "Windows program uninstaller (C) 2000 by Andreas Mohr <andi@lisas.de>";
44 static char program_description[] =
45 "Welcome to the Wine uninstaller !\n\nThe purpose of this program is to let you get rid of all those fantastic programs that somehow manage to always take way too much space on your HDD :-)";
54 uninst_entry *entries = NULL;
64 { BS_PUSHBUTTON, "Add/Remove", 0 },
65 { BS_PUSHBUTTON, "About", 0 },
66 { BS_PUSHBUTTON, "Exit", 0 }
69 #define NUM (sizeof button/sizeof button[0])
71 int GetUninstallStrings(void);
72 void UninstallProgram(void);
74 void ListUninstallPrograms(void)
78 if (! GetUninstallStrings())
81 for (i=0; i < numentries; i++)
82 printf("%s|||%s\n", entries[i].key, entries[i].descr);
86 void RemoveSpecificProgram(char *name)
90 if (! GetUninstallStrings())
93 for (i=0; i < numentries; i++)
95 if (strcmp(entries[i].key, name) == 0)
106 fprintf(stderr, "Error: could not match program [%s]\n", name);
111 int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow )
117 /*------------------------------------------------------------------------
118 ** Handle requests just to list the programs
119 **----------------------------------------------------------------------*/
120 if (cmdline && strlen(cmdline) >= 6 && memcmp(cmdline, "--list", 6) == 0)
122 ListUninstallPrograms();
126 /*------------------------------------------------------------------------
127 ** Handle requests to remove one program
128 **----------------------------------------------------------------------*/
129 if (cmdline && strlen(cmdline) > 9 && memcmp(cmdline, "--remove ", 9) == 0)
131 RemoveSpecificProgram(cmdline + 9);
137 LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
140 wc.lpfnWndProc = MainProc;
143 wc.hInstance = hInst;
144 wc.hIcon = LoadIcon( hInst, appname );
145 wc.hCursor = LoadCursor( NULL_HANDLE, IDI_APPLICATION );
146 wc.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH );
147 wc.lpszMenuName = NULL;
148 wc.lpszClassName = appname;
150 if (!RegisterClass(&wc)) exit(1);
151 hWnd = CreateWindow( appname, appname,
152 WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
153 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
154 NULL_HANDLE, NULL_HANDLE, hInst, NULL );
158 ShowWindow( hWnd, cmdshow );
159 UpdateWindow( hWnd );
161 while( GetMessage(&msg, NULL_HANDLE, 0, 0) ) {
162 TranslateMessage( &msg );
163 DispatchMessage( &msg );
168 int GetUninstallStrings(void)
170 HKEY hkeyUninst, hkeyApp;
172 DWORD sizeOfSubKeyName=255, displen, uninstlen;
173 char subKeyName[256];
178 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
179 0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS )
181 MessageBox(0, "Uninstall registry key not available (yet), nothing to do !", appname, MB_OK);
185 strcpy(key_app, REGSTR_PATH_UNINSTALL);
186 strcat(key_app, "\\");
187 p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1;
189 RegEnumKeyExA( hkeyUninst, i, subKeyName, &sizeOfSubKeyName,
190 NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS;
191 ++i, sizeOfSubKeyName=255 )
193 strcpy(p, subKeyName);
194 RegOpenKeyEx(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);
196 if ( (RegQueryValueEx(hkeyApp, REGSTR_VAL_UNINSTALLER_DISPLAYNAME,
197 0, 0, NULL, &displen) == ERROR_SUCCESS)
198 && (RegQueryValueEx(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE,
199 0, 0, NULL, &uninstlen) == ERROR_SUCCESS) )
202 entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
203 entries[numentries-1].key =
204 HeapAlloc(GetProcessHeap(), 0, strlen(subKeyName)+1);
205 strcpy(entries[numentries-1].key, subKeyName);
206 entries[numentries-1].descr =
207 HeapAlloc(GetProcessHeap(), 0, displen);
208 RegQueryValueEx(hkeyApp, REGSTR_VAL_UNINSTALLER_DISPLAYNAME, 0, 0,
209 entries[numentries-1].descr, &displen);
210 entries[numentries-1].command =
211 HeapAlloc(GetProcessHeap(), 0, uninstlen);
212 entries[numentries-1].active = 0;
213 RegQueryValueEx(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE, 0, 0,
214 entries[numentries-1].command, &uninstlen);
216 RegCloseKey(hkeyApp);
218 RegCloseKey(hkeyUninst);
222 void UninstallProgram(void)
228 PROCESS_INFORMATION info;
234 for (i=0; i < numentries; i++)
236 if (!(entries[i].active)) /* don't uninstall this one */
238 memset(&si, 0, sizeof(STARTUPINFO));
239 si.cb = sizeof(STARTUPINFO);
240 si.wShowWindow = SW_NORMAL;
241 res = CreateProcess(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
243 { /* wait for the process to exit */
244 WaitForSingleObject(info.hProcess, INFINITE);
245 res = GetExitCodeProcess(info.hProcess, &exit_code);
246 fprintf(stderr, "%d: %08lx\n", res, exit_code);
248 /* delete the program's uninstall entry */
249 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
250 0, KEY_READ, &hkey) == ERROR_SUCCESS)
252 RegDeleteKey(hkey, entries[i].key);
259 sprintf(errormsg, "Execution of uninstall command '%s' failed, perhaps due to missing executable.", entries[i].command);
260 MessageBox(0, errormsg, appname, MB_OK);
265 LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
270 int cxChar, cyChar, i, y, bx, by, maxx, maxy, wx, wy;
271 static HWND hwndList = 0, hwndEdit = 0;
278 if (!(GetUninstallStrings()))
284 GetTextMetrics(hdc, &tm);
285 cxChar = tm.tmAveCharWidth;
286 cyChar = tm.tmHeight + tm.tmExternalLeading;
287 ReleaseDC(hWnd, hdc);
288 /* FIXME: implement sorting and use LBS_SORT here ! */
289 style = (WS_CHILD|WS_VISIBLE|LBS_STANDARD) & ~LBS_SORT;
290 #ifdef USE_MULTIPLESEL
291 style |= LBS_MULTIPLESEL;
293 bx = maxx = cxChar * 5;
294 by = maxy = cyChar * 3;
295 hwndList = CreateWindow("listbox", NULL,
298 cxChar * 50 + GetSystemMetrics(SM_CXVSCROLL), cyChar * 20,
300 (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
302 GetWindowRect(hwndList, &rect);
304 maxx += (rect.right - rect.left)*1.1;
305 maxy += (rect.bottom - rect.top)*1.1;
308 for (i=0; i < NUM; i++)
310 button[i].hwnd = CreateWindow("button", button[i].text,
311 WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
315 ((LPCREATESTRUCT)lParam)->hInstance, NULL);
320 CreateWindow("static", program_description,
321 WS_CHILD|WS_VISIBLE|SS_LEFT,
325 ((LPCREATESTRUCT)lParam)->hInstance, NULL);
326 maxx += wx + cxChar * 5; /* button + right border */
327 maxy += cyChar * 5 + cyChar * 2; /* static text + distance */
328 CreateWindow("static", "command line to be executed:",
329 WS_CHILD|WS_VISIBLE|SS_LEFT,
333 ((LPCREATESTRUCT)lParam)->hInstance, NULL);
335 hwndEdit = CreateWindow("edit", NULL,
336 WS_CHILD|WS_VISIBLE|WS_BORDER|ES_LEFT|ES_MULTILINE|ES_READONLY,
337 bx, maxy, maxx-(2*bx), (cyChar*6)+4,
339 ((LPCREATESTRUCT)lParam)->hInstance, NULL);
340 maxy += (cyChar*6)+4 + cyChar * 3; /* edit ctrl + bottom border */
341 SetWindowPos( hWnd, 0,
349 SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
350 SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
351 for (i=0; i < numentries; i++)
352 SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
353 SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
354 hdc = BeginPaint( hWnd, &ps );
355 EndPaint( hWnd, &ps );
360 PostQuitMessage( 0 );
364 if ((HWND)lParam == hwndList)
366 if (HIWORD(wParam) == LBN_SELCHANGE)
368 int sel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
370 entries[sel].active ^= 1; /* toggle */
371 SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)entries[sel].command);
375 if ((HWND)lParam == button[0].hwnd) /* Uninstall button */
381 GetUninstallStrings();
382 InvalidateRect(hWnd, NULL, TRUE);
387 if ((HWND)lParam == button[1].hwnd) /* About button */
388 MessageBox(0, about_string, "About", MB_OK);
390 if ((HWND)lParam == button[2].hwnd) /* Exit button */
395 return( DefWindowProc( hWnd, msg, wParam, lParam ));