comparison src/uninstall.c @ 18174:1ec6539cef68 v8.1.2082

patch 8.1.2082: some files have a weird name to fit in 8.3 characters Commit: https://github.com/vim/vim/commit/30e8e73506e4522ef4aebf7d525c0e6ffe8805fd Author: Bram Moolenaar <Bram@vim.org> Date: Fri Sep 27 13:08:36 2019 +0200 patch 8.1.2082: some files have a weird name to fit in 8.3 characters Problem: Some files have a weird name to fit in 8.3 characters. Solution: Use a nicer names.
author Bram Moolenaar <Bram@vim.org>
date Fri, 27 Sep 2019 13:15:03 +0200
parents src/uninstal.c@b9098585d945
children 15539899a112
comparison
equal deleted inserted replaced
18173:f046fb05b08f 18174:1ec6539cef68
1 /* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10 /*
11 * uninstall.c: Minimalistic uninstall program for Vim on MS-Windows
12 * Removes:
13 * - the "Edit with Vim" popup menu entry
14 * - the Vim "Open With..." popup menu entry
15 * - any Vim Batch files in the path
16 * - icons for Vim on the Desktop
17 * - the Vim entry in the Start Menu
18 */
19
20 /* Include common code for dosinst.c and uninstall.c. */
21 #include "dosinst.h"
22
23 /*
24 * Return TRUE if the user types a 'y' or 'Y', FALSE otherwise.
25 */
26 static int
27 confirm(void)
28 {
29 char answer[10];
30
31 fflush(stdout);
32 return (scanf(" %c", answer) == 1 && toupper(answer[0]) == 'Y');
33 }
34
35 static int
36 reg_delete_key(HKEY hRootKey, const char *key, DWORD flag)
37 {
38 static int did_load = FALSE;
39 static HANDLE advapi_lib = NULL;
40 static LONG (WINAPI *delete_key_ex)(HKEY, LPCTSTR, REGSAM, DWORD) = NULL;
41
42 if (!did_load)
43 {
44 /* The RegDeleteKeyEx() function is only available on new systems. It
45 * is required for 64-bit registry access. For other systems fall
46 * back to RegDeleteKey(). */
47 did_load = TRUE;
48 advapi_lib = LoadLibrary("ADVAPI32.DLL");
49 if (advapi_lib != NULL)
50 delete_key_ex = (LONG (WINAPI *)(HKEY, LPCTSTR, REGSAM, DWORD))GetProcAddress(advapi_lib, "RegDeleteKeyExA");
51 }
52 if (delete_key_ex != NULL) {
53 return (*delete_key_ex)(hRootKey, key, flag, 0);
54 }
55 return RegDeleteKey(hRootKey, key);
56 }
57
58 /*
59 * Check if the popup menu entry exists and what gvim it refers to.
60 * Returns non-zero when it's found.
61 */
62 static int
63 popup_gvim_path(char *buf, DWORD bufsize)
64 {
65 HKEY key_handle;
66 DWORD value_type;
67 int r;
68
69 /* Open the key where the path to gvim.exe is stored. */
70 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0,
71 KEY_WOW64_64KEY | KEY_READ, &key_handle) != ERROR_SUCCESS)
72 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0,
73 KEY_WOW64_32KEY | KEY_READ, &key_handle) != ERROR_SUCCESS)
74 return 0;
75
76 /* get the DisplayName out of it to show the user */
77 r = RegQueryValueEx(key_handle, "path", 0,
78 &value_type, (LPBYTE)buf, &bufsize);
79 RegCloseKey(key_handle);
80
81 return (r == ERROR_SUCCESS);
82 }
83
84 /*
85 * Check if the "Open With..." menu entry exists and what gvim it refers to.
86 * Returns non-zero when it's found.
87 */
88 static int
89 openwith_gvim_path(char *buf, DWORD bufsize)
90 {
91 HKEY key_handle;
92 DWORD value_type;
93 int r;
94
95 /* Open the key where the path to gvim.exe is stored. */
96 if (RegOpenKeyEx(HKEY_CLASSES_ROOT,
97 "Applications\\gvim.exe\\shell\\edit\\command", 0,
98 KEY_WOW64_64KEY | KEY_READ, &key_handle) != ERROR_SUCCESS)
99 return 0;
100
101 /* get the DisplayName out of it to show the user */
102 r = RegQueryValueEx(key_handle, "", 0, &value_type, (LPBYTE)buf, &bufsize);
103 RegCloseKey(key_handle);
104
105 return (r == ERROR_SUCCESS);
106 }
107
108 static void
109 remove_popup(void)
110 {
111 int fail = 0;
112 int i;
113 int loop = is_64bit_os() ? 2 : 1;
114 int maxfail = loop * 6;
115 DWORD flag;
116 HKEY kh;
117
118 for (i = 0; i < loop; i++)
119 {
120 if (i == 0)
121 flag = KEY_WOW64_32KEY;
122 else
123 flag = KEY_WOW64_64KEY;
124
125 if (reg_delete_key(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32", flag) != ERROR_SUCCESS)
126 ++fail;
127 if (reg_delete_key(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}", flag) != ERROR_SUCCESS)
128 ++fail;
129 if (reg_delete_key(HKEY_CLASSES_ROOT, "*\\shellex\\ContextMenuHandlers\\gvim", flag) != ERROR_SUCCESS)
130 ++fail;
131 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0,
132 flag | KEY_ALL_ACCESS, &kh) != ERROR_SUCCESS)
133 ++fail;
134 else
135 {
136 if (RegDeleteValue(kh, "{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS)
137 ++fail;
138 RegCloseKey(kh);
139 }
140 if (reg_delete_key(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", flag) != ERROR_SUCCESS)
141 ++fail;
142 if (reg_delete_key(HKEY_LOCAL_MACHINE, "Software\\Vim", flag) != ERROR_SUCCESS)
143 ++fail;
144 }
145
146 if (fail == maxfail)
147 printf("No Vim popup registry entries could be removed\n");
148 else if (fail > 0)
149 printf("Some Vim popup registry entries could not be removed\n");
150 else
151 printf("The Vim popup registry entries have been removed\n");
152 }
153
154 static void
155 remove_openwith(void)
156 {
157 int fail = 0;
158 int i;
159 int loop = is_64bit_os() ? 2 : 1;
160 int maxfail = loop * 7;
161 DWORD flag;
162
163 for (i = 0; i < loop; i++)
164 {
165 if (i == 0)
166 flag = KEY_WOW64_32KEY;
167 else
168 flag = KEY_WOW64_64KEY;
169
170 if (reg_delete_key(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit\\command", flag) != ERROR_SUCCESS)
171 ++fail;
172 if (reg_delete_key(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit", flag) != ERROR_SUCCESS)
173 ++fail;
174 if (reg_delete_key(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell", flag) != ERROR_SUCCESS)
175 ++fail;
176 if (reg_delete_key(HKEY_CLASSES_ROOT, "Applications\\gvim.exe", flag) != ERROR_SUCCESS)
177 ++fail;
178 if (reg_delete_key(HKEY_CLASSES_ROOT, ".htm\\OpenWithList\\gvim.exe", flag) != ERROR_SUCCESS)
179 ++fail;
180 if (reg_delete_key(HKEY_CLASSES_ROOT, ".vim\\OpenWithList\\gvim.exe", flag) != ERROR_SUCCESS)
181 ++fail;
182 if (reg_delete_key(HKEY_CLASSES_ROOT, "*\\OpenWithList\\gvim.exe", flag) != ERROR_SUCCESS)
183 ++fail;
184 }
185
186 if (fail == maxfail)
187 printf("No Vim open-with registry entries could be removed\n");
188 else if (fail > 0)
189 printf("Some Vim open-with registry entries could not be removed\n");
190 else
191 printf("The Vim open-with registry entries have been removed\n");
192 }
193
194 /*
195 * Check if a batch file is really for the current version. Don't delete a
196 * batch file that was written for another (possibly newer) version.
197 */
198 static int
199 batfile_thisversion(char *path)
200 {
201 FILE *fd;
202 char line[BUFSIZE];
203 char *p;
204 int ver_len = strlen(VIM_VERSION_NODOT);
205 int found = FALSE;
206
207 fd = fopen(path, "r");
208 if (fd != NULL)
209 {
210 while (fgets(line, sizeof(line), fd) != NULL)
211 {
212 for (p = line; *p != 0; ++p)
213 /* don't accept "vim60an" when looking for "vim60". */
214 if (strnicmp(p, VIM_VERSION_NODOT, ver_len) == 0
215 && !isdigit(p[ver_len])
216 && !isalpha(p[ver_len]))
217 {
218 found = TRUE;
219 break;
220 }
221 if (found)
222 break;
223 }
224 fclose(fd);
225 }
226 return found;
227 }
228
229 static int
230 remove_batfiles(int doit)
231 {
232 char *batfile_path;
233 int i;
234 int found = 0;
235
236 for (i = 1; i < TARGET_COUNT; ++i)
237 {
238 batfile_path = searchpath_save(targets[i].batname);
239 if (batfile_path != NULL && batfile_thisversion(batfile_path))
240 {
241 ++found;
242 if (doit)
243 {
244 printf("removing %s\n", batfile_path);
245 remove(batfile_path);
246 }
247 else
248 printf(" - the batch file %s\n", batfile_path);
249 free(batfile_path);
250 }
251 }
252 return found;
253 }
254
255 static void
256 remove_if_exists(char *path, char *filename)
257 {
258 char buf[BUFSIZE];
259 FILE *fd;
260
261 sprintf(buf, "%s\\%s", path, filename);
262
263 fd = fopen(buf, "r");
264 if (fd != NULL)
265 {
266 fclose(fd);
267 printf("removing %s\n", buf);
268 remove(buf);
269 }
270 }
271
272 static void
273 remove_icons(void)
274 {
275 char path[BUFSIZE];
276 int i;
277
278 if (get_shell_folder_path(path, "desktop"))
279 for (i = 0; i < ICON_COUNT; ++i)
280 remove_if_exists(path, icon_link_names[i]);
281 }
282
283 static void
284 remove_start_menu(void)
285 {
286 char path[BUFSIZE];
287 int i;
288 struct stat st;
289
290 if (get_shell_folder_path(path, VIM_STARTMENU))
291 {
292 for (i = 1; i < TARGET_COUNT; ++i)
293 remove_if_exists(path, targets[i].lnkname);
294 remove_if_exists(path, "uninstall.lnk");
295 remove_if_exists(path, "Help.lnk");
296 /* Win95 uses .pif, WinNT uses .lnk */
297 remove_if_exists(path, "Vim tutor.pif");
298 remove_if_exists(path, "Vim tutor.lnk");
299 remove_if_exists(path, "Vim online.url");
300 if (stat(path, &st) == 0)
301 {
302 printf("removing %s\n", path);
303 rmdir(path);
304 }
305 }
306 }
307
308 static void
309 delete_uninstall_key(void)
310 {
311 reg_delete_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT, KEY_WOW64_64KEY);
312 }
313
314 int
315 main(int argc, char *argv[])
316 {
317 int found = 0;
318 FILE *fd;
319 int i;
320 struct stat st;
321 char icon[BUFSIZE];
322 char path[MAX_PATH];
323 char popup_path[MAX_PATH];
324
325 /* The nsis uninstaller calls us with a "-nsis" argument. */
326 if (argc == 2 && stricmp(argv[1], "-nsis") == 0)
327 interactive = FALSE;
328 else
329 interactive = TRUE;
330
331 /* Initialize this program. */
332 do_inits(argv);
333
334 printf("This program will remove the following items:\n");
335
336 if (popup_gvim_path(popup_path, sizeof(popup_path)))
337 {
338 printf(" - the \"Edit with Vim\" entry in the popup menu\n");
339 printf(" which uses \"%s\"\n", popup_path);
340 if (interactive)
341 printf("\nRemove it (y/n)? ");
342 if (!interactive || confirm())
343 {
344 remove_popup();
345 /* Assume the "Open With" entry can be removed as well, don't
346 * bother the user with asking him again. */
347 remove_openwith();
348 }
349 }
350 else if (openwith_gvim_path(popup_path, sizeof(popup_path)))
351 {
352 printf(" - the Vim \"Open With...\" entry in the popup menu\n");
353 printf(" which uses \"%s\"\n", popup_path);
354 printf("\nRemove it (y/n)? ");
355 if (confirm())
356 remove_openwith();
357 }
358
359 if (get_shell_folder_path(path, "desktop"))
360 {
361 printf("\n");
362 for (i = 0; i < ICON_COUNT; ++i)
363 {
364 sprintf(icon, "%s\\%s", path, icon_link_names[i]);
365 if (stat(icon, &st) == 0)
366 {
367 printf(" - the \"%s\" icon on the desktop\n", icon_names[i]);
368 ++found;
369 }
370 }
371 if (found > 0)
372 {
373 if (interactive)
374 printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
375 if (!interactive || confirm())
376 remove_icons();
377 }
378 }
379
380 if (get_shell_folder_path(path, VIM_STARTMENU)
381 && stat(path, &st) == 0)
382 {
383 printf("\n - the \"%s\" entry in the Start Menu\n", VIM_STARTMENU);
384 if (interactive)
385 printf("\nRemove it (y/n)? ");
386 if (!interactive || confirm())
387 remove_start_menu();
388 }
389
390 printf("\n");
391 found = remove_batfiles(0);
392 if (found > 0)
393 {
394 if (interactive)
395 printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
396 if (!interactive || confirm())
397 remove_batfiles(1);
398 }
399
400 fd = fopen("gvim.exe", "r");
401 if (fd != NULL)
402 {
403 fclose(fd);
404 printf("gvim.exe detected. Attempting to unregister gvim with OLE\n");
405 system("gvim.exe -silent -unregister");
406 }
407
408 delete_uninstall_key();
409
410 if (interactive)
411 {
412 printf("\nYou may now want to delete the Vim executables and runtime files.\n");
413 printf("(They are still where you unpacked them.)\n");
414 }
415
416 if (interactive)
417 {
418 rewind(stdin);
419 printf("\nPress Enter to exit...");
420 (void)getchar();
421 }
422 else
423 sleep(3);
424
425 return 0;
426 }