summaryrefslogtreecommitdiff
path: root/src/uninstal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uninstal.c')
-rw-r--r--src/uninstal.c438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/uninstal.c b/src/uninstal.c
new file mode 100644
index 000000000..23c246b30
--- /dev/null
+++ b/src/uninstal.c
@@ -0,0 +1,438 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * uninstal.c: Minimalistic uninstall program for Vim on MS-Windows
+ * Removes:
+ * - the "Edit with Vim" popup menu entry
+ * - the Vim "Open With..." popup menu entry
+ * - any Vim Batch files in the path
+ * - icons for Vim on the Desktop
+ * - the Vim entry in the Start Menu
+ */
+
+/* Include common code for dosinst.c and uninstal.c. */
+#include "dosinst.h"
+
+/*
+ * Return TRUE if the user types a 'y' or 'Y', FALSE otherwise.
+ */
+ static int
+confirm(void)
+{
+ char answer[10];
+
+ fflush(stdout);
+ return (scanf(" %c", answer) == 1 && toupper(answer[0]) == 'Y');
+}
+
+#ifdef WIN3264
+/*
+ * Check if the popup menu entry exists and what gvim it refers to.
+ * Returns non-zero when it's found.
+ */
+ static int
+popup_gvim_path(char *buf)
+{
+ HKEY key_handle;
+ DWORD value_type;
+ DWORD bufsize = BUFSIZE;
+ int r;
+
+ /* Open the key where the path to gvim.exe is stored. */
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, KEY_READ,
+ &key_handle) != ERROR_SUCCESS)
+ return 0;
+
+ /* get the DisplayName out of it to show the user */
+ r = RegQueryValueEx(key_handle, "path", 0,
+ &value_type, (LPBYTE)buf, &bufsize);
+ RegCloseKey(key_handle);
+
+ return (r == ERROR_SUCCESS);
+}
+
+/*
+ * Check if the "Open With..." menu entry exists and what gvim it refers to.
+ * Returns non-zero when it's found.
+ */
+ static int
+openwith_gvim_path(char *buf)
+{
+ HKEY key_handle;
+ DWORD value_type;
+ DWORD bufsize = BUFSIZE;
+ int r;
+
+ /* Open the key where the path to gvim.exe is stored. */
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ "Applications\\gvim.exe\\shell\\edit\\command", 0, KEY_READ,
+ &key_handle) != ERROR_SUCCESS)
+ return 0;
+
+ /* get the DisplayName out of it to show the user */
+ r = RegQueryValueEx(key_handle, "", 0, &value_type, (LPBYTE)buf, &bufsize);
+ RegCloseKey(key_handle);
+
+ return (r == ERROR_SUCCESS);
+}
+
+ static void
+remove_popup(void)
+{
+ int fail = 0;
+ HKEY kh;
+
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shellex\\ContextMenuHandlers\\gvim") != ERROR_SUCCESS)
+ ++fail;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_ALL_ACCESS, &kh) != ERROR_SUCCESS)
+ ++fail;
+ else
+ {
+ if (RegDeleteValue(kh, "{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS)
+ ++fail;
+ RegCloseKey(kh);
+ }
+ if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim") != ERROR_SUCCESS)
+ ++fail;
+
+ if (fail == 6)
+ printf("No Vim popup registry entries could be removed\n");
+ else if (fail > 0)
+ printf("Some Vim popup registry entries could not be removed\n");
+ else
+ printf("The Vim popup registry entries have been removed\n");
+}
+
+ static void
+remove_openwith(void)
+{
+ int fail = 0;
+
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit\\command") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell\\edit") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe\\shell") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "Applications\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, ".htm\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, ".vim\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+ if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\OpenWithList\\gvim.exe") != ERROR_SUCCESS)
+ ++fail;
+
+ if (fail == 7)
+ printf("No Vim open-with registry entries could be removed\n");
+ else if (fail > 0)
+ printf("Some Vim open-with registry entries could not be removed\n");
+ else
+ printf("The Vim open-with registry entries have been removed\n");
+}
+#endif
+
+/*
+ * Check if a batch file is really for the current version. Don't delete a
+ * batch file that was written for another (possibly newer) version.
+ */
+ static int
+batfile_thisversion(char *path)
+{
+ FILE *fd;
+ char line[BUFSIZE];
+ char *p;
+ int ver_len = strlen(VIM_VERSION_NODOT);
+ int found = FALSE;
+
+ fd = fopen(path, "r");
+ if (fd != NULL)
+ {
+ while (fgets(line, BUFSIZE, fd) != NULL)
+ {
+ for (p = line; *p != 0; ++p)
+ /* don't accept "vim60an" when looking for "vim60". */
+ if (strnicmp(p, VIM_VERSION_NODOT, ver_len) == 0
+ && !isdigit(p[ver_len])
+ && !isalpha(p[ver_len]))
+ {
+ found = TRUE;
+ break;
+ }
+ if (found)
+ break;
+ }
+ fclose(fd);
+ }
+ return found;
+}
+
+ static int
+remove_batfiles(int doit)
+{
+ char *batfile_path;
+ int i;
+ int found = 0;
+
+ for (i = 1; i < TARGET_COUNT; ++i)
+ {
+ batfile_path = searchpath_save(targets[i].batname);
+ if (batfile_path != NULL && batfile_thisversion(batfile_path))
+ {
+ ++found;
+ if (doit)
+ {
+ printf("removing %s\n", batfile_path);
+ remove(batfile_path);
+ }
+ else
+ printf(" - the batch file %s\n", batfile_path);
+ free(batfile_path);
+ }
+ }
+ return found;
+}
+
+#ifdef WIN3264
+ static void
+remove_if_exists(char *path, char *filename)
+{
+ char buf[BUFSIZE];
+ FILE *fd;
+
+ sprintf(buf, "%s\\%s", path, filename);
+
+ fd = fopen(buf, "r");
+ if (fd != NULL)
+ {
+ fclose(fd);
+ printf("removing %s\n", buf);
+ remove(buf);
+ }
+}
+
+ static void
+remove_icons(void)
+{
+ char path[BUFSIZE];
+ int i;
+
+ if (get_shell_folder_path(path, "desktop"))
+ for (i = 0; i < ICON_COUNT; ++i)
+ remove_if_exists(path, icon_link_names[i]);
+}
+
+ static void
+remove_start_menu(void)
+{
+ char path[BUFSIZE];
+ int i;
+ struct stat st;
+
+ if (get_shell_folder_path(path, VIM_STARTMENU))
+ {
+ for (i = 1; i < TARGET_COUNT; ++i)
+ remove_if_exists(path, targets[i].lnkname);
+ remove_if_exists(path, "uninstall.lnk");
+ remove_if_exists(path, "Help.lnk");
+ /* Win95 uses .pif, WinNT uses .lnk */
+ remove_if_exists(path, "Vim tutor.pif");
+ remove_if_exists(path, "Vim tutor.lnk");
+ remove_if_exists(path, "Vim online.url");
+ if (stat(path, &st) == 0)
+ {
+ printf("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+#endif
+
+#if 0 /* currently not used */
+/*
+ * Return TRUE when we're on Windows 95/98/ME.
+ */
+ static int
+win95(void)
+{
+ static int done = FALSE;
+ static DWORD PlatformId;
+
+ if (!done)
+ {
+ OSVERSIONINFO ovi;
+
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+ GetVersionEx(&ovi);
+ PlatformId = ovi.dwPlatformId;
+ done = TRUE;
+ }
+ /* Win NT/2000/XP is VER_PLATFORM_WIN32_NT */
+ return PlatformId == VER_PLATFORM_WIN32_WINDOWS;
+}
+#endif
+
+ static void
+delete_uninstall_key(void)
+{
+#ifdef WIN3264
+ RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT);
+#else
+ FILE *fd;
+ char buf[BUFSIZE];
+
+ /*
+ * On DJGPP we delete registry entries by creating a .inf file and
+ * installing it.
+ */
+ fd = fopen("vim.inf", "w");
+ if (fd != NULL)
+ {
+ fprintf(fd, "[version]\n");
+ fprintf(fd, "signature=\"$CHICAGO$\"\n\n");
+ fprintf(fd, "[DefaultInstall]\n");
+ fprintf(fd, "DelReg=DeleteMe\n\n");
+ fprintf(fd, "[DeleteMe]\n");
+ fprintf(fd, "HKLM,\"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT "\"\n");
+ fclose(fd);
+
+ /* Don't know how to detect Win NT with DJGPP. Hack: Just try the Win
+ * 95/98/ME method, since the DJGPP version can't use long filenames
+ * on Win NT anyway. */
+ sprintf(buf, "rundll setupx.dll,InstallHinfSection DefaultInstall 132 %s\\vim.inf", installdir);
+ run_command(buf);
+#if 0
+ /* Windows NT method (untested). */
+ sprintf(buf, "rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128 %s\\vim.inf", installdir);
+ run_command(buf);
+#endif
+
+ remove("vim.inf");
+ }
+#endif
+}
+
+ int
+main(int argc, char *argv[])
+{
+ int found = 0;
+ FILE *fd;
+#ifdef WIN3264
+ int i;
+ struct stat st;
+ char icon[BUFSIZE];
+ char path[BUFSIZE];
+ char popup_path[BUFSIZE];
+
+ /* The nsis uninstaller calls us with a "-nsis" argument. */
+ if (argc == 2 && stricmp(argv[1], "-nsis") == 0)
+ interactive = FALSE;
+ else
+#endif
+ interactive = TRUE;
+
+ /* Initialize this program. */
+ do_inits(argv);
+
+ printf("This program will remove the following items:\n");
+
+#ifdef WIN3264
+ if (popup_gvim_path(popup_path))
+ {
+ printf(" - the \"Edit with Vim\" entry in the popup menu\n");
+ printf(" which uses \"%s\"\n", popup_path);
+ printf("\nRemove it (y/n)? ");
+ if (confirm())
+ {
+ remove_popup();
+ /* Assume the "Open With" entry can be removed as well, don't
+ * bother the user with asking him again. */
+ remove_openwith();
+ }
+ }
+ else if (openwith_gvim_path(popup_path))
+ {
+ printf(" - the Vim \"Open With...\" entry in the popup menu\n");
+ printf(" which uses \"%s\"\n", popup_path);
+ printf("\nRemove it (y/n)? ");
+ if (confirm())
+ remove_openwith();
+ }
+
+ if (get_shell_folder_path(path, "desktop"))
+ {
+ printf("\n");
+ for (i = 0; i < ICON_COUNT; ++i)
+ {
+ sprintf(icon, "%s\\%s", path, icon_link_names[i]);
+ if (stat(icon, &st) == 0)
+ {
+ printf(" - the \"%s\" icon on the desktop\n", icon_names[i]);
+ ++found;
+ }
+ }
+ if (found > 0)
+ {
+ if (interactive)
+ printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
+ if (!interactive || confirm())
+ remove_icons();
+ }
+ }
+
+ if (get_shell_folder_path(path, VIM_STARTMENU)
+ && stat(path, &st) == 0)
+ {
+ printf("\n - the \"%s\" entry in the Start Menu\n", VIM_STARTMENU);
+ if (interactive)
+ printf("\nRemove it (y/n)? ");
+ if (!interactive || confirm())
+ remove_start_menu();
+ }
+#endif
+
+ printf("\n");
+ found = remove_batfiles(0);
+ if (found > 0)
+ {
+ if (interactive)
+ printf("\nRemove %s (y/n)? ", found > 1 ? "them" : "it");
+ if (!interactive || confirm())
+ remove_batfiles(1);
+ }
+
+ fd = fopen("gvim.exe", "r");
+ if (fd != NULL)
+ {
+ fclose(fd);
+ printf("gvim.exe detected. Attempting to unregister gvim with OLE\n");
+ system("gvim.exe -silent -unregister");
+ }
+
+ delete_uninstall_key();
+
+ if (interactive)
+ {
+ printf("\nYou may now want to delete the Vim executables and runtime files.\n");
+ printf("(They are still where you unpacked them.)\n");
+ }
+
+ rewind(stdin);
+ printf("\nPress Enter to exit...");
+ (void)getchar();
+
+ return 0;
+}