Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999, Ghostgum Software Pty Ltd.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
// $Id: dwuninst.cpp,v 1.6 2005/03/04 21:58:55 ghostgum Exp $
18
 
19
#define STRICT
20
#include <windows.h>
21
#include <objbase.h>
22
#include <shlobj.h>
23
#include <shellapi.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <stdlib.h>
27
#include <direct.h>
28
#include "dwuninst.h"
29
 
30
 
31
#ifdef _MSC_VER
32
#define _export
33
#define chdir(x) _chdir(x)
34
#define mkdir(x) _mkdir(x)
35
#endif
36
#define DELAY_STEP 500
37
#define DELAY_FILE 0
38
#define MAXSTR 256
39
#define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
40
 
41
#ifdef _WIN64
42
#define DLGRETURN INT_PTR
43
#else
44
#define DLGRETURN BOOL
45
#endif
46
 
47
 
48
HWND hDlgModeless;
49
HWND hText1;
50
HWND hText2;
51
char path[MAXSTR];
52
int language = 0;
53
BOOL is_win4 = FALSE;
54
HINSTANCE phInstance;
55
char szSection[] = "////////////////////////////////";
56
BOOL bQuit = FALSE;
57
BOOL gError = FALSE;	// set TRUE if an uninstall was not successful 
58
 
59
char szTitle[MAXSTR];
60
char szLogFile[MAXSTR];
61
char szLine[MAXSTR];
62
FILE *fLog;
63
 
64
void do_message(void);
65
BOOL dofiles(void);
66
BOOL registry_delete(void);
67
BOOL registry_import(void);
68
BOOL shell_new(void);
69
BOOL shell_old(void);
70
BOOL doEOF(void);
71
 
72
// #define gs_addmess(str) fputs(str, stdout)	// for debug 
73
#define gs_addmess(str)
74
 
75
 
76
// linked list for deleting registry entries in reverse order
77
typedef struct tagKEY {
78
    long index;
79
    struct tagKEY *previous;
80
} KEY;
81
KEY *last_key = NULL;
82
 
83
 
84
// read a line from the log, removing trailing new line character
85
BOOL GetLine(void)
86
{
87
    BOOL err = TRUE;
88
    int i;
89
    szLine[0] = '\0';
90
    if (fLog)
91
        err = (fgets(szLine, sizeof(szLine)-1, fLog) == NULL);
92
    i = strlen(szLine) - 1;
93
    if ( (szLine[0] != '\0') && (szLine[i] == '\n'))
94
		szLine[i] = '\0';
95
    return !err;
96
}
97
 
98
BOOL IsSection(void)
99
{
100
    return (strncmp(szLine, szSection, strlen(szSection)) == 0);
101
}
102
 
103
BOOL
104
NextSection(void)
105
{
106
    while (GetLine()) {
107
		do_message();
108
		if (bQuit)
109
			return FALSE;
110
		if (IsSection())
111
			return TRUE;
112
	}
113
 
114
	return TRUE;
115
}
116
 
117
BOOL ReadSection(void)
118
{
119
	do_message();
120
	if (bQuit)
121
		return FALSE;
122
	GetLine();
123
	if (strlen(szLine) == 0) {
124
		doEOF();
125
		return TRUE;
126
	}
127
	else if (strcmp(szLine, "FileNew")==0) {
128
		SetWindowText(hText1, "Removing Files");
129
		Sleep(DELAY_STEP);
130
		if (!dofiles())
131
			return FALSE;
132
		SetWindowText(hText1, "");
133
		return TRUE;
134
	}
135
	else if (strcmp(szLine, "RegistryNew")==0) {
136
		SetWindowText(hText1, "Removing Registry entries");
137
		Sleep(DELAY_STEP);
138
		if (!registry_delete())
139
			return FALSE;
140
		SetWindowText(hText1, "");
141
		return TRUE;
142
	}
143
	else if (strcmp(szLine, "RegistryOld")==0) {
144
		SetWindowText(hText1, "Restoring Registry entries");
145
		Sleep(DELAY_STEP);
146
		if (!registry_import())
147
			return FALSE;
148
		SetWindowText(hText1, "");
149
		return TRUE;
150
	}
151
	else if (strcmp(szLine, "ShellNew")==0) {
152
		SetWindowText(hText1, "Removing Start Menu items");
153
		Sleep(DELAY_STEP);
154
		if (!shell_new())
155
			return FALSE;
156
		SetWindowText(hText1, "");
157
		return TRUE;
158
	}
159
	else if (strcmp(szLine, "ShellOld")==0) {
160
		SetWindowText(hText1, "Restoring Start Menu items");
161
		Sleep(DELAY_STEP);
162
		if (!shell_old())
163
			return FALSE;
164
		SetWindowText(hText1, "");
165
		return TRUE;
166
	}
167
	return FALSE;
168
}
169
 
170
 
171
BOOL
172
dofiles(void)
173
{
174
    while (GetLine()) {
175
	do_message();
176
	if (bQuit)
177
	    return FALSE;
178
	if (IsSection()) {
179
	    SetWindowText(hText2, "");
180
	    return TRUE;
181
	}
182
	if (szLine[0] != '\0') {
183
	    SetWindowText(hText2, szLine);
184
	    Sleep(DELAY_FILE);
185
	    gs_addmess("Deleting File: ");
186
	    gs_addmess(szLine);
187
	    gs_addmess("\n");
188
	    DeleteFile(szLine);
189
	}
190
    }
191
    return FALSE;
192
}
193
 
194
BOOL
195
doEOF(void)
196
{
197
    fclose(fLog);
198
    fLog = NULL;
199
    unlink(szLogFile);
200
    PostMessage(hDlgModeless, WM_COMMAND, IDC_DONE, 0L);
201
	bQuit = TRUE;
202
    return TRUE;
203
}
204
 
205
 
206
BOOL
207
registry_delete_key(void)
208
{
209
char keyname[MAXSTR];
210
HKEY hkey = HKEY_CLASSES_ROOT;
211
HKEY hrkey = HKEY_CLASSES_ROOT;
212
char *rkey, *skey;
213
char *name;
214
DWORD dwResult;
215
    keyname[0] = '\0';
216
    while (GetLine()) {
217
	if ((szLine[0] == '\0') || (szLine[0] == '\r') || (szLine[0] == '\n'))
218
	    break;
219
	if (szLine[0] == '[') {
220
	    // key name
221
	    rkey = strtok(szLine+1, "\\]\n\r");
222
	    if (rkey == (char *)NULL)
223
		return FALSE;
224
	    skey = strtok(NULL, "]\n\r");
225
	    if (strcmp(rkey, "HKEY_CLASSES_ROOT")==0)
226
		hrkey = HKEY_CLASSES_ROOT;
227
	    else if (strcmp(rkey, "HKEY_CURRENT_USER")==0)
228
		hrkey = HKEY_CURRENT_USER;
229
	    else if (strcmp(rkey, "HKEY_LOCAL_MACHINE")==0)
230
		hrkey = HKEY_LOCAL_MACHINE;
231
	    else if (strcmp(rkey, "HKEY_USERS")==0)
232
		hrkey = HKEY_USERS;
233
	    else
234
		return FALSE;
235
	    if (skey == (char *)NULL)
236
		return FALSE;
237
	    gs_addmess("Opening registry key\n   ");
238
	    gs_addmess(rkey);
239
	    gs_addmess("\\");
240
	    gs_addmess(skey);
241
	    gs_addmess("\n");
242
	    if (RegCreateKeyEx(hrkey, skey, 0, "", 0, KEY_ALL_ACCESS, 
243
		NULL, &hkey, &dwResult)
244
		!= ERROR_SUCCESS)
245
		return FALSE;
246
	    strcpy(keyname, skey);
247
	}
248
	else if (szLine[0] == '@') {
249
	    // default value
250
	    RegDeleteValue(hkey, NULL);
251
	    gs_addmess("Deleting registry default value\n");
252
	}
253
	else if (szLine[0] == '\042') {
254
	    // named value
255
	    name = strtok(szLine+1, "\042\r\n");
256
	    RegDeleteValue(hkey, name);
257
	    gs_addmess("Deleting registry named value\n   ");
258
	    gs_addmess(name);
259
	    gs_addmess("\n");
260
	}
261
    }
262
    // close key
263
    if (hkey != HKEY_CLASSES_ROOT)
264
	RegCloseKey(hkey);
265
    // delete the key
266
    if (strlen(keyname)) {
267
	gs_addmess("Deleting registry key\n   ");
268
	gs_addmess(keyname);
269
	gs_addmess("\n");
270
	RegOpenKeyEx(hrkey, NULL, 0, 0, &hkey);
271
	RegDeleteKey(hkey, keyname);
272
	RegCloseKey(hkey);
273
    }
274
    return TRUE;
275
}
276
 
277
BOOL
278
registry_delete()
279
{
280
	long logindex;
281
	KEY *key;
282
 
283
    // scan log file
284
    // so we can remove keys in reverse order
285
    logindex = 0;
286
    while (GetLine() && !IsSection()) {
287
		KEY *key;
288
		if (szLine[0] == '[') {
289
			if ((key = (KEY *)malloc(sizeof(KEY)))
290
				!= (KEY *)NULL) {
291
				key->previous = last_key;
292
				key->index = logindex;
293
				last_key = key;
294
			}
295
		}
296
		logindex = ftell(fLog);
297
    }
298
 
299
    // Remove keys
300
    for (key = last_key; key != NULL; 
301
	key = key->previous) {
302
		if (key != last_key)
303
			free(last_key);
304
		fseek(fLog, key->index, SEEK_SET);
305
		registry_delete_key();
306
		last_key = key;
307
    }
308
    free(last_key);
309
 
310
    fseek(fLog, logindex, SEEK_SET);
311
	GetLine();
312
    return TRUE;
313
}
314
 
315
 
316
 
317
void
318
registry_unquote(char *line)
319
{
320
char *s, *d;
321
int value;
322
    s = d = line;
323
    while (*s) {
324
	if (*s != '\\') {
325
	    *d++ = *s;
326
	}
327
	else {
328
	    s++;
329
	    if (*s == '\\')
330
		*d++ = *s;
331
	    else {
332
		value = 0;
333
		if (*s) {
334
		    value = *s++ - '0';
335
		}
336
		if (*s) {
337
		    value <<= 3;
338
		    value += *s++ - '0';
339
		}
340
		if (*s) {
341
		    value <<= 3;
342
		    value += *s - '0';
343
		}
344
		*d++ = (char)value;
345
	    }
346
	}
347
	s++;
348
    }
349
    *d = '\0';
350
}
351
 
352
BOOL
353
registry_import()
354
{
355
	HKEY hkey = HKEY_CLASSES_ROOT;
356
	HKEY hrkey;
357
	char *rkey, *skey;
358
	char *value;
359
	char *name;
360
	DWORD dwResult;
361
    GetLine();
362
    if (strncmp(szLine, "REGEDIT4", 8) != 0)
363
		return FALSE;
364
 
365
    while (GetLine()) {
366
		if (IsSection())
367
			break;
368
		if ((szLine[0] == '\0') || (szLine[0] == '\r') || (szLine[0] == '\n'))
369
			continue;
370
		if (szLine[0] == '[') {
371
			// key name
372
			if (hkey != HKEY_CLASSES_ROOT) {
373
				RegCloseKey(hkey);
374
				hkey = HKEY_CLASSES_ROOT;
375
			}
376
			rkey = strtok(szLine+1, "\\]\n\r");
377
			if (rkey == (char *)NULL)
378
				return FALSE;
379
			skey = strtok(NULL, "]\n\r");
380
			if (strcmp(rkey, "HKEY_CLASSES_ROOT")==0)
381
				hrkey = HKEY_CLASSES_ROOT;
382
			else if (strcmp(rkey, "HKEY_CURRENT_USER")==0)
383
				hrkey = HKEY_CURRENT_USER;
384
			else if (strcmp(rkey, "HKEY_LOCAL_MACHINE")==0)
385
				hrkey = HKEY_LOCAL_MACHINE;
386
			else if (strcmp(rkey, "HKEY_USERS")==0)
387
				hrkey = HKEY_USERS;
388
			else
389
				return FALSE;
390
			if (skey == (char *)NULL)
391
				return FALSE;
392
			gs_addmess("Creating registry key\n   ");
393
			gs_addmess(rkey);
394
			gs_addmess("\\");
395
			gs_addmess("skey");
396
			gs_addmess("\n");
397
			if (RegCreateKeyEx(hrkey, skey, 0, "", 0, KEY_ALL_ACCESS, 
398
				NULL, &hkey, &dwResult)
399
				!= ERROR_SUCCESS)
400
				return FALSE;
401
		}
402
		else if (szLine[0] == '@') {
403
			// default value
404
			if (strlen(szLine) < 4)
405
				return FALSE;
406
			value = strtok(szLine+3, "\042\r\n");
407
			if (value) {
408
				registry_unquote(value);
409
				gs_addmess("Setting registry key value\n   ");
410
				gs_addmess(value);
411
				gs_addmess("\n");
412
				if (RegSetValueEx(hkey, NULL, 0, REG_SZ, 
413
					(CONST BYTE *)value, strlen(value)+1)
414
					!= ERROR_SUCCESS)
415
					return FALSE;
416
			}
417
		}
418
		else if (szLine[0] == '\042') {
419
			// named value
420
			name = strtok(szLine+1, "\042\r\n");
421
			strtok(NULL, "\042\r\n");
422
			value = strtok(NULL, "\042\r\n");
423
			registry_unquote(value);
424
			gs_addmess("Setting registry key value\n   ");
425
			gs_addmess(name);
426
			gs_addmess("=");
427
			gs_addmess(value);
428
			gs_addmess("\n");
429
			if (RegSetValueEx(hkey, name, 0, REG_SZ, (CONST BYTE *)value, strlen(value)+1)
430
				!= ERROR_SUCCESS)
431
				return FALSE;
432
		}
433
    }
434
    if (hkey != HKEY_CLASSES_ROOT)
435
		RegCloseKey(hkey);
436
    return TRUE;
437
}
438
 
439
// recursive mkdir
440
// requires a full path to be specified, so ignores root \ 
441
// apart from root \, must not contain trailing \ 
442
// Examples:
443
//  c:\          (OK, but useless)
444
//  c:\gstools   (OK)
445
//  c:\gstools\  (incorrect)
446
//  c:gstools    (incorrect)
447
//  gstools      (incorrect)
448
// The following UNC names should work,
449
// but didn't under Win3.1 because gs_chdir wouldn't accept UNC names
450
// Needs to be tested under Windows 95.
451
//  \\server\sharename\gstools    (OK)
452
//  \\server\sharename\           (OK, but useless)
453
//
454
 
455
BOOL MakeDir(char *dirname)
456
{
457
char newdir[MAXSTR];
458
char *p;
459
    if (strlen(dirname) < 3)
460
        return -1;
461
 
462
    gs_addmess("Making Directory\n  ");
463
    gs_addmess(dirname);
464
    gs_addmess("\n");
465
    if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') {
466
        // drive mapped path
467
        p = dirname+3;
468
    }
469
    else if (dirname[1]=='\\' && dirname[1]=='\\') {
470
        // UNC path
471
        p = strchr(dirname+2, '\\');    // skip servername
472
        if (p == NULL)
473
            return -1;
474
        p++;
475
        p = strchr(p, '\\');            // skip sharename
476
        if (p == NULL)
477
            return -1;
478
    }
479
    else {
480
        // not full path so error
481
        return -1;
482
    }
483
 
484
    while (1) {
485
        strncpy(newdir, dirname, (int)(p-dirname));
486
        newdir[(int)(p-dirname)] = '\0';
487
        if (chdir(newdir)) {
488
            if (mkdir(newdir))
489
                return -1;
490
        }
491
        p++;
492
        if (p >= dirname + strlen(dirname))
493
            break;              // all done
494
        p = strchr(p, '\\');
495
        if (p == NULL)
496
            p = dirname + strlen(dirname);
497
    }
498
 
499
    return SetCurrentDirectory(dirname);
500
}
501
 
502
 
503
BOOL shell_new(void)
504
{
505
 
506
	char *p, *q;
507
	char group[MAXSTR];
508
	// remove shell items added by Ghostscript
509
	// We can only delete one group with this code
510
	group[0] = '\0';
511
	while (GetLine()) {
512
		if (IsSection()) {
513
			if (strlen(group) != 0) {
514
				gs_addmess("Removing shell folder\n  ");
515
				gs_addmess(group);
516
				gs_addmess("\n");
517
				RemoveDirectory(group);
518
			}
519
			return TRUE;
520
		}
521
		p = strtok(szLine, "=");
522
		q = strtok(NULL, "");
523
		if (p == NULL) {
524
			continue;
525
		}
526
		else if (strcmp(p, "Group")==0) {
527
			if (q)
528
				strncpy(group, q, sizeof(group)-1);
529
			// defer this until we have remove contents
530
		}
531
		else if (strcmp(p, "Name") == 0) {
532
			if (q) {
533
				gs_addmess("Removing shell link\n  ");
534
				gs_addmess(q);
535
				gs_addmess("\n");
536
				DeleteFile(q);
537
			}
538
		}
539
	}
540
 
541
	return TRUE;
542
}
543
 
544
 
545
BOOL CreateShellLink(LPCSTR name, LPCSTR description, LPCSTR program, 
546
	LPCSTR arguments, LPCSTR directory, LPCSTR icon, int nIconIndex)
547
{
548
	HRESULT hres;    
549
	IShellLink* psl;
550
 
551
	// Ensure string is UNICODE.
552
	WCHAR wsz[MAX_PATH];
553
	MultiByteToWideChar(CP_ACP, 0, name, -1, wsz, MAX_PATH);
554
 
555
	// Save new shell link
556
 
557
	// Get a pointer to the IShellLink interface.
558
	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
559
		IID_IShellLink, (void **)&psl);
560
	if (SUCCEEDED(hres))    {
561
		IPersistFile* ppf;
562
		// Query IShellLink for the IPersistFile interface for 
563
		// saving the shell link in persistent storage.
564
		hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
565
		if (SUCCEEDED(hres)) {            
566
			gs_addmess("Adding shell link\n  ");
567
			gs_addmess(name);
568
			gs_addmess("\n");
569
 
570
			// Set the path to the shell link target.
571
			hres = psl->SetPath(program);         
572
			if (!SUCCEEDED(hres)) {
573
				gs_addmess("SetPath failed!");
574
				gError = TRUE;
575
			}
576
			// Set the description of the shell link.
577
			hres = psl->SetDescription(description);         
578
			if (!SUCCEEDED(hres)) {
579
				gs_addmess("SetDescription failed!");
580
				gError = TRUE;
581
			}
582
			if ((arguments != (LPCSTR)NULL) && *arguments) {
583
				// Set the arguments of the shell link target.
584
				hres = psl->SetArguments(arguments);         
585
				if (!SUCCEEDED(hres)) {
586
					gs_addmess("SetArguments failed!");
587
					gError = TRUE;
588
				}
589
			}
590
			if ((directory != (LPCSTR)NULL) && *directory) {
591
				// Set the arguments of the shell link target.
592
				hres = psl->SetWorkingDirectory(directory);         
593
				if (!SUCCEEDED(hres)) {
594
					gs_addmess("SetWorkingDirectory failed!");
595
					gError = TRUE;
596
				}
597
			}
598
			if ((icon != (LPCSTR)NULL) && *icon) {
599
				// Set the arguments of the shell link target.
600
				hres = psl->SetIconLocation(icon, nIconIndex);         
601
				if (!SUCCEEDED(hres)) {
602
					gs_addmess("SetIconLocation failed!");
603
					gError = TRUE;
604
				}
605
			}
606
 
607
			// Save the link via the IPersistFile::Save method.
608
			hres = ppf->Save(wsz, TRUE);    
609
			// Release pointer to IPersistFile.         
610
			ppf->Release();
611
		}
612
		// Release pointer to IShellLink.       
613
		psl->Release();    
614
	}
615
 
616
	return (hres == 0);
617
}
618
 
619
 
620
 
621
BOOL shell_old(void)
622
{
623
	// Add shell items removed by Ghostscript
624
	char *p, *q;
625
	char name[MAXSTR];
626
	char description[MAXSTR];
627
	char program[MAXSTR];
628
	char arguments[MAXSTR];
629
	char directory[MAXSTR];
630
	char icon[MAXSTR];
631
	int nIconIndex;
632
	// Remove shell items added by Ghostscript
633
	name[0] = description[0] = program[0] = arguments[0] 
634
		= directory[0] = icon[0] = '\0';
635
	nIconIndex = 0;
636
 
637
	while (GetLine()) {
638
		if (IsSection())
639
			return TRUE;
640
		p = strtok(szLine, "=");
641
		q = strtok(NULL, "");
642
		if (strlen(szLine) == 0) {
643
			if (name[0] != '\0') {
644
				// add start menu item
645
				CreateShellLink(name, description, program, arguments, 
646
					directory, icon, nIconIndex);
647
			}
648
			name[0] = description[0] = program[0] = arguments[0] 
649
				= directory[0] = icon[0] = '\0';
650
			nIconIndex = 0;
651
			continue;
652
		}
653
		else if (p == (char *)NULL) {
654
			continue;
655
		}
656
		else if (strcmp(p, "Group")==0) {
657
			MakeDir(q);
658
		}
659
		else if (strcmp(p, "Name") == 0)
660
			strncpy(name, q, sizeof(name)-1);
661
		else if (strcmp(p, "Description") == 0)
662
			strncpy(description, q, sizeof(description)-1);
663
		else if (strcmp(p, "Program") == 0)
664
			strncpy(program, q, sizeof(program)-1);
665
		else if (strcmp(p, "Arguments") == 0)
666
			strncpy(arguments, q, sizeof(arguments)-1);
667
		else if (strcmp(p, "Directory") == 0)
668
			strncpy(directory, q, sizeof(directory)-1);
669
		else if (strcmp(p, "IconLocation") == 0)
670
			strncpy(icon, q, sizeof(icon)-1);
671
		else if (strcmp(p, "IconIndex") == 0)
672
			nIconIndex = atoi(q);
673
	}
674
 
675
	return TRUE;
676
}
677
 
678
 
679
 
680
#ifdef __BORLANDC__
681
#pragma argsused
682
#endif
683
DLGRETURN CALLBACK _export
684
RemoveDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
685
{
686
  switch(message) {
687
    case WM_INITDIALOG:
688
	    SetWindowText(hwnd, szTitle);
689
	    return TRUE;
690
	case WM_COMMAND:
691
	    switch(LOWORD(wParam)) {
692
		case IDC_DONE:
693
		    // delete registry entries for uninstall
694
			if (is_win4) {
695
				HKEY hkey;
696
				if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
697
					UNINSTALLKEY, 0, KEY_ALL_ACCESS, &hkey) 
698
					== ERROR_SUCCESS) {
699
					RegDeleteKey(hkey, szTitle);
700
					RegCloseKey(hkey);
701
				}
702
			}
703
 
704
		    SetWindowText(hText1, "Uninstall successful");
705
		    SetWindowText(hText2, "");
706
		    EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
707
		    EnableWindow(GetDlgItem(hwnd, IDCANCEL), TRUE);
708
		    SetDlgItemText(hwnd, IDCANCEL, "Exit");
709
		    SetFocus(GetDlgItem(hwnd, IDCANCEL));
710
		    return TRUE;
711
		case IDOK:
712
		    // Start removal
713
		    EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
714
			EnableWindow(GetDlgItem(hwnd, IDC_PRESSOK), FALSE);
715
		    while (!bQuit) {
716
			do_message();
717
			if (!ReadSection()) {
718
			    SetWindowText(hText1, "Uninstall FAILED");
719
			    SetWindowText(hText2, "");
720
			    EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
721
			    EnableWindow(GetDlgItem(hwnd, IDCANCEL), TRUE);
722
			    SetDlgItemText(hwnd, IDCANCEL, "Exit");
723
			    SetFocus(GetDlgItem(hwnd, IDCANCEL));
724
				bQuit = TRUE;
725
			}
726
		    }
727
		    return TRUE;
728
		case IDCANCEL:
729
		    bQuit = TRUE;
730
		    DestroyWindow(hwnd);
731
		    hDlgModeless = 0;
732
		    return TRUE;
733
	    }
734
	case WM_CLOSE:
735
	    DestroyWindow(hwnd);
736
	    hDlgModeless = 0;
737
	    return TRUE;
738
    }
739
    return FALSE;
740
}
741
 
742
void
743
do_message(void)
744
{
745
MSG msg;
746
    while (hDlgModeless && PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) {
747
	if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
748
	    TranslateMessage(&msg);
749
	    DispatchMessage(&msg);
750
	}
751
    }
752
}
753
 
754
 
755
 
756
BOOL
757
init(void)
758
{
759
	DWORD version = GetVersion();
760
	char *p, *s;
761
    // get location of uninstall log from command line as argv[1]
762
    p = GetCommandLine();
763
	s = p;
764
	if (*s == '\042') {
765
		// skip over program name
766
		s++;
767
		while (*s && *s!='\042')
768
			s++;
769
		if (*s)
770
			s++;
771
	}
772
	else if (*s != ' ') {
773
		// skip over program name
774
		s++;
775
		while (*s && *s!=' ')
776
			s++;
777
		if (*s)
778
			s++;
779
	}
780
	while (*s && *s==' ')
781
		s++;
782
	if (*s == '\042')
783
		s++;
784
	strncpy(szLogFile, s, sizeof(szLogFile));
785
	s = szLogFile;
786
	while (*s) {
787
		if (*s == '\042') {
788
			*s = '\0';
789
			break;
790
		}
791
		s++;
792
	}
793
	if (strlen(szLogFile) == 0) {
794
		MessageBox(HWND_DESKTOP, "Usage: uninstgs logfile.txt", 
795
			"AFPL Ghostscript Uninstall", MB_OK);
796
		return FALSE;
797
	}
798
 
799
	// read first few lines of file to get title
800
	fLog = fopen(szLogFile, "r");
801
	if (fLog == (FILE *)NULL) {
802
		MessageBox(HWND_DESKTOP, szLogFile, "Can't find file", MB_OK);
803
		return FALSE;
804
	}
805
	GetLine();
806
	if (!IsSection()) {
807
		MessageBox(HWND_DESKTOP, szLogFile, "Not valid uninstall log", 
808
			MB_OK);
809
		return FALSE;
810
	}
811
	GetLine();
812
	if (strcmp(szLine, "UninstallName") != 0) {
813
		MessageBox(HWND_DESKTOP, szLogFile, "Not valid uninstall log", 
814
			MB_OK);
815
		return FALSE;
816
	}
817
	GetLine();
818
	strcpy(szTitle, szLine);
819
 
820
	NextSection();
821
 
822
	if (LOBYTE(LOWORD(version)) >= 4)
823
		is_win4 = TRUE;
824
	return TRUE;
825
}
826
 
827
#ifdef __BORLANDC__
828
#pragma argsused
829
#endif
830
int PASCAL 
831
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
832
{
833
MSG msg;
834
 
835
    phInstance = hInstance;
836
    if (!init())
837
	return 1;
838
 
839
 
840
    CoInitialize(NULL);
841
 
842
    hDlgModeless = CreateDialogParam(hInstance, 
843
	    MAKEINTRESOURCE(IDD_UNSET),
844
	    HWND_DESKTOP, RemoveDlgProc, (LPARAM)NULL);
845
    hText1 = GetDlgItem(hDlgModeless, IDC_T1);
846
    hText2 = GetDlgItem(hDlgModeless, IDC_T2);
847
 
848
    SetWindowPos(hDlgModeless, HWND_TOP, 0, 0, 0, 0, 
849
	SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
850
 
851
    while (hDlgModeless && GetMessage(&msg, (HWND)NULL, 0, 0)) {
852
	if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
853
	    TranslateMessage(&msg);
854
	    DispatchMessage(&msg);
855
	}
856
    }
857
 
858
	if (fLog)
859
		fclose(fLog);
860
 
861
	CoUninitialize();
862
 
863
    return 0;
864
}
865