Mercurial > vim
annotate src/uninstal.c @ 2449:943280505f72 vim73
Fix that uninstaller isn't found on 64-bit Windows.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Sat, 31 Jul 2010 22:03:44 +0200 |
parents | 573da4dac306 |
children | b204ac54bea4 |
rev | line source |
---|---|
7 | 1 /* vi:set ts=8 sts=4 sw=4: |
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 * uninstal.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 uninstal.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 #ifdef WIN3264 | |
36 /* | |
37 * Check if the popup menu entry exists and what gvim it refers to. | |
38 * Returns non-zero when it's found. | |
39 */ | |
40 static int | |
41 popup_gvim_path(char *buf) | |
42 { | |
43 HKEY key_handle; | |
44 DWORD value_type; | |
45 DWORD bufsize = BUFSIZE; | |
46 int r; | |
47 | |
48 /* Open the key where the path to gvim.exe is stored. */ | |
2449
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
49 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
50 KEY_WOW64_64KEY | KEY_READ, &key_handle) != ERROR_SUCCESS) |
7 | 51 return 0; |
52 | |
53 /* get the DisplayName out of it to show the user */ | |
54 r = RegQueryValueEx(key_handle, "path", 0, | |
55 &value_type, (LPBYTE)buf, &bufsize); | |
56 RegCloseKey(key_handle); | |
57 | |
58 return (r == ERROR_SUCCESS); | |
59 } | |
60 | |
61 /* | |
62 * Check if the "Open With..." menu entry exists and what gvim it refers to. | |
63 * Returns non-zero when it's found. | |
64 */ | |
65 static int | |
66 openwith_gvim_path(char *buf) | |
67 { | |
68 HKEY key_handle; | |
69 DWORD value_type; | |
70 DWORD bufsize = BUFSIZE; | |
71 int r; | |
72 | |
73 /* Open the key where the path to gvim.exe is stored. */ | |
74 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, | |
2449
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
75 "Applications\\gvim.exe\\shell\\edit\\command", 0, |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
76 KEY_WOW64_64KEY | KEY_READ, &key_handle) != ERROR_SUCCESS) |
7 | 77 return 0; |
78 | |
79 /* get the DisplayName out of it to show the user */ | |
80 r = RegQueryValueEx(key_handle, "", 0, &value_type, (LPBYTE)buf, &bufsize); | |
81 RegCloseKey(key_handle); | |
82 | |
83 return (r == ERROR_SUCCESS); | |
84 } | |
85 | |
86 static void | |
87 remove_popup(void) | |
88 { | |
89 int fail = 0; | |
90 HKEY kh; | |
91 | |
92 if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32") != ERROR_SUCCESS) | |
93 ++fail; | |
94 if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS) | |
95 ++fail; | |
96 if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shellex\\ContextMenuHandlers\\gvim") != ERROR_SUCCESS) | |
97 ++fail; | |
2449
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
98 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
99 KEY_WOW64_64KEY | KEY_ALL_ACCESS, &kh) != ERROR_SUCCESS) |
7 | 100 ++fail; |
101 else | |
102 { | |
103 if (RegDeleteValue(kh, "{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS) | |
104 ++fail; | |
105 RegCloseKey(kh); | |
106 } | |
107 if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim") != ERROR_SUCCESS) | |
108 ++fail; | |
109 if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim") != ERROR_SUCCESS) | |
110 ++fail; | |
111 | |
112 if (fail == 6) | |
113 printf("No Vim popup registry entries could be removed\n"); | |
114 else if (fail > 0) | |
115 printf("Some Vim popup registry entries could not be removed\n"); | |
116 else | |
117 printf("The Vim popup registry entries have been removed\n"); | |
118 } | |
119 | |
120 static void | |
121 remove_openwith(void) | |
122 { | |
123 int fail = 0; | |
124 | |
125 if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit\\command") != ERROR_SUCCESS) | |
126 ++fail; | |
127 if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit") != ERROR_SUCCESS) | |
128 ++fail; | |
129 if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell") != ERROR_SUCCESS) | |
130 ++fail; | |
131 if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe") != ERROR_SUCCESS) | |
132 ++fail; | |
133 if (RegDeleteKey(HKEY_CLASSES_ROOT, ".htm\\OpenWithList\\gvim.exe") != ERROR_SUCCESS) | |
134 ++fail; | |
135 if (RegDeleteKey(HKEY_CLASSES_ROOT, ".vim\\OpenWithList\\gvim.exe") != ERROR_SUCCESS) | |
136 ++fail; | |
137 if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\OpenWithList\\gvim.exe") != ERROR_SUCCESS) | |
138 ++fail; | |
139 | |
140 if (fail == 7) | |
141 printf("No Vim open-with registry entries could be removed\n"); | |
142 else if (fail > 0) | |
143 printf("Some Vim open-with registry entries could not be removed\n"); | |
144 else | |
145 printf("The Vim open-with registry entries have been removed\n"); | |
146 } | |
147 #endif | |
148 | |
149 /* | |
150 * Check if a batch file is really for the current version. Don't delete a | |
151 * batch file that was written for another (possibly newer) version. | |
152 */ | |
153 static int | |
154 batfile_thisversion(char *path) | |
155 { | |
156 FILE *fd; | |
157 char line[BUFSIZE]; | |
158 char *p; | |
159 int ver_len = strlen(VIM_VERSION_NODOT); | |
160 int found = FALSE; | |
161 | |
162 fd = fopen(path, "r"); | |
163 if (fd != NULL) | |
164 { | |
165 while (fgets(line, BUFSIZE, fd) != NULL) | |
166 { | |
167 for (p = line; *p != 0; ++p) | |
168 /* don't accept "vim60an" when looking for "vim60". */ | |
169 if (strnicmp(p, VIM_VERSION_NODOT, ver_len) == 0 | |
170 && !isdigit(p[ver_len]) | |
171 && !isalpha(p[ver_len])) | |
172 { | |
173 found = TRUE; | |
174 break; | |
175 } | |
176 if (found) | |
177 break; | |
178 } | |
179 fclose(fd); | |
180 } | |
181 return found; | |
182 } | |
183 | |
184 static int | |
185 remove_batfiles(int doit) | |
186 { | |
187 char *batfile_path; | |
188 int i; | |
189 int found = 0; | |
190 | |
191 for (i = 1; i < TARGET_COUNT; ++i) | |
192 { | |
193 batfile_path = searchpath_save(targets[i].batname); | |
194 if (batfile_path != NULL && batfile_thisversion(batfile_path)) | |
195 { | |
196 ++found; | |
197 if (doit) | |
198 { | |
199 printf("removing %s\n", batfile_path); | |
200 remove(batfile_path); | |
201 } | |
202 else | |
203 printf(" - the batch file %s\n", batfile_path); | |
204 free(batfile_path); | |
205 } | |
206 } | |
207 return found; | |
208 } | |
209 | |
210 #ifdef WIN3264 | |
211 static void | |
212 remove_if_exists(char *path, char *filename) | |
213 { | |
214 char buf[BUFSIZE]; | |
215 FILE *fd; | |
216 | |
217 sprintf(buf, "%s\\%s", path, filename); | |
218 | |
219 fd = fopen(buf, "r"); | |
220 if (fd != NULL) | |
221 { | |
222 fclose(fd); | |
223 printf("removing %s\n", buf); | |
224 remove(buf); | |
225 } | |
226 } | |
227 | |
228 static void | |
229 remove_icons(void) | |
230 { | |
231 char path[BUFSIZE]; | |
232 int i; | |
233 | |
234 if (get_shell_folder_path(path, "desktop")) | |
235 for (i = 0; i < ICON_COUNT; ++i) | |
236 remove_if_exists(path, icon_link_names[i]); | |
237 } | |
238 | |
239 static void | |
240 remove_start_menu(void) | |
241 { | |
242 char path[BUFSIZE]; | |
243 int i; | |
244 struct stat st; | |
245 | |
246 if (get_shell_folder_path(path, VIM_STARTMENU)) | |
247 { | |
248 for (i = 1; i < TARGET_COUNT; ++i) | |
249 remove_if_exists(path, targets[i].lnkname); | |
250 remove_if_exists(path, "uninstall.lnk"); | |
251 remove_if_exists(path, "Help.lnk"); | |
252 /* Win95 uses .pif, WinNT uses .lnk */ | |
253 remove_if_exists(path, "Vim tutor.pif"); | |
254 remove_if_exists(path, "Vim tutor.lnk"); | |
255 remove_if_exists(path, "Vim online.url"); | |
256 if (stat(path, &st) == 0) | |
257 { | |
258 printf("removing %s\n", path); | |
259 rmdir(path); | |
260 } | |
261 } | |
262 } | |
263 #endif | |
264 | |
265 #if 0 /* currently not used */ | |
266 /* | |
267 * Return TRUE when we're on Windows 95/98/ME. | |
268 */ | |
269 static int | |
270 win95(void) | |
271 { | |
272 static int done = FALSE; | |
273 static DWORD PlatformId; | |
274 | |
275 if (!done) | |
276 { | |
277 OSVERSIONINFO ovi; | |
278 | |
279 ovi.dwOSVersionInfoSize = sizeof(ovi); | |
280 GetVersionEx(&ovi); | |
281 PlatformId = ovi.dwPlatformId; | |
282 done = TRUE; | |
283 } | |
284 /* Win NT/2000/XP is VER_PLATFORM_WIN32_NT */ | |
285 return PlatformId == VER_PLATFORM_WIN32_WINDOWS; | |
286 } | |
287 #endif | |
288 | |
289 static void | |
290 delete_uninstall_key(void) | |
291 { | |
292 #ifdef WIN3264 | |
293 RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT); | |
294 #else | |
295 FILE *fd; | |
296 char buf[BUFSIZE]; | |
297 | |
298 /* | |
299 * On DJGPP we delete registry entries by creating a .inf file and | |
300 * installing it. | |
301 */ | |
302 fd = fopen("vim.inf", "w"); | |
303 if (fd != NULL) | |
304 { | |
305 fprintf(fd, "[version]\n"); | |
306 fprintf(fd, "signature=\"$CHICAGO$\"\n\n"); | |
307 fprintf(fd, "[DefaultInstall]\n"); | |
308 fprintf(fd, "DelReg=DeleteMe\n\n"); | |
309 fprintf(fd, "[DeleteMe]\n"); | |
310 fprintf(fd, "HKLM,\"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "\"\n"); | |
311 fclose(fd); | |
312 | |
313 /* Don't know how to detect Win NT with DJGPP. Hack: Just try the Win | |
314 * 95/98/ME method, since the DJGPP version can't use long filenames | |
315 * on Win NT anyway. */ | |
316 sprintf(buf, "rundll setupx.dll,InstallHinfSection DefaultInstall 132 %s\\vim.inf", installdir); | |
317 run_command(buf); | |
318 #if 0 | |
319 /* Windows NT method (untested). */ | |
320 sprintf(buf, "rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 %s\\vim.inf", installdir); | |
321 run_command(buf); | |
322 #endif | |
323 | |
324 remove("vim.inf"); | |
325 } | |
326 #endif | |
327 } | |
328 | |
329 int | |
330 main(int argc, char *argv[]) | |
331 { | |
332 int found = 0; | |
333 FILE *fd; | |
334 #ifdef WIN3264 | |
335 int i; | |
336 struct stat st; | |
337 char icon[BUFSIZE]; | |
338 char path[BUFSIZE]; | |
339 char popup_path[BUFSIZE]; | |
340 | |
341 /* The nsis uninstaller calls us with a "-nsis" argument. */ | |
342 if (argc == 2 && stricmp(argv[1], "-nsis") == 0) | |
343 interactive = FALSE; | |
344 else | |
345 #endif | |
346 interactive = TRUE; | |
347 | |
348 /* Initialize this program. */ | |
349 do_inits(argv); | |
350 | |
351 printf("This program will remove the following items:\n"); | |
352 | |
353 #ifdef WIN3264 | |
354 if (popup_gvim_path(popup_path)) | |
355 { | |
356 printf(" - the \"Edit with Vim\" entry in the popup menu\n"); | |
357 printf(" which uses \"%s\"\n", popup_path); | |
2217
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
358 if (interactive) |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
359 printf("\nRemove it (y/n)? "); |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
360 if (!interactive || confirm()) |
7 | 361 { |
362 remove_popup(); | |
363 /* Assume the "Open With" entry can be removed as well, don't | |
364 * bother the user with asking him again. */ | |
365 remove_openwith(); | |
366 } | |
367 } | |
368 else if (openwith_gvim_path(popup_path)) | |
369 { | |
370 printf(" - the Vim \"Open With...\" entry in the popup menu\n"); | |
371 printf(" which uses \"%s\"\n", popup_path); | |
372 printf("\nRemove it (y/n)? "); | |
373 if (confirm()) | |
374 remove_openwith(); | |
375 } | |
376 | |
377 if (get_shell_folder_path(path, "desktop")) | |
378 { | |
379 printf("\n"); | |
380 for (i = 0; i < ICON_COUNT; ++i) | |
381 { | |
382 sprintf(icon, "%s\\%s", path, icon_link_names[i]); | |
383 if (stat(icon, &st) == 0) | |
384 { | |
385 printf(" - the \"%s\" icon on the desktop\n", icon_names[i]); | |
386 ++found; | |
387 } | |
388 } | |
389 if (found > 0) | |
390 { | |
391 if (interactive) | |
392 printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it"); | |
393 if (!interactive || confirm()) | |
394 remove_icons(); | |
395 } | |
396 } | |
397 | |
398 if (get_shell_folder_path(path, VIM_STARTMENU) | |
399 && stat(path, &st) == 0) | |
400 { | |
401 printf("\n - the \"%s\" entry in the Start Menu\n", VIM_STARTMENU); | |
402 if (interactive) | |
403 printf("\nRemove it (y/n)? "); | |
404 if (!interactive || confirm()) | |
405 remove_start_menu(); | |
406 } | |
407 #endif | |
408 | |
409 printf("\n"); | |
410 found = remove_batfiles(0); | |
411 if (found > 0) | |
412 { | |
413 if (interactive) | |
414 printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it"); | |
415 if (!interactive || confirm()) | |
416 remove_batfiles(1); | |
417 } | |
418 | |
419 fd = fopen("gvim.exe", "r"); | |
420 if (fd != NULL) | |
421 { | |
422 fclose(fd); | |
423 printf("gvim.exe detected. Attempting to unregister gvim with OLE\n"); | |
424 system("gvim.exe -silent -unregister"); | |
425 } | |
426 | |
427 delete_uninstall_key(); | |
428 | |
429 if (interactive) | |
430 { | |
431 printf("\nYou may now want to delete the Vim executables and runtime files.\n"); | |
432 printf("(They are still where you unpacked them.)\n"); | |
433 } | |
434 | |
2217
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
435 if (interactive) |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
436 { |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
437 rewind(stdin); |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
438 printf("\nPress Enter to exit..."); |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
439 (void)getchar(); |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
440 } |
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
7
diff
changeset
|
441 else |
2287
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
442 sleep(3); |
7 | 443 |
444 return 0; | |
445 } |