view uninst/uninst.c @ 0:879c2819a48d

Initial commit.
author Brian Smith <brian@dbsoft.org>
date Fri, 18 Feb 2011 08:45:38 -0600
parents
children 821abb186ec1
line wrap: on
line source

/* $Id: uninst.c,v 1.24 2003/05/10 09:18:10 bsmith Exp $ */

/*
 *  uninst.c (c) 2002-2003 Brian Smith
 */

#ifdef __UNIX__
#include "config.h"
#endif

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#ifndef __UNIX__
#include <process.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include "dw.h"
#include "compat.h"

#include <string.h>
#ifndef __UNIX__
#define strcasecmp stricmp
#endif

#ifdef __OS2__
#include <direct.h>
#include <ctype.h>
#endif

/* I know I am being excessive but... better safe than sorry ;) */
char *configsys[8196];
int configfilecount=-1;

/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter
                 It is just a place holder. (For the next 3 entries)             */
char csfile[] = "C:\\CONFIG.SYS";
/* Backup Config.Sys filename */
char bufile[] = "C:\\CONFIG.NST";
/* Installation Log Database -- Used for uninstallation and aborting */
#ifdef __WIN32__
char instlog[MAX_PATH+1] = "C:\\DBINST.LOG";
#elif defined(__OS2__)
char instlog[] = "C:\\OS2\\INSTALL\\DBINST.LOG";
#else
char instlog[] = "/var/log/dbinst";
#endif
char installdir[_MAX_PATH];

char bootdrive[2] = "C";
char empty_string[] = "";
char currentcf[_MAX_PATH] = "";

char *INSTALLER_APPLICATION, *INSTALLER_VERSION;
HWND mainwindow, mainbox, slider, stext, bigbox, logo, custombox, groupbox, buttonbox, status, exitbutton, nextbutton, blanktext;

#ifdef __OS2__
#define UNINSTALL_SCRIPT "uninstal.cmd"
#elif defined(__WIN32__)
#define UNINSTALL_SCRIPT "uninstal.bat"
#else
#define UNINSTALL_SCRIPT "Uninstall.sh"
#endif

/* Undocumented functions */
#if defined(__OS2__) || defined(__EMX__)
APIRET APIENTRY DosReplaceModule(PSZ pszOldModule,PSZ pszNewModule,PSZ pszBackupModule);
#endif
/*
 * Removes a folder on the desktop.
 */
void RemoveFolder(char Title[], char *Icon, char *dest, char *id, char *setup, char *platform)
{
#ifdef __OS2__
	if(id)
	{
		HOBJECT ho = WinQueryObject(id);

		if(ho != NULLHANDLE)
			WinDestroyObject(ho);
	}
#elif defined(__WIN32__)
	if(platform && *platform)
	{
		int res;

		res = rmdir(platform);
		if(res == -1)
			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
	}
#else
	/* Unix? */
#endif
}

/*
 * Makes a Program object on the desktop.
 */
void RemoveProgram(char *Title, char *Program, char *Icon, char *dest, char *id, char *setup, char *platform)
{
#ifdef __OS2__
	if(id)
	{
		HOBJECT ho = WinQueryObject(id);

		if(ho != NULLHANDLE)
			WinDestroyObject(ho);
	}
#elif defined(__WIN32__)
	if(platform && *platform)
	{
		int res;

		res = remove(platform);
		if(res == -1)
			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
	}
#else
	/* Unix? */
#endif
}
/*
 * Makes a user defined object on the desktop.
 */
void RemoveObject(char *Title, char *oclass, char *dest, char *id, char *setup, char *platform)
{
#ifdef __OS2__
	if(id)
	{
		HOBJECT ho = WinQueryObject(id);

		if(ho != NULLHANDLE)
			WinDestroyObject(ho);
	}
#elif defined(WIN32)
    /* Not sure if there is an equivilent on Windows */
#else
	/* Unix? */
#endif
}

/*
 * Makes a shadow on the desktop.
 */
void RemoveShadow(char *Title, char *reference, char *dest, char *id, char *platform)
{
#ifdef __OS2__
	if(id)
	{
		HOBJECT ho = WinQueryObject(id);

		if(ho != NULLHANDLE)
			WinDestroyObject(ho);
	}
#elif defined(WIN32)
	if(platform && *platform)
	{
		int res;

		res = remove(platform);
		if(res == -1)
			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
	}
#else
	/* Unix? */
#endif
}

void update_percent(int current, int total)
{
	static int pixels = 0;
	ULONG sliderpos = 0;

	if(total && (pixels = dw_percent_query_range(slider)))
	{
		sliderpos = (int)(((float)current/(float)total)*pixels);
		dw_percent_set_pos(slider, sliderpos);
	}
}

/*
 * Read the generated log file and anything installed.
 */
void do_uninstall(void)
{
	char tmpbuf[8196], *fileptr, **lines;
	FILE *tmplf;
	int linenum=0, found=-1, theend = 0, count = 0, z;

	if((tmplf=fopen(instlog, "rb"))==NULL)
	{
		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Could not open install log.");
		return;
	}

	while(!feof(tmplf))
	{
		fgets(tmpbuf, 8196, tmplf);
		linenum++;
		if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
		{
			fgets(tmpbuf, 8196, tmplf);
			linenum++;
			if((char *)strstr(tmpbuf, "<Version>") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL)
			{
				found=linenum;
				theend = 0;
			}
		}
		if(found != -1 && !theend && ((char *)strstr(tmpbuf, "<End>") != NULL || tmpbuf[0] == '['))
			theend=linenum;
	}
	if(found != -1)
	{
		if(!theend)
			theend = linenum;

		if(theend - found > 0)
			lines = calloc(theend - found, sizeof(char *));
		else
			lines = calloc(8096, sizeof(char *));

		rewind(tmplf);
		for (z=0;z<found;z++)
			fgets(tmpbuf, 8196, tmplf);
		while(!feof(tmplf) && count < (theend - found))
		{
			tmpbuf[0] = 0;
			fgets(tmpbuf, 8196, tmplf);
			lines[count] = strdup(tmpbuf);
			count++;

		}
		fclose(tmplf);

		/* The first NewDir should be the installation directory */
		for(z=0;z<count;z++)
		{
			if(lines[z])
			{
				int res;

				fileptr = lines[z];

				/* Remove trailing CRLFs */
				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
					fileptr[strlen(fileptr)-1]=0;
				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
					fileptr[strlen(fileptr)-1]=0;

				if((char *)strstr(lines[z], "<NewDir>") != NULL)
				{
					char path[_MAX_PATH];
					struct stat sb;

					fileptr = (char *)strchr(lines[z], ',')+1;
#ifndef __UNIX__
					if(fileptr[1] == ':')
					{
						char drive = toupper(fileptr[0]);
						_chdrive((drive - 'A')+1);
					}
#endif
					chdir(fileptr);

#ifdef __UNIX__
					sprintf(path, "%s/%s", fileptr, UNINSTALL_SCRIPT);
#else
					sprintf(path, "%s\\%s", fileptr, UNINSTALL_SCRIPT);
#endif
					if(!stat(path, &sb))
						system(path);

					z = count;
				}
			}
		}

		for(z=count-1;z>-1;z--)
		{
			if(lines[z])
			{
				int res;

				fileptr = lines[z];

				/* Remove trailing CRLFs */
				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
					fileptr[strlen(fileptr)-1]=0;
				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
					fileptr[strlen(fileptr)-1]=0;

				if((char *)strstr(lines[z], "<FileInst>") != NULL)
				{
					fileptr = (char *)strchr(lines[z], ',')+1;
#ifdef __OS2__
					DosReplaceModule(fileptr,NULL,NULL);
#endif
					res = remove(fileptr);
#ifdef __WIN32__
					if(res == -1)
						MoveFileEx(fileptr, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
				}
				if((char *)strstr(lines[z], "<NewDir>") != NULL)
				{
					fileptr = (char *)strchr(lines[z], ',')+1;
					res = rmdir(fileptr);
#ifdef __WIN32__
					if(res == -1)
						MoveFileEx(fileptr, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
				}
				if((char *)strstr(lines[z], "<WPSFolderAdd>") != NULL)
				{
					char *args[6], *ptr = lines[z];
					int x;

					for(x=0;x<6;x++)
					{
						if(ptr)
							ptr = strstr(ptr, ",");
						if(ptr)
						{
							ptr[0] = 0;
							ptr = args[x] = &ptr[1];
						}
						else
							args[x] = NULL;
					}
					RemoveFolder(args[0],args[1],args[2],args[3],args[4],args[5]);
				}
				if((char *)strstr(lines[z], "<WPSProgramAdd>") != NULL)
				{
					char *args[7], *ptr = lines[z];
					int x;

					for(x=0;x<7;x++)
					{
						if(ptr)
							ptr = strstr(ptr, ",");
						if(ptr)
						{
							ptr[0] = 0;
							ptr = args[x] = &ptr[1];
						}
						else
							args[x] = NULL;
					}
					RemoveProgram(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
				}
				if((char *)strstr(lines[z], "<WPSObjectAdd>") != NULL)
				{
					char *args[6], *ptr = lines[z];
					int x;

					for(x=0;x<6;x++)
					{
						if(ptr)
							ptr = strstr(ptr, ",");
						if(ptr)
						{
							ptr[0] = 0;
							ptr = args[x] = &ptr[1];
						}
						else
							args[x] = NULL;
					}
					RemoveObject(args[0],args[1],args[2],args[3],args[4],args[5]);
				}
				if((char *)strstr(lines[z], "<WPSShadowAdd>") != NULL)
				{
					char *args[5], *ptr = lines[z];
					int x;

					for(x=0;x<5;x++)
					{
						if(ptr)
							ptr = strstr(ptr, ",");
						if(ptr)
						{
							ptr[0] = 0;
							ptr = args[x] = &ptr[1];
						}
						else
							args[x] = NULL;
					}
					RemoveShadow(args[0],args[1],args[2],args[3],args[4]);
				}
				free(lines[z]);
				update_percent(count-z, count);
			}
		}
		free(lines);
		return;
	}
	else
		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Could not find section in install log.");
	fclose(tmplf);
	return;
}

/*
 * Removes any carriage returns or line feeds from the buffer.
 */
void stripcrlf(char *buffer)
{
	int z, len = strlen(buffer);

	for(z=0;z<len;z++)
	{
		if(buffer[z] == '\r' || buffer[z] == '\n')
		{
			buffer[z] = 0;
			return;
		}
	}
}

/*
 * Adds or replaces a SET variable based on the flags (CONFIG.SYS)
 */
#if 0
void updateset(char *setname, char *newvalue, int flag)
{
	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *nv;
	int i, z, t;

    nv=replaceem(newvalue);

	cmpbuf1=malloc(strlen(setname)+2);
	strcpy(cmpbuf1, setname);
	strcat(cmpbuf1, "=");
	for(i=0;i<configfilecount;i++)
	{
		if(strlen(cmpbuf1) <= strlen(configsys[i]))
		{
			tmpptr=(char *)strdup(configsys[i]);
			strupr(tmpptr);
			if((tmpptr2=(char*)strstr(tmpptr, "SET "))!=NULL)
			{
				tmpptr2 += 4;
				cmpbuf2=malloc(strlen(tmpptr2)+1);
				/* Remove any spaces from the string */
				z=0;
				for (t=0;t<strlen(tmpptr2) && z < strlen(cmpbuf1);t++)
				{
					if(tmpptr2[t] != ' ')
					{
						cmpbuf2[z]=tmpptr2[t];
						z++;
					}
				}
				cmpbuf2[z]=0;
				if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
				{
					/* Ok we found the entry, and if UPDATE_ALWAYS change it to the
					 new entry, otherwise exit */
					if(flag == UPDATE_ALWAYS)
					{
						free(configsys[i]);
						configsys[i] = malloc(strlen(setname)+strlen(nv)+6);
                        strcpy(configsys[i], "SET ");
						strcat(configsys[i], setname);
                        strcat(configsys[i], "=");
						strcat(configsys[i], nv);
						free(cmpbuf1);free(cmpbuf2);free(tmpptr);
					}
					return;
				}
				free(cmpbuf2);
			}
			free(tmpptr);
		}
	}
	/* Couldn't find the line so we'll add it */
	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6);
	strcpy(configsys[configfilecount], "SET ");
	strcat(configsys[configfilecount], setname);
	strcat(configsys[configfilecount], "=");
	strcat(configsys[configfilecount], nv);
	configfilecount++;
	free(cmpbuf1);
    free(nv);
}     

/*
 * Adds an entry to a system variable (CONFIG.SYS)
 */
void updatesys(char *sysname, char *newvalue)
{
	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian;
	int i, z, t;

	nv=replaceem(newvalue);

	cmpbuf1=malloc(strlen(sysname)+2);
	strcpy(cmpbuf1, sysname);
	strcat(cmpbuf1, "=");
	for(i=0;i<configfilecount;i++)
	{
		if(strlen(cmpbuf1) <= strlen(configsys[i]))
		{
			cmpbuf2=malloc(strlen(configsys[i])+1);
			/* Remove any spaces from the string */
			z=0;
			for (t=0;t<strlen(configsys[i]) && z < strlen(cmpbuf1);t++)
			{
				if(configsys[i][t] != ' ')
				{
					cmpbuf2[z]=configsys[i][t];
					z++;
				}
			}
			cmpbuf2[z]=0;
			if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
			{
				/* Do a case insensitive comparison but preserve the case */
				tmpptr = &configsys[i][t];
				capbuf1=malloc(strlen(tmpptr)+1);
				capbuf2=malloc(strlen(nv)+1);
				strcpy(capbuf1, tmpptr);
				strcpy(capbuf2, nv);
				strupr(capbuf1);
				strupr(capbuf2);
				/* Ok, we found the line, and it doesn't have an entry so we'll add it */
				if((tmpptr2=(char *)strstr(capbuf1, capbuf2)) == NULL)
				{
					brian = configsys[i];
					configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4);
					strcpy(configsys[i], brian);
					free(brian);
					/* Remove any trailing CRLFs */
					if(configsys[i][strlen(configsys[i])-1]!=';')
						strcat(configsys[i], ";");
					strcat(configsys[i], nv);
					strcat(configsys[i], ";");
				}
				free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2);
				return;
			}
			free(cmpbuf2);
		}
	}
	/* Couldn't find the line so we'll add it */
	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3);
	strcpy(configsys[configfilecount], cmpbuf1);
	strcat(configsys[configfilecount], nv);
	strcat(configsys[configfilecount], ";");
	configfilecount++;
	free(cmpbuf1);
	free(nv);
}
#endif

/*
 * Removes a line from a config file.
 */
void removeline(char *text)
{
	int z;
	for(z=0;z<configfilecount;z++)
	{
		if(strcasecmp(configsys[z], text) == 0)
		{
			int t;

			free(configsys[z]);
			for(t=z;t<(configfilecount-1);t++)
				configsys[t] = configsys[t+1];
			configfilecount--;
		}
	}
}


/*
 * Reads a line from a file and returns it in raw.
 */
void getline(FILE *f, char *raw)
{
	memset(raw, 0, 256);
	fgets(raw, 255, f);
    stripcrlf(raw);
}

/*
 * Removes a character from a buffer by advancing the buffer to the left.
 */
void removechar(char *buffer, int thisone, int len)
{
	int x;

	for(x=thisone;x<len;x++)
        buffer[x] = buffer[x+1];
}

void getbootdrive(void)
{
#ifdef __OS2__
	ULONG   ulSysInfo;

	DosQuerySysInfo(QSV_BOOT_DRIVE,
			QSV_BOOT_DRIVE,
			(PVOID)&ulSysInfo,
			sizeof(ULONG));

	bootdrive[0]=installdir[0]=instlog[0]=csfile[0]=bufile[0]=(char)('A'+(ulSysInfo-1));
#elif defined(__WIN32__)
	char winpath[MAX_PATH+1] = "";

	GetWindowsDirectory(winpath, MAX_PATH);

	if(winpath[0] && winpath[1] == ':')
	{
		bootdrive[0]=installdir[0]=csfile[0]=bufile[0]=winpath[0];
		strcpy(instlog, winpath);
		if(instlog[strlen(instlog)-1] != '\\')
			strcat(instlog, "\\");
		strcat(instlog, "DBINST.LOG");
	}
#endif
}

void remove_uninstall_object(void)
{
#ifdef __OS2__
	char binpath[8096], *objectid = strdup(INSTALLER_APPLICATION);
	HOBJECT ho;
	int z;

	for(z=0;z<strlen(objectid);z++)
	{
		if(objectid[z] == ' ')
			objectid[z] = '_';
	}

	sprintf(binpath, "<DBUNINST_%s>", objectid);
	ho = WinQueryObject(binpath);
	if(ho != NULLHANDLE)
		WinDestroyObject(ho);
	free(objectid);
#elif defined( __WIN32__)
	char keyname[1024];

	sprintf(keyname, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s", INSTALLER_APPLICATION);
	if(RegDeleteKey(HKEY_LOCAL_MACHINE, keyname))
		return;
#endif
}

void actual_install(void *data)
{
	getbootdrive();

	do_uninstall();

	remove_uninstall_object();

	dw_messagebox("Uninstall", DW_MB_OK | DW_MB_INFORMATION, "Finished uninstalling.");

	dw_window_destroy(mainwindow);

	exit(0);
}

void DWSIGNAL start_callback(HWND window, void *data)
{
	dw_window_disable(exitbutton);
	dw_window_disable(nextbutton);

	dw_thread_new((void *)actual_install, NULL, 10000);
}

void DWSIGNAL exit_callback(HWND window, void *data)
{
	dw_window_destroy(mainwindow);

	exit(0);
}

void uninstall_dialog(void)
{
	ULONG flStyle = DW_FCF_SYSMENU | DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_TASKLIST | DW_FCF_DLGBORDER;
	char text[1024];

	mainwindow = dw_window_new(HWND_DESKTOP, "Uninstall", flStyle);

	/* This number must corespond to a resource ID in the bound resources */
	dw_window_set_icon(mainwindow, 2000);

	bigbox = dw_box_new(BOXVERT, 10);

	dw_box_pack_start(mainwindow, bigbox, 0, 0, TRUE, TRUE, 0);

	mainbox = dw_box_new(BOXHORZ, 0);

	dw_box_pack_start(bigbox, mainbox, 0, 0, TRUE, TRUE, 0);

	logo = dw_bitmap_new(1001);

	/* This number must corespond to a resource ID in the bound resources */
	dw_window_set_bitmap(logo, 2001, NULL);

	dw_box_pack_start(mainbox, logo, 100, 275, FALSE, FALSE, 10);

	custombox = dw_box_new(BOXVERT, 0);

	dw_box_pack_start(mainbox, custombox, 0, 0, TRUE, TRUE, 0);

	sprintf(text, "Ready to Uninstall %s %s", INSTALLER_APPLICATION, INSTALLER_VERSION);
	stext = dw_text_new(text, 0);

	dw_window_set_style(stext, DW_DT_VCENTER, DW_DT_VCENTER);

	dw_box_pack_start(custombox, stext, 300, 50, TRUE, TRUE, 10);

	groupbox = dw_groupbox_new(BOXHORZ, 10, "Progress");

	dw_box_pack_start(custombox, groupbox, 0, 0, TRUE, FALSE, 10);

	slider = dw_percent_new(1010);

	dw_box_pack_start(groupbox, slider, 300, 20, TRUE, FALSE, 10);

	status = dw_text_new("", 0);

	dw_box_pack_start(custombox, status, 300, 50, TRUE, TRUE, 10);

	dw_box_pack_start(custombox, 0, 300, 100, TRUE, TRUE, 10);

	buttonbox = dw_box_new(BOXHORZ, 5);

	dw_box_pack_start(bigbox, buttonbox, 0, 0, TRUE, FALSE, 0);

	exitbutton = dw_button_new("Exit Uninstall", 1003);

	dw_box_pack_start(buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0);

	blanktext = dw_text_new("", 0);

	dw_box_pack_start(buttonbox, blanktext, 150, 30, TRUE, FALSE, 0);

	nextbutton = dw_button_new("Begin >>", 1001);

	dw_box_pack_start(buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0);

	/* Set some nice fonts and colors */
#ifdef __OS2__
	dw_window_set_font(stext, "9.WarpSans Bold");
#elif defined(__WIN32__)
	dw_window_set_font(stext, "14.Arial Bold");
#endif

	dw_signal_connect(exitbutton, "clicked", DW_SIGNAL_FUNC(exit_callback), NULL);
	dw_signal_connect(nextbutton, "clicked", DW_SIGNAL_FUNC(start_callback), NULL);

	dw_window_set_pos_size(mainwindow, (dw_screen_width()-550)/2, (dw_screen_height()-375)/2, 550, 375);
	dw_window_show(mainwindow);
}

/*
 * Main function
 */
int main(int argc, char *argv[])
{
	dw_init(TRUE, argc, argv);

	if(argc > 2)
	{
		INSTALLER_APPLICATION = argv[1];
		INSTALLER_VERSION = argv[2];
	}
	else
	{
		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Error in uninstaller.");
		return 0;
	}

	uninstall_dialog();

	dw_main();

	return 0;
}