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
GetLine(void)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
IsSection(void)98 BOOL IsSection(void)
99 {
100 return (strncmp(szLine, szSection, strlen(szSection)) == 0);
101 }
102
103 BOOL
NextSection(void)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
ReadSection(void)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
dofiles(void)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
doEOF(void)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
registry_delete_key(void)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
registry_delete()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
registry_unquote(char * line)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
registry_import()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
MakeDir(char * dirname)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
shell_new(void)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
CreateShellLink(LPCSTR name,LPCSTR description,LPCSTR program,LPCSTR arguments,LPCSTR directory,LPCSTR icon,int nIconIndex)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
shell_old(void)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
RemoveDlgProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)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
do_message(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
init(void)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
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int cmdShow)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
866