summaryrefslogtreecommitdiff
path: root/gs/psi/dwuninst.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gs/psi/dwuninst.cpp')
-rw-r--r--gs/psi/dwuninst.cpp918
1 files changed, 918 insertions, 0 deletions
diff --git a/gs/psi/dwuninst.cpp b/gs/psi/dwuninst.cpp
new file mode 100644
index 000000000..4d7305e41
--- /dev/null
+++ b/gs/psi/dwuninst.cpp
@@ -0,0 +1,918 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+// $Id$
+
+#define STRICT
+#include <windows.h>
+#include <objbase.h>
+#include <shlobj.h>
+#include <shellapi.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <direct.h>
+#include "dwuninst.h"
+
+
+#ifdef _MSC_VER
+#define _export
+#define chdir(x) _chdir(x)
+#define mkdir(x) _mkdir(x)
+#endif
+#define DELAY_STEP 500
+#define DELAY_FILE 0
+#define MAXSTR 256
+#define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
+
+HWND hDlgModeless;
+HWND hText1;
+HWND hText2;
+char path[MAXSTR];
+int language = 0;
+BOOL is_win4 = FALSE;
+HINSTANCE phInstance;
+char szSection[] = "////////////////////////////////";
+BOOL bQuit = FALSE;
+BOOL gError = FALSE; // set TRUE if an uninstall was not successful
+BOOL bSilent = FALSE;
+
+char szTitle[MAXSTR];
+char szLogFile[MAXSTR];
+char szLine[MAXSTR];
+FILE *fLog;
+
+void do_message(void);
+BOOL dofiles(void);
+BOOL registry_delete(void);
+BOOL registry_import(void);
+BOOL shell_new(void);
+BOOL shell_old(void);
+BOOL doEOF(void);
+
+#ifdef _WIN64
+#define DLGRETURN INT_PTR
+#else
+#define DLGRETURN BOOL
+#endif
+
+// #define gs_addmess(str) fputs(str, stdout) // for debug
+#define gs_addmess(str)
+
+int message_box(LPCTSTR message, LPCTSTR title, int nType)
+{
+ if (bSilent)
+ return 0;
+ return MessageBox(HWND_DESKTOP, message, title, nType);
+}
+
+// linked list for deleting registry entries in reverse order
+typedef struct tagKEY {
+ long index;
+ struct tagKEY *previous;
+} KEY;
+KEY *last_key = NULL;
+
+
+// read a line from the log, removing trailing new line character
+BOOL GetLine(void)
+{
+ BOOL err = TRUE;
+ int i;
+ szLine[0] = '\0';
+ if (fLog)
+ err = (fgets(szLine, sizeof(szLine)-1, fLog) == NULL);
+ i = strlen(szLine) - 1;
+ if ( (szLine[0] != '\0') && (szLine[i] == '\n'))
+ szLine[i] = '\0';
+ return !err;
+}
+
+BOOL IsSection(void)
+{
+ return (strncmp(szLine, szSection, strlen(szSection)) == 0);
+}
+
+BOOL
+NextSection(void)
+{
+ while (GetLine()) {
+ do_message();
+ if (bQuit)
+ return FALSE;
+ if (IsSection())
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+BOOL ReadSection(void)
+{
+ do_message();
+ if (bQuit)
+ return FALSE;
+ GetLine();
+ if (strlen(szLine) == 0) {
+ doEOF();
+ return TRUE;
+ }
+ else if (strcmp(szLine, "FileNew")==0) {
+ SetWindowText(hText1, "Removing Files");
+ if (!bSilent)
+ Sleep(DELAY_STEP);
+ if (!dofiles())
+ return FALSE;
+ SetWindowText(hText1, "");
+ return TRUE;
+ }
+ else if (strcmp(szLine, "RegistryNew")==0) {
+ SetWindowText(hText1, "Removing Registry entries");
+ if (!bSilent)
+ Sleep(DELAY_STEP);
+ if (!registry_delete())
+ return FALSE;
+ SetWindowText(hText1, "");
+ return TRUE;
+ }
+ else if (strcmp(szLine, "RegistryOld")==0) {
+ SetWindowText(hText1, "Restoring Registry entries");
+ if (!bSilent)
+ Sleep(DELAY_STEP);
+ if (!registry_import())
+ return FALSE;
+ SetWindowText(hText1, "");
+ return TRUE;
+ }
+ else if (strcmp(szLine, "ShellNew")==0) {
+ SetWindowText(hText1, "Removing Start Menu items");
+ if (!bSilent)
+ Sleep(DELAY_STEP);
+ if (!shell_new())
+ return FALSE;
+ SetWindowText(hText1, "");
+ return TRUE;
+ }
+ else if (strcmp(szLine, "ShellOld")==0) {
+ SetWindowText(hText1, "Restoring Start Menu items");
+ if (!bSilent)
+ Sleep(DELAY_STEP);
+ if (!shell_old())
+ return FALSE;
+ SetWindowText(hText1, "");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL
+dofiles(void)
+{
+ while (GetLine()) {
+ do_message();
+ if (bQuit)
+ return FALSE;
+ if (IsSection()) {
+ SetWindowText(hText2, "");
+ return TRUE;
+ }
+ if (szLine[0] != '\0') {
+ SetWindowText(hText2, szLine);
+ if (!bSilent)
+ Sleep(DELAY_FILE);
+ gs_addmess("Deleting File: ");
+ gs_addmess(szLine);
+ gs_addmess("\n");
+ DeleteFile(szLine);
+ }
+ }
+ return FALSE;
+}
+
+BOOL
+doEOF(void)
+{
+ fclose(fLog);
+ fLog = NULL;
+ unlink(szLogFile);
+ PostMessage(hDlgModeless, WM_COMMAND, IDC_DONE, 0L);
+ bQuit = TRUE;
+ return TRUE;
+}
+
+
+BOOL
+registry_delete_key(void)
+{
+char keyname[MAXSTR];
+HKEY hkey = HKEY_CLASSES_ROOT;
+HKEY hrkey = HKEY_CLASSES_ROOT;
+char *rkey, *skey;
+char *name;
+DWORD dwResult;
+ keyname[0] = '\0';
+ while (GetLine()) {
+ if ((szLine[0] == '\0') || (szLine[0] == '\r') || (szLine[0] == '\n'))
+ break;
+ if (szLine[0] == '[') {
+ // key name
+ rkey = strtok(szLine+1, "\\]\n\r");
+ if (rkey == (char *)NULL)
+ return FALSE;
+ skey = strtok(NULL, "]\n\r");
+ if (strcmp(rkey, "HKEY_CLASSES_ROOT")==0)
+ hrkey = HKEY_CLASSES_ROOT;
+ else if (strcmp(rkey, "HKEY_CURRENT_USER")==0)
+ hrkey = HKEY_CURRENT_USER;
+ else if (strcmp(rkey, "HKEY_LOCAL_MACHINE")==0)
+ hrkey = HKEY_LOCAL_MACHINE;
+ else if (strcmp(rkey, "HKEY_USERS")==0)
+ hrkey = HKEY_USERS;
+ else
+ return FALSE;
+ if (skey == (char *)NULL)
+ return FALSE;
+ gs_addmess("Opening registry key\n ");
+ gs_addmess(rkey);
+ gs_addmess("\\");
+ gs_addmess(skey);
+ gs_addmess("\n");
+ if (RegCreateKeyEx(hrkey, skey, 0, "", 0, KEY_ALL_ACCESS,
+ NULL, &hkey, &dwResult)
+ != ERROR_SUCCESS)
+ return FALSE;
+ strcpy(keyname, skey);
+ }
+ else if (szLine[0] == '@') {
+ // default value
+ RegDeleteValue(hkey, NULL);
+ gs_addmess("Deleting registry default value\n");
+ }
+ else if (szLine[0] == '\042') {
+ // named value
+ name = strtok(szLine+1, "\042\r\n");
+ RegDeleteValue(hkey, name);
+ gs_addmess("Deleting registry named value\n ");
+ gs_addmess(name);
+ gs_addmess("\n");
+ }
+ }
+
+ // Find out if key has subkeys or values
+ TCHAR szClass[MAXSTR];
+ DWORD cchClass;
+ DWORD cSubKeys;
+ DWORD cchMaxSubKey;
+ DWORD cchMaxClass;
+ DWORD cValues;
+ DWORD cchMaxValueName;
+ DWORD cbMaxValueData;
+ DWORD cbSecurityDescriptor;
+ FILETIME ftLastWriteTime;
+ cchClass = sizeof(szClass) / sizeof(TCHAR);
+ cSubKeys = 0;
+ cValues = 0;
+ RegQueryInfoKey(hkey, szClass, &cchClass, NULL,
+ &cSubKeys, &cchMaxSubKey, &cchMaxClass,
+ &cValues, &cchMaxValueName, &cbMaxValueData,
+ &cbSecurityDescriptor, &ftLastWriteTime);
+
+ // close key
+ if (hkey != HKEY_CLASSES_ROOT)
+ RegCloseKey(hkey);
+ // delete the key
+ if ((cSubKeys != 0) || (cValues != 0)) {
+ gs_addmess("Not deleting non empty registry key\n ");
+ gs_addmess(keyname);
+ gs_addmess("\n");
+ }
+ else if (strlen(keyname)) {
+ gs_addmess("Deleting registry key\n ");
+ gs_addmess(keyname);
+ gs_addmess("\n");
+ RegOpenKeyEx(hrkey, NULL, 0, 0, &hkey);
+ RegDeleteKey(hkey, keyname);
+ RegCloseKey(hkey);
+ }
+ return TRUE;
+}
+
+BOOL
+registry_delete()
+{
+ long logindex;
+ KEY *key;
+
+ // scan log file
+ // so we can remove keys in reverse order
+ logindex = 0;
+ while (GetLine() && !IsSection()) {
+ KEY *key;
+ if (szLine[0] == '[') {
+ if ((key = (KEY *)malloc(sizeof(KEY)))
+ != (KEY *)NULL) {
+ key->previous = last_key;
+ key->index = logindex;
+ last_key = key;
+ }
+ }
+ logindex = ftell(fLog);
+ }
+
+ // Remove keys
+ for (key = last_key; key != NULL; key = key->previous) {
+ if (key != last_key)
+ free(last_key);
+ fseek(fLog, key->index, SEEK_SET);
+ registry_delete_key();
+ last_key = key;
+ }
+ free(last_key);
+
+ fseek(fLog, logindex, SEEK_SET);
+ GetLine();
+ return TRUE;
+}
+
+
+
+void
+registry_unquote(char *line)
+{
+char *s, *d;
+int value;
+ s = d = line;
+ while (*s) {
+ if (*s != '\\') {
+ *d++ = *s;
+ }
+ else {
+ s++;
+ if (*s == '\\')
+ *d++ = *s;
+ else {
+ value = 0;
+ if (*s) {
+ value = *s++ - '0';
+ }
+ if (*s) {
+ value <<= 3;
+ value += *s++ - '0';
+ }
+ if (*s) {
+ value <<= 3;
+ value += *s - '0';
+ }
+ *d++ = (char)value;
+ }
+ }
+ s++;
+ }
+ *d = '\0';
+}
+
+BOOL
+registry_import()
+{
+ HKEY hkey = HKEY_CLASSES_ROOT;
+ HKEY hrkey;
+ char *rkey, *skey;
+ char *value;
+ char *name;
+ DWORD dwResult;
+ GetLine();
+ if (strncmp(szLine, "REGEDIT4", 8) != 0)
+ return FALSE;
+
+ while (GetLine()) {
+ if (IsSection())
+ break;
+ if ((szLine[0] == '\0') || (szLine[0] == '\r') || (szLine[0] == '\n'))
+ continue;
+ if (szLine[0] == '[') {
+ // key name
+ if (hkey != HKEY_CLASSES_ROOT) {
+ RegCloseKey(hkey);
+ hkey = HKEY_CLASSES_ROOT;
+ }
+ rkey = strtok(szLine+1, "\\]\n\r");
+ if (rkey == (char *)NULL)
+ return FALSE;
+ skey = strtok(NULL, "]\n\r");
+ if (strcmp(rkey, "HKEY_CLASSES_ROOT")==0)
+ hrkey = HKEY_CLASSES_ROOT;
+ else if (strcmp(rkey, "HKEY_CURRENT_USER")==0)
+ hrkey = HKEY_CURRENT_USER;
+ else if (strcmp(rkey, "HKEY_LOCAL_MACHINE")==0)
+ hrkey = HKEY_LOCAL_MACHINE;
+ else if (strcmp(rkey, "HKEY_USERS")==0)
+ hrkey = HKEY_USERS;
+ else
+ return FALSE;
+ if (skey == (char *)NULL)
+ return FALSE;
+ gs_addmess("Creating registry key\n ");
+ gs_addmess(rkey);
+ gs_addmess("\\");
+ gs_addmess("skey");
+ gs_addmess("\n");
+ if (RegCreateKeyEx(hrkey, skey, 0, "", 0, KEY_ALL_ACCESS,
+ NULL, &hkey, &dwResult)
+ != ERROR_SUCCESS)
+ return FALSE;
+ }
+ else if (szLine[0] == '@') {
+ // default value
+ if (strlen(szLine) < 4)
+ return FALSE;
+ value = strtok(szLine+3, "\042\r\n");
+ if (value) {
+ registry_unquote(value);
+ gs_addmess("Setting registry key value\n ");
+ gs_addmess(value);
+ gs_addmess("\n");
+ if (RegSetValueEx(hkey, NULL, 0, REG_SZ,
+ (CONST BYTE *)value, strlen(value)+1)
+ != ERROR_SUCCESS)
+ return FALSE;
+ }
+ }
+ else if (szLine[0] == '\042') {
+ // named value
+ name = strtok(szLine+1, "\042\r\n");
+ strtok(NULL, "\042\r\n");
+ value = strtok(NULL, "\042\r\n");
+ registry_unquote(value);
+ gs_addmess("Setting registry key value\n ");
+ gs_addmess(name);
+ gs_addmess("=");
+ gs_addmess(value);
+ gs_addmess("\n");
+ if (RegSetValueEx(hkey, name, 0, REG_SZ, (CONST BYTE *)value,
+ strlen(value)+1) != ERROR_SUCCESS)
+ return FALSE;
+ }
+ }
+ if (hkey != HKEY_CLASSES_ROOT)
+ RegCloseKey(hkey);
+ return TRUE;
+}
+
+// recursive mkdir
+// requires a full path to be specified, so ignores root \
+// apart from root \, must not contain trailing \
+// Examples:
+// c:\ (OK, but useless)
+// c:\gstools (OK)
+// c:\gstools\ (incorrect)
+// c:gstools (incorrect)
+// gstools (incorrect)
+// The following UNC names should work,
+// but didn't under Win3.1 because gs_chdir wouldn't accept UNC names
+// Needs to be tested under Windows 95.
+// \\server\sharename\gstools (OK)
+// \\server\sharename\ (OK, but useless)
+//
+
+BOOL MakeDir(char *dirname)
+{
+char newdir[MAXSTR];
+char *p;
+ if (strlen(dirname) < 3)
+ return -1;
+
+ gs_addmess("Making Directory\n ");
+ gs_addmess(dirname);
+ gs_addmess("\n");
+ if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') {
+ // drive mapped path
+ p = dirname+3;
+ }
+ else if (dirname[1]=='\\' && dirname[1]=='\\') {
+ // UNC path
+ p = strchr(dirname+2, '\\'); // skip servername
+ if (p == NULL)
+ return -1;
+ p++;
+ p = strchr(p, '\\'); // skip sharename
+ if (p == NULL)
+ return -1;
+ }
+ else {
+ // not full path so error
+ return -1;
+ }
+
+ while (1) {
+ strncpy(newdir, dirname, (int)(p-dirname));
+ newdir[(int)(p-dirname)] = '\0';
+ if (chdir(newdir)) {
+ if (mkdir(newdir))
+ return -1;
+ }
+ p++;
+ if (p >= dirname + strlen(dirname))
+ break; // all done
+ p = strchr(p, '\\');
+ if (p == NULL)
+ p = dirname + strlen(dirname);
+ }
+
+ return SetCurrentDirectory(dirname);
+}
+
+
+BOOL shell_new(void)
+{
+
+ char *p, *q;
+ char group[MAXSTR];
+ // remove shell items added by Ghostscript
+ // We can only delete one group with this code
+ group[0] = '\0';
+ while (GetLine()) {
+ if (IsSection()) {
+ if (strlen(group) != 0) {
+ gs_addmess("Removing shell folder\n ");
+ gs_addmess(group);
+ gs_addmess("\n");
+ RemoveDirectory(group);
+ }
+ return TRUE;
+ }
+ p = strtok(szLine, "=");
+ q = strtok(NULL, "");
+ if (p == NULL) {
+ continue;
+ }
+ else if (strcmp(p, "Group")==0) {
+ if (q)
+ strncpy(group, q, sizeof(group)-1);
+ // defer this until we have remove contents
+ }
+ else if (strcmp(p, "Name") == 0) {
+ if (q) {
+ gs_addmess("Removing shell link\n ");
+ gs_addmess(q);
+ gs_addmess("\n");
+ DeleteFile(q);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL CreateShellLink(LPCSTR name, LPCSTR description, LPCSTR program,
+ LPCSTR arguments, LPCSTR directory, LPCSTR icon, int nIconIndex)
+{
+ HRESULT hres;
+ IShellLink* psl;
+
+ // Ensure string is UNICODE.
+ WCHAR wsz[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, name, -1, wsz, MAX_PATH);
+
+ // Save new shell link
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (void **)&psl);
+ if (SUCCEEDED(hres)) {
+ IPersistFile* ppf;
+ // Query IShellLink for the IPersistFile interface for
+ // saving the shell link in persistent storage.
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ gs_addmess("Adding shell link\n ");
+ gs_addmess(name);
+ gs_addmess("\n");
+
+ // Set the path to the shell link target.
+ hres = psl->SetPath(program);
+ if (!SUCCEEDED(hres)) {
+ gs_addmess("SetPath failed!");
+ gError = TRUE;
+ }
+ // Set the description of the shell link.
+ hres = psl->SetDescription(description);
+ if (!SUCCEEDED(hres)) {
+ gs_addmess("SetDescription failed!");
+ gError = TRUE;
+ }
+ if ((arguments != (LPCSTR)NULL) && *arguments) {
+ // Set the arguments of the shell link target.
+ hres = psl->SetArguments(arguments);
+ if (!SUCCEEDED(hres)) {
+ gs_addmess("SetArguments failed!");
+ gError = TRUE;
+ }
+ }
+ if ((directory != (LPCSTR)NULL) && *directory) {
+ // Set the arguments of the shell link target.
+ hres = psl->SetWorkingDirectory(directory);
+ if (!SUCCEEDED(hres)) {
+ gs_addmess("SetWorkingDirectory failed!");
+ gError = TRUE;
+ }
+ }
+ if ((icon != (LPCSTR)NULL) && *icon) {
+ // Set the arguments of the shell link target.
+ hres = psl->SetIconLocation(icon, nIconIndex);
+ if (!SUCCEEDED(hres)) {
+ gs_addmess("SetIconLocation failed!");
+ gError = TRUE;
+ }
+ }
+
+ // Save the link via the IPersistFile::Save method.
+ hres = ppf->Save(wsz, TRUE);
+ // Release pointer to IPersistFile.
+ ppf->Release();
+ }
+ // Release pointer to IShellLink.
+ psl->Release();
+ }
+
+ return (hres == 0);
+}
+
+
+
+BOOL shell_old(void)
+{
+ // Add shell items removed by Ghostscript
+ char *p, *q;
+ char name[MAXSTR];
+ char description[MAXSTR];
+ char program[MAXSTR];
+ char arguments[MAXSTR];
+ char directory[MAXSTR];
+ char icon[MAXSTR];
+ int nIconIndex;
+ // Remove shell items added by Ghostscript
+ name[0] = description[0] = program[0] = arguments[0]
+ = directory[0] = icon[0] = '\0';
+ nIconIndex = 0;
+
+ while (GetLine()) {
+ if (IsSection())
+ return TRUE;
+ p = strtok(szLine, "=");
+ q = strtok(NULL, "");
+ if (strlen(szLine) == 0) {
+ if (name[0] != '\0') {
+ // add start menu item
+ CreateShellLink(name, description, program, arguments,
+ directory, icon, nIconIndex);
+ }
+ name[0] = description[0] = program[0] = arguments[0]
+ = directory[0] = icon[0] = '\0';
+ nIconIndex = 0;
+ continue;
+ }
+ else if (p == (char *)NULL) {
+ continue;
+ }
+ else if (strcmp(p, "Group")==0) {
+ MakeDir(q);
+ }
+ else if (strcmp(p, "Name") == 0)
+ strncpy(name, q, sizeof(name)-1);
+ else if (strcmp(p, "Description") == 0)
+ strncpy(description, q, sizeof(description)-1);
+ else if (strcmp(p, "Program") == 0)
+ strncpy(program, q, sizeof(program)-1);
+ else if (strcmp(p, "Arguments") == 0)
+ strncpy(arguments, q, sizeof(arguments)-1);
+ else if (strcmp(p, "Directory") == 0)
+ strncpy(directory, q, sizeof(directory)-1);
+ else if (strcmp(p, "IconLocation") == 0)
+ strncpy(icon, q, sizeof(icon)-1);
+ else if (strcmp(p, "IconIndex") == 0)
+ nIconIndex = atoi(q);
+ }
+
+ return TRUE;
+}
+
+
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+DLGRETURN CALLBACK _export
+RemoveDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_INITDIALOG:
+ SetWindowText(hwnd, szTitle);
+ if (bSilent)
+ PostMessage(hwnd, WM_COMMAND, IDOK, 0);
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_DONE:
+ // delete registry entries for uninstall
+ if (is_win4) {
+ HKEY hkey;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ UNINSTALLKEY, 0, KEY_ALL_ACCESS, &hkey)
+ == ERROR_SUCCESS) {
+ RegDeleteKey(hkey, szTitle);
+ RegCloseKey(hkey);
+ }
+ }
+
+ SetWindowText(hText1, "Uninstall successful");
+ SetWindowText(hText2, "");
+ EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDCANCEL), TRUE);
+ SetDlgItemText(hwnd, IDCANCEL, "Exit");
+ SetFocus(GetDlgItem(hwnd, IDCANCEL));
+ if (bSilent)
+ PostMessage(hwnd, WM_COMMAND, IDCANCEL, 0);
+ return TRUE;
+ case IDOK:
+ // Start removal
+ EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_PRESSOK), FALSE);
+ while (!bQuit) {
+ do_message();
+ if (!ReadSection()) {
+ SetWindowText(hText1, "Uninstall FAILED");
+ SetWindowText(hText2, "");
+ EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDCANCEL), TRUE);
+ SetDlgItemText(hwnd, IDCANCEL, "Exit");
+ SetFocus(GetDlgItem(hwnd, IDCANCEL));
+ bQuit = TRUE;
+ }
+ }
+ return TRUE;
+ case IDCANCEL:
+ bQuit = TRUE;
+ DestroyWindow(hwnd);
+ hDlgModeless = 0;
+ return TRUE;
+ }
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ hDlgModeless = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+do_message(void)
+{
+MSG msg;
+ while (hDlgModeless && PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) {
+ if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+
+
+BOOL
+init(void)
+{
+ DWORD version = GetVersion();
+ char *p, *s;
+ int len;
+ BOOL inquote = FALSE;
+ // get location of uninstall log from command line as argv[1]
+ p = GetCommandLine();
+ s = p;
+ if (*s == '\042') {
+ // skip over program name
+ s++;
+ while (*s && *s!='\042')
+ s++;
+ if (*s)
+ s++;
+ }
+ else if (*s != ' ') {
+ // skip over program name
+ s++;
+ while (*s && *s!=' ')
+ s++;
+ if (*s)
+ s++;
+ }
+ while (*s && *s==' ')
+ s++;
+ if (*s == '\042') {
+ s++;
+ inquote = TRUE;
+ }
+ p = s;
+ if (inquote) {
+ while (*s && (*s != '\042'))
+ s++;
+ }
+ else {
+ while (*s && (*s != ' '))
+ s++;
+ }
+ len = s - p;
+ strncpy(szLogFile, p, min(len, (int)sizeof(szLogFile)-1));
+ szLogFile[len] = '\0';
+ if (inquote && (*s == '\042')) {
+ s++;
+ inquote = FALSE;
+ }
+
+ if (strlen(szLogFile) == 0) {
+ message_box("Usage: uninstgs logfile.txt [-q]",
+ "GPL Ghostscript Uninstall", MB_OK);
+ return FALSE;
+ }
+
+ while (*s && *s==' ')
+ s++;
+ if (strncmp(s, "-q", 2) == 0)
+ bSilent = TRUE;
+
+ // read first few lines of file to get title
+ fLog = fopen(szLogFile, "r");
+ if (fLog == (FILE *)NULL) {
+ message_box(szLogFile, "Can't find file", MB_OK);
+ return FALSE;
+ }
+ GetLine();
+ if (!IsSection()) {
+ message_box(szLogFile, "Not valid uninstall log", MB_OK);
+ return FALSE;
+ }
+ GetLine();
+ if (strcmp(szLine, "UninstallName") != 0) {
+ message_box(szLogFile, "Not valid uninstall log", MB_OK);
+ return FALSE;
+ }
+ GetLine();
+ strcpy(szTitle, szLine);
+
+ NextSection();
+
+ if (LOBYTE(LOWORD(version)) >= 4)
+ is_win4 = TRUE;
+ return TRUE;
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+int PASCAL
+WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
+{
+MSG msg;
+
+ phInstance = hInstance;
+ if (!init())
+ return 1;
+
+
+ CoInitialize(NULL);
+
+ hDlgModeless = CreateDialogParam(hInstance,
+ MAKEINTRESOURCE(IDD_UNSET),
+ HWND_DESKTOP, RemoveDlgProc, (LPARAM)NULL);
+ hText1 = GetDlgItem(hDlgModeless, IDC_T1);
+ hText2 = GetDlgItem(hDlgModeless, IDC_T2);
+
+ SetWindowPos(hDlgModeless, HWND_TOP, 0, 0, 0, 0,
+ (bSilent ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | SWP_NOMOVE | SWP_NOSIZE);
+
+ while (hDlgModeless && GetMessage(&msg, (HWND)NULL, 0, 0)) {
+ if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ if (fLog)
+ fclose(fLog);
+
+ CoUninitialize();
+
+ return 0;
+}
+