~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to psi/dwinst.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
  
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
7
   This software is distributed under license and may not be copied, modified
 
8
   or distributed except as expressly authorized under the terms of that
 
9
   license.  Refer to licensing information at http://www.artifex.com/
 
10
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
 
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
 
12
*/
 
13
 
 
14
// $Id: dwinst.cpp 9043 2008-08-28 22:48:19Z giles $
 
15
 
 
16
#define STRICT
 
17
#include <windows.h>
 
18
#include <objbase.h>
 
19
#include <shlobj.h>
 
20
#include <stdio.h>
 
21
#include <io.h>
 
22
#include <direct.h>
 
23
 
 
24
#include "dwinst.h"
 
25
 
 
26
#define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
 
27
#define UNINSTALLSTRINGKEY TEXT("UninstallString")
 
28
#define DISPLAYNAMEKEY TEXT("DisplayName")
 
29
#define UNINSTALL_FILE "uninstal.txt"
 
30
char szSection[] = "////////////////////////////////\n";
 
31
 
 
32
#ifdef _MSC_VER
 
33
#define mktemp(x) _mktemp(x)
 
34
#define chdir(x) _chdir(x)
 
35
#define mkdir(x) _mkdir(x)
 
36
#endif
 
37
 
 
38
 
 
39
 
 
40
//////////////////////////////////////////////////////////////////////
 
41
// Construction/Destruction
 
42
//////////////////////////////////////////////////////////////////////
 
43
 
 
44
CInstall::CInstall()
 
45
{
 
46
        CoInitialize(NULL);
 
47
        
 
48
        m_szTargetDir[0] = '\0';
 
49
        m_szTargetGroup[0] = '\0';
 
50
        m_szPrograms[0] = '\0';
 
51
        m_szMainDir[0] = '\0';
 
52
        AddMessageFn = NULL;
 
53
        SetAllUsers(FALSE);
 
54
}
 
55
 
 
56
CInstall::~CInstall()
 
57
{
 
58
        CoUninitialize();
 
59
}
 
60
 
 
61
void CInstall::CleanUp(void)
 
62
{
 
63
        // delete all temporary files
 
64
        if (m_fLogNew)
 
65
                fclose(m_fLogNew);
 
66
        m_fLogNew = NULL;
 
67
        if (m_fLogOld)
 
68
                fclose(m_fLogOld);
 
69
        m_fLogOld = NULL;
 
70
        
 
71
        if (strlen(m_szRegistryNew))
 
72
                DeleteFile(m_szRegistryNew);
 
73
        m_szRegistryNew[0] = '\0';
 
74
        
 
75
        if (strlen(m_szRegistryOld))
 
76
                DeleteFile(m_szRegistryOld);
 
77
        m_szRegistryOld[0] = '\0';
 
78
        
 
79
        if (strlen(m_szShellNew))
 
80
                DeleteFile(m_szShellNew);
 
81
        m_szShellNew[0] = '\0';
 
82
        
 
83
        if (strlen(m_szShellOld))
 
84
                DeleteFile(m_szShellOld);
 
85
        m_szShellOld[0] = '\0';
 
86
        
 
87
        if (strlen(m_szFileNew))
 
88
                DeleteFile(m_szFileNew);
 
89
        m_szFileNew[0] = '\0';
 
90
}
 
91
 
 
92
 
 
93
void CInstall::SetMessageFunction(void(*fn)(const char *))
 
94
{
 
95
        AddMessageFn = fn;
 
96
}
 
97
 
 
98
void CInstall::AddMessage(const char *message)
 
99
{
 
100
        if (AddMessageFn)
 
101
                (*AddMessageFn)(message);
 
102
}
 
103
 
 
104
void CInstall::SetTargetDir(const char *szTargetDir)
 
105
{
 
106
        strcpy(m_szTargetDir, szTargetDir);
 
107
        // remove trailing backslash
 
108
        char *p;
 
109
        p = m_szTargetDir + strlen(m_szTargetDir) - 1;
 
110
        if (*p == '\\')
 
111
                *p = '\0';
 
112
}
 
113
 
 
114
void CInstall::SetTargetGroup(const char *szTargetGroup)
 
115
{
 
116
        strcpy(m_szTargetGroup, szTargetGroup);
 
117
        // remove trailing backslash
 
118
        char *p;
 
119
        p = m_szTargetGroup + strlen(m_szTargetGroup) - 1;
 
120
        if (*p == '\\')
 
121
                *p = '\0';
 
122
}
 
123
 
 
124
const char *CInstall::GetMainDir()
 
125
{
 
126
        return m_szMainDir;
 
127
}
 
128
 
 
129
const char *CInstall::GetUninstallName()
 
130
{
 
131
        return m_szUninstallName;
 
132
}
 
133
 
 
134
BOOL CInstall::Init(const char *szSourceDir, const char *szFileList)
 
135
{
 
136
        FILE *f;
 
137
        
 
138
        strcpy(m_szSourceDir, szSourceDir);
 
139
        // remove trailing backslash
 
140
        char *p;
 
141
        p = m_szSourceDir + strlen(m_szSourceDir) - 1;
 
142
        if (*p == '\\')
 
143
                *p = '\0';
 
144
        strcpy(m_szFileList, szFileList);
 
145
        
 
146
        m_szRegistryNew[0] = m_szRegistryOld[0] = 
 
147
                m_szShellNew[0] = m_szShellOld[0] = 
 
148
                m_szFileNew[0] = '\0';
 
149
        
 
150
        // Open list of files
 
151
        SetCurrentDirectory(m_szSourceDir);
 
152
        f = fopen(m_szFileList, "r");
 
153
        if (f == (FILE *)NULL) {
 
154
                char buf[MAXSTR];
 
155
                wsprintf(buf, "Failed to open \042%s\042\n", m_szFileList);
 
156
                AddMessage(buf);
 
157
                return FALSE;
 
158
        }
 
159
        
 
160
        // get application and directory name
 
161
        m_szUninstallName[0] = '\0';
 
162
        if (!fgets(m_szUninstallName, sizeof(m_szUninstallName), f)) {
 
163
                AddMessage("Invalid file list\n");
 
164
                fclose(f);
 
165
                return FALSE;
 
166
        }
 
167
        if (*m_szUninstallName )
 
168
                m_szUninstallName[strlen(m_szUninstallName)-1] = '\0';
 
169
        
 
170
        m_szMainDir[0] = '\0';
 
171
        if (!fgets(m_szMainDir, sizeof(m_szMainDir), f)) {
 
172
                AddMessage("Invalid file list\n");
 
173
                fclose(f);
 
174
                return FALSE;
 
175
        }
 
176
        if (*m_szMainDir )
 
177
                m_szMainDir[strlen(m_szMainDir)-1] = '\0';
 
178
        fclose(f);
 
179
        
 
180
        // Create log directory
 
181
        strcpy(m_szLogDir, m_szTargetDir);
 
182
        strcat(m_szLogDir, "\\");
 
183
        strcat(m_szLogDir, m_szMainDir);
 
184
        MakeDir(m_szLogDir);
 
185
        
 
186
        return TRUE;
 
187
}
 
188
 
 
189
 
 
190
//////////////////////////////////////////
 
191
// File installation methods
 
192
 
 
193
BOOL CInstall::InstallFiles(BOOL bNoCopy, BOOL *pbQuit)
 
194
{
 
195
        char szLogNew[MAXSTR];
 
196
        
 
197
        AddMessage(bNoCopy ? "Checking" : "Copying");
 
198
        AddMessage(" files listed in ");
 
199
        AddMessage(m_szFileList);
 
200
        AddMessage("\n");
 
201
        
 
202
        // Open list of files
 
203
        SetCurrentDirectory(m_szSourceDir);
 
204
        FILE *f = fopen(m_szFileList, "r");
 
205
        if (f == (FILE *)NULL) {
 
206
                AddMessage("Failed to open \042");
 
207
                AddMessage(m_szFileList);
 
208
                AddMessage("\042\n");
 
209
                return FALSE;
 
210
        }
 
211
        
 
212
        // skip application and directory name
 
213
        fgets(szLogNew, sizeof(szLogNew), f);
 
214
        fgets(szLogNew, sizeof(szLogNew), f);
 
215
        
 
216
        // Create target log
 
217
        
 
218
        m_fLogNew = MakeTemp(m_szFileNew);
 
219
        if (!m_fLogNew) {
 
220
                AddMessage("Failed to create FileNew temporary file\n");
 
221
                return FALSE;
 
222
        }
 
223
        
 
224
        // Copy files
 
225
        char line[MAXSTR];
 
226
        while (fgets(line, sizeof(line), f) != (char *)NULL) {
 
227
                if (*pbQuit)
 
228
                        return FALSE;
 
229
                if (*line)
 
230
                        line[strlen(line)-1] = '\0';
 
231
                if (!InstallFile(line, bNoCopy)) {
 
232
                        fclose(f);
 
233
                        fclose(m_fLogNew);
 
234
                        return FALSE;
 
235
                }
 
236
        }
 
237
        fclose(f);
 
238
        fclose(m_fLogNew);
 
239
        m_fLogNew = NULL;
 
240
        return TRUE;
 
241
}
 
242
 
 
243
 
 
244
void CInstall::AppendFileNew(const char *filename)
 
245
{
 
246
    FILE *f;
 
247
    /* mark backup file for uninstall */
 
248
    if ((f = fopen(m_szFileNew, "a")) != (FILE *)NULL) {
 
249
        fputs(filename, f);
 
250
        fputs("\n", f);
 
251
        fclose(f);
 
252
    }
 
253
}
 
254
 
 
255
// recursive mkdir
 
256
// requires a full path to be specified, so ignores root \ 
 
257
// apart from root \, must not contain trailing \
 
258
// Examples:
 
259
//  c:\          (OK, but useless)
 
260
//  c:\gstools   (OK)
 
261
//  c:\gstools\  (incorrect)
 
262
//  c:gstools    (incorrect)
 
263
//  gstools      (incorrect)
 
264
// The following UNC names should work,
 
265
// but didn't under Win3.1 because gs_chdir wouldn't accept UNC names
 
266
// Needs to be tested under Windows 95.
 
267
//  \\server\sharename\gstools    (OK)
 
268
//  \\server\sharename\           (OK, but useless)
 
269
//
 
270
 
 
271
BOOL CInstall::MakeDir(const char *dirname)
 
272
{
 
273
        char newdir[MAXSTR];
 
274
        const char *p;
 
275
    if (strlen(dirname) < 3)
 
276
        return -1;
 
277
        
 
278
    if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') {
 
279
        // drive mapped path
 
280
        p = dirname+3;
 
281
    }
 
282
    else if (dirname[1]=='\\' && dirname[1]=='\\') {
 
283
        // UNC path
 
284
        p = strchr(dirname+2, '\\');    // skip servername
 
285
        if (p == NULL)
 
286
            return -1;
 
287
        p++;
 
288
        p = strchr(p, '\\');            // skip sharename
 
289
        if (p == NULL)
 
290
            return -1;
 
291
    }
 
292
    else {
 
293
        // not full path so error
 
294
        return -1;
 
295
    }
 
296
        
 
297
    while (1) {
 
298
        strncpy(newdir, dirname, (int)(p-dirname));
 
299
        newdir[(int)(p-dirname)] = '\0';
 
300
        if (chdir(newdir)) {
 
301
            if (mkdir(newdir))
 
302
                return -1;
 
303
        }
 
304
        p++;
 
305
        if (p >= dirname + strlen(dirname))
 
306
            break;              // all done
 
307
        p = strchr(p, '\\');
 
308
        if (p == NULL)
 
309
            p = dirname + strlen(dirname);
 
310
    }
 
311
        
 
312
    return SetCurrentDirectory(dirname);
 
313
}
 
314
 
 
315
void CInstall::ResetReadonly(const char *filename)
 
316
{
 
317
    DWORD dwAttr = GetFileAttributes(filename);
 
318
    if (dwAttr & FILE_ATTRIBUTE_READONLY)
 
319
        SetFileAttributes(filename, dwAttr & (~FILE_ATTRIBUTE_READONLY));
 
320
}
 
321
 
 
322
BOOL CInstall::InstallFile(char *filename, BOOL bNoCopy)
 
323
{
 
324
        char existing_name[MAXSTR];
 
325
        char new_name[MAXSTR];
 
326
        char dir_name[MAXSTR];
 
327
        
 
328
        strcpy(existing_name, m_szSourceDir);
 
329
        strcat(existing_name, "\\");
 
330
        strcat(existing_name, filename);
 
331
        strcpy(new_name, m_szTargetDir);
 
332
        strcat(new_name, "\\");
 
333
        strcat(new_name, filename);
 
334
        strcpy(dir_name, new_name);
 
335
        char *p = strrchr(dir_name, '\\');
 
336
        if (p) {
 
337
                *p = '\0';
 
338
                if (!MakeDir(dir_name)) {
 
339
                        AddMessage("Failed to make directory ");
 
340
                        AddMessage(dir_name);
 
341
                        AddMessage("\n");
 
342
                        return FALSE;
 
343
                }
 
344
        }
 
345
        AddMessage("   ");
 
346
        AddMessage(new_name);
 
347
        AddMessage("\n");
 
348
        
 
349
        if (bNoCopy) {
 
350
                // Don't copy files.  Leave them where they are.
 
351
                // Check that all files exist
 
352
                FILE *f;
 
353
                if ((f = fopen(existing_name, "r")) == (FILE *)NULL) {
 
354
                        AddMessage("Missing file ");
 
355
                        AddMessage(existing_name);
 
356
                        AddMessage("\n");
 
357
                        return FALSE;
 
358
                }
 
359
                fclose(f);
 
360
        }
 
361
        else {
 
362
                if (!CopyFile(existing_name, new_name, FALSE)) {
 
363
                        char message[MAXSTR+MAXSTR+100];
 
364
                        wsprintf(message, "Failed to copy file %s to %s\n", 
 
365
                                existing_name, new_name);
 
366
                        AddMessage(message);
 
367
                        return FALSE;
 
368
                }
 
369
                ResetReadonly(new_name);
 
370
                fputs(new_name, m_fLogNew);
 
371
                fputs("\n", m_fLogNew);
 
372
        }
 
373
        
 
374
        
 
375
        return TRUE;
 
376
}
 
377
 
 
378
//////////////////////////////////////////
 
379
// Shell methods
 
380
 
 
381
BOOL CInstall::StartMenuBegin()
 
382
{
 
383
        m_fLogNew = MakeTemp(m_szShellNew);
 
384
        if (!m_fLogNew) {
 
385
                AddMessage("Failed to create ShellNew temporary file\n");
 
386
                return FALSE;
 
387
        }
 
388
        
 
389
        m_fLogOld = MakeTemp(m_szShellOld);
 
390
        if (!m_fLogOld) {
 
391
                AddMessage("Failed to create ShellNew temporary file\n");
 
392
                return FALSE;
 
393
        }
 
394
        
 
395
        // make folder if needed
 
396
        char szLink[MAXSTR];
 
397
        strcpy(szLink, m_szPrograms);
 
398
        strcat(szLink, "\\");
 
399
        strcat(szLink, m_szTargetGroup);
 
400
        if (chdir(szLink) != 0) {
 
401
                if (mkdir(szLink) != 0) {
 
402
                        char buf[MAXSTR+64];
 
403
                        wsprintf(buf, "Couldn't make Programs folder \042%s'042", szLink);
 
404
                        AddMessage(buf);
 
405
                        StartMenuEnd();
 
406
                        return FALSE;
 
407
                }
 
408
        }
 
409
        else {
 
410
                fprintf(m_fLogOld, "Group=%s\n\n", szLink);
 
411
        }
 
412
        fprintf(m_fLogNew, "Group=%s\n\n", szLink);
 
413
        
 
414
        return TRUE;
 
415
}
 
416
 
 
417
BOOL CInstall::StartMenuEnd()
 
418
{
 
419
        if (m_fLogOld)
 
420
                fclose(m_fLogOld);
 
421
        m_fLogOld = NULL;
 
422
        if (m_fLogNew)
 
423
                fclose(m_fLogNew);
 
424
        m_fLogNew = NULL;
 
425
        return TRUE;
 
426
}
 
427
 
 
428
BOOL CInstall::StartMenuAdd(const char *szDescription, 
 
429
                                                        const char *szProgram, const char *szArguments) 
 
430
{
 
431
        if (!CreateShellLink(szDescription, szProgram, szArguments)) {
 
432
                AddMessage("Couldn't make shell link for ");
 
433
                AddMessage(szDescription);
 
434
                AddMessage("\n");
 
435
                StartMenuEnd();
 
436
                return FALSE;
 
437
        }
 
438
        
 
439
        return TRUE;
 
440
}
 
441
 
 
442
 
 
443
BOOL CInstall::CreateShellLink(LPCSTR description, LPCSTR program, 
 
444
                                                           LPCSTR arguments, LPCSTR icon, int nIconIndex)
 
445
{
 
446
        HRESULT hres;    
 
447
        IShellLink* psl;
 
448
        CHAR szLink[MAXSTR];
 
449
        strcpy(szLink, m_szPrograms);
 
450
        strcat(szLink, "\\");
 
451
        strcat(szLink, m_szTargetGroup);
 
452
        strcat(szLink, "\\");
 
453
        strcat(szLink, description);
 
454
        strcat(szLink, ".LNK");
 
455
        AddMessage("Adding shell link\n   ");
 
456
        AddMessage(szLink);
 
457
        AddMessage("\n");
 
458
        
 
459
        // Ensure string is UNICODE.
 
460
        WCHAR wsz[MAX_PATH];
 
461
        MultiByteToWideChar(CP_ACP, 0, szLink, -1, wsz, MAX_PATH);
 
462
        
 
463
        // Save old shell link
 
464
        
 
465
        // Get a pointer to the IShellLink interface.
 
466
        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
 
467
                IID_IShellLink, (void **)&psl);
 
468
        if (SUCCEEDED(hres))    {
 
469
                IPersistFile* ppf;
 
470
                // Query IShellLink for the IPersistFile interface.
 
471
                hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
 
472
                if (SUCCEEDED(hres))       {            
 
473
                        // Load the shell link.
 
474
                        hres = ppf->Load(wsz, STGM_READ);
 
475
                        if (SUCCEEDED(hres)) {
 
476
                                // Resolve the link.
 
477
                                hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);       
 
478
                                if (SUCCEEDED(hres)) {
 
479
                                        // found it, so save details
 
480
                                        CHAR szTemp[MAXSTR];
 
481
                                        WIN32_FIND_DATA wfd;
 
482
                                        int i;
 
483
                                        
 
484
                                        
 
485
                                        fprintf(m_fLogOld, "Name=%s\n", szLink);
 
486
                                        hres = psl->GetPath(szTemp, MAXSTR, (WIN32_FIND_DATA *)&wfd, 
 
487
                                                SLGP_SHORTPATH );
 
488
                                        if (SUCCEEDED(hres))
 
489
                                                fprintf(m_fLogOld, "Path=%s\n", szTemp);
 
490
                                        hres = psl->GetDescription(szTemp, MAXSTR);
 
491
                                        if (SUCCEEDED(hres))
 
492
                                                fprintf(m_fLogOld, "Description=%s\n", szTemp);
 
493
                                        hres = psl->GetArguments(szTemp, MAXSTR);
 
494
                                        if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
 
495
                                                fprintf(m_fLogOld, "Arguments=%s\n", szTemp);
 
496
                                        hres = psl->GetWorkingDirectory(szTemp, MAXSTR);
 
497
                                        if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
 
498
                                                fprintf(m_fLogOld, "Directory=%s\n", szTemp);
 
499
                                        hres = psl->GetIconLocation(szTemp, MAXSTR, &i);
 
500
                                        if (SUCCEEDED(hres) && (szTemp[0] != '\0')) {
 
501
                                                fprintf(m_fLogOld, "IconLocation=%s\n", szTemp);
 
502
                                                fprintf(m_fLogOld, "IconIndex=%d\n", i);
 
503
                                        }
 
504
                                        fprintf(m_fLogOld, "\n");
 
505
                                }      
 
506
                        }
 
507
                        // Release pointer to IPersistFile.         
 
508
                        ppf->Release();       
 
509
                }
 
510
                // Release pointer to IShellLink.       
 
511
                psl->Release();    
 
512
        }
 
513
        
 
514
        
 
515
        // Save new shell link
 
516
        
 
517
        // Get a pointer to the IShellLink interface.
 
518
        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
 
519
                IID_IShellLink, (void **)&psl);
 
520
        if (SUCCEEDED(hres))    {
 
521
                IPersistFile* ppf;
 
522
                // Query IShellLink for the IPersistFile interface for 
 
523
                // saving the shell link in persistent storage.
 
524
                hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
 
525
                if (SUCCEEDED(hres)) {            
 
526
                        fprintf(m_fLogNew, "Name=%s\n", szLink);
 
527
                        
 
528
                        // Set the path to the shell link target.
 
529
                        hres = psl->SetPath(program);         
 
530
                        if (!SUCCEEDED(hres))
 
531
                                AddMessage("SetPath failed!");
 
532
                        fprintf(m_fLogNew, "Path=%s\n", program);
 
533
                        // Set the description of the shell link.
 
534
                        hres = psl->SetDescription(description);         
 
535
                        if (!SUCCEEDED(hres))
 
536
                                AddMessage("SetDescription failed!");
 
537
                        fprintf(m_fLogNew, "Description=%s\n", description);
 
538
                        if (arguments != (LPCSTR)NULL) {
 
539
                                // Set the arguments of the shell link target.
 
540
                                hres = psl->SetArguments(arguments);         
 
541
                                if (!SUCCEEDED(hres))
 
542
                                        AddMessage("SetArguments failed!");
 
543
                                fprintf(m_fLogNew, "Arguments=%s\n", arguments);
 
544
                        }
 
545
                        if (icon != (LPCSTR)NULL) {
 
546
                                // Set the arguments of the shell link target.
 
547
                                hres = psl->SetIconLocation(icon, nIconIndex);         
 
548
                                if (!SUCCEEDED(hres))
 
549
                                        AddMessage("SetIconLocation failed!");
 
550
                                fprintf(m_fLogNew, "IconLocation=%s\n", icon);
 
551
                                fprintf(m_fLogNew, "IconIndex=%d\n", nIconIndex);
 
552
                        }
 
553
                        
 
554
                        // Save the link via the IPersistFile::Save method.
 
555
                        hres = ppf->Save(wsz, TRUE);    
 
556
                        // Release pointer to IPersistFile.         
 
557
                        ppf->Release();
 
558
                }
 
559
                // Release pointer to IShellLink.       
 
560
                psl->Release();    
 
561
                fprintf(m_fLogNew, "\n");
 
562
        }
 
563
        
 
564
        return (hres == 0);
 
565
}
 
566
 
 
567
 
 
568
//////////////////////////////////////////
 
569
// Registry methods
 
570
 
 
571
void
 
572
reg_quote(char *d, const char *s)
 
573
{
 
574
    while (*s) {
 
575
                if (*s == '\\')
 
576
                        *d++ = '\\';
 
577
                *d++ = *s++;
 
578
    }
 
579
    *d = *s;
 
580
}
 
581
 
 
582
BOOL CInstall::UpdateRegistryBegin()
 
583
{
 
584
        const char regheader[]="REGEDIT4\n";
 
585
        m_fLogNew = MakeTemp(m_szRegistryNew);
 
586
        if (!m_fLogNew) {
 
587
                AddMessage("Failed to create RegistryNew temporary file\n");
 
588
                return FALSE;
 
589
        }
 
590
        fputs(regheader, m_fLogNew);
 
591
        
 
592
        m_fLogOld = MakeTemp(m_szRegistryOld);
 
593
        if (!m_fLogOld) {
 
594
                AddMessage("Failed to create RegistryOld temporary file\n");
 
595
                UpdateRegistryEnd();
 
596
                return FALSE;
 
597
        }
 
598
        fputs(regheader, m_fLogOld);
 
599
        
 
600
        return TRUE;
 
601
}
 
602
 
 
603
BOOL CInstall::UpdateRegistryEnd()
 
604
{
 
605
        if (m_fLogNew)
 
606
                fclose(m_fLogNew);
 
607
        m_fLogNew = NULL;
 
608
        if (m_fLogOld)
 
609
                fclose(m_fLogOld);
 
610
        m_fLogOld = NULL;
 
611
        return TRUE;
 
612
}
 
613
 
 
614
BOOL CInstall::UpdateRegistryKey(const char *product, const char *version)
 
615
{
 
616
        const char hkey_name[] = "HKEY_LOCAL_MACHINE";
 
617
        const HKEY hkey_key = HKEY_LOCAL_MACHINE;
 
618
        const char key_format[] = "\n[%s\\%s]\n";
 
619
        
 
620
        /* Create default registry entries */
 
621
        HKEY hkey;
 
622
        LONG lrc;
 
623
        char name[MAXSTR];
 
624
        
 
625
        // Create/Open application key
 
626
        sprintf(name, "SOFTWARE\\%s", product);
 
627
        lrc = RegOpenKey(hkey_key, name, &hkey);
 
628
        if (lrc == ERROR_SUCCESS) {
 
629
                fprintf(m_fLogOld, key_format, hkey_name, name);
 
630
        }
 
631
        else {
 
632
                lrc = RegCreateKey(hkey_key, name, &hkey);
 
633
                if (lrc == ERROR_SUCCESS)
 
634
                        fprintf(m_fLogNew, key_format, hkey_name, name);
 
635
        }
 
636
        if (lrc == ERROR_SUCCESS)
 
637
                RegCloseKey(hkey);
 
638
        
 
639
        // Create/Open application version key
 
640
        sprintf(name, "SOFTWARE\\%s\\%s", product, version);
 
641
        
 
642
        AddMessage("   ");
 
643
        AddMessage(hkey_name);
 
644
        AddMessage("\\");
 
645
        AddMessage(name);
 
646
        AddMessage("\n");
 
647
        lrc = RegOpenKey(hkey_key, name, &hkey);
 
648
        if (lrc == ERROR_SUCCESS)
 
649
                fprintf(m_fLogOld, key_format, hkey_name, name);
 
650
        else 
 
651
                lrc = RegCreateKey(hkey_key, name, &hkey);
 
652
        if (lrc == ERROR_SUCCESS) {
 
653
                fprintf(m_fLogNew, key_format, hkey_name, name);
 
654
        }
 
655
        else {
 
656
                UpdateRegistryEnd();
 
657
        }
 
658
        return TRUE;
 
659
}
 
660
 
 
661
BOOL CInstall::UpdateRegistryValue(const char *product, const char *version, 
 
662
                                                                   const char *name, const char *value)
 
663
{
 
664
        char appver[MAXSTR];
 
665
        BOOL flag = FALSE;
 
666
        HKEY hkey;
 
667
        // Open application/version key
 
668
        sprintf(appver, "SOFTWARE\\%s\\%s", product, version);
 
669
        
 
670
        if (RegOpenKey(HKEY_LOCAL_MACHINE, appver, &hkey)
 
671
                == ERROR_SUCCESS) {
 
672
                flag = SetRegistryValue(hkey, name, value);
 
673
                RegCloseKey(hkey);
 
674
        }
 
675
        
 
676
        return flag;
 
677
}
 
678
 
 
679
BOOL CInstall::SetRegistryValue(HKEY hkey, const char *value_name, const char *value)
 
680
{
 
681
        char buf[MAXSTR];
 
682
        char qbuf[MAXSTR];
 
683
        DWORD cbData;
 
684
        DWORD keytype;
 
685
        
 
686
        cbData = sizeof(buf);
 
687
        keytype =  REG_SZ;
 
688
        if (RegQueryValueEx(hkey, value_name, 0, &keytype, 
 
689
                (LPBYTE)buf, &cbData) == ERROR_SUCCESS) {
 
690
                reg_quote(qbuf, buf);
 
691
                fprintf(m_fLogOld, "\042%s\042=\042%s\042\n", value_name, qbuf);
 
692
        }
 
693
        reg_quote(qbuf, value);
 
694
        fprintf(m_fLogNew, "\042%s\042=\042%s\042\n", value_name, qbuf);
 
695
        AddMessage("      ");
 
696
        AddMessage(value_name);
 
697
        AddMessage("=");
 
698
        AddMessage(value);
 
699
        AddMessage("\n");
 
700
        if (RegSetValueEx(hkey, value_name, 0, REG_SZ, 
 
701
                (CONST BYTE *)value, strlen(value)+1) != ERROR_SUCCESS)
 
702
                return FALSE;
 
703
        return TRUE;
 
704
}
 
705
 
 
706
////////////////////////////////////
 
707
// Uninstall
 
708
 
 
709
 
 
710
BOOL CInstall::WriteUninstall(const char *szProg, BOOL bNoCopy)
 
711
{
 
712
        LONG rc;
 
713
        HKEY hkey;
 
714
        HKEY hsubkey;
 
715
        char buffer[MAXSTR];
 
716
        char ungsprog[MAXSTR];
 
717
        
 
718
        lstrcpy(ungsprog, m_szTargetDir);
 
719
        lstrcat(ungsprog, "\\");
 
720
        lstrcat(ungsprog, szProg);
 
721
        
 
722
        lstrcpy(buffer, m_szSourceDir);
 
723
        lstrcat(buffer, "\\");
 
724
        lstrcat(buffer, szProg);
 
725
        
 
726
        if (bNoCopy) {
 
727
                // Don't copy files.  Leave them where they are.
 
728
                // Check that all files exist
 
729
                FILE *f;
 
730
                if ((f = fopen(buffer, "r")) == (FILE *)NULL) {
 
731
                        AddMessage("Missing file ");
 
732
                        AddMessage(buffer);
 
733
                        AddMessage("\n");
 
734
                        return FALSE;
 
735
                }
 
736
                fclose(f);
 
737
        }
 
738
        else if (!CopyFile(buffer, ungsprog, FALSE)) {
 
739
                char message[MAXSTR+MAXSTR+100];
 
740
                wsprintf(message, "Failed to copy file %s to %s", buffer, ungsprog);
 
741
                AddMessage(message);
 
742
                return FALSE;
 
743
        }
 
744
        ResetReadonly(ungsprog);
 
745
        
 
746
        /* write registry entries for uninstall */
 
747
        if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINSTALLKEY, 0, 
 
748
                KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS) {
 
749
                /* failed to open key, so try to create it */
 
750
        rc = RegCreateKey(HKEY_LOCAL_MACHINE, UNINSTALLKEY, &hkey);
 
751
        }
 
752
        if (rc == ERROR_SUCCESS) {
 
753
                // Uninstall key for program
 
754
                if (RegCreateKey(hkey, m_szUninstallName, &hsubkey) == ERROR_SUCCESS) {
 
755
                        RegSetValueEx(hsubkey, DISPLAYNAMEKEY, 0, REG_SZ,
 
756
                                (CONST BYTE *)m_szUninstallName, lstrlen(m_szUninstallName)+1);
 
757
                        lstrcpy(buffer, ungsprog);
 
758
                        lstrcat(buffer, " \042");
 
759
                        lstrcat(buffer, m_szTargetDir);
 
760
                        lstrcat(buffer, "\\");
 
761
                        lstrcat(buffer, m_szMainDir);
 
762
                        lstrcat(buffer, "\\");
 
763
                        lstrcat(buffer, UNINSTALL_FILE);
 
764
                        lstrcat(buffer, "\042");
 
765
                        AddMessage("   ");
 
766
                        AddMessage(m_szUninstallName);
 
767
                        AddMessage("=");
 
768
                        AddMessage(buffer);
 
769
                        AddMessage("\n");
 
770
                        RegSetValueEx(hsubkey, UNINSTALLSTRINGKEY, 0, REG_SZ,
 
771
                                (CONST BYTE *)buffer, lstrlen(buffer)+1);
 
772
                        RegCloseKey(hsubkey);
 
773
                }
 
774
                
 
775
                RegCloseKey(hkey);
 
776
        }
 
777
        return TRUE;
 
778
}
 
779
 
 
780
 
 
781
void
 
782
CInstall::CopyFileContents(FILE *df, FILE *sf)
 
783
{
 
784
        char buf[MAXSTR];
 
785
        int count;
 
786
        while ((count = fread(buf, 1, sizeof(buf), sf)) != 0)
 
787
                fwrite(buf, 1, count, df);
 
788
}
 
789
 
 
790
FILE *CInstall::MakeTemp(char *fname)
 
791
{
 
792
        char *temp;
 
793
        if ( (temp = getenv("TEMP")) == NULL )
 
794
                strcpy(fname, m_szTargetDir);
 
795
        else
 
796
                strcpy(fname, temp);
 
797
        
 
798
        /* Prevent X's in path from being converted by mktemp. */
 
799
        for ( temp = fname; *temp; temp++ ) {
 
800
                *temp = (char)tolower(*temp);
 
801
                if (*temp == '/')
 
802
                        *temp = '\\';
 
803
        }
 
804
        if ( strlen(fname) && (fname[strlen(fname)-1] != '\\') )
 
805
                strcat(fname, "\\");
 
806
        
 
807
        strcat(fname, "gsXXXXXX");
 
808
        mktemp(fname);
 
809
        AddMessage("Creating temporary file ");
 
810
        AddMessage(fname);
 
811
        AddMessage("\n");
 
812
        return fopen(fname, "w");
 
813
}
 
814
 
 
815
BOOL CInstall::MakeLog()
 
816
{
 
817
        FILE *f, *lf;
 
818
        char szFileName[MAXSTR];
 
819
        char szLogDir[MAXSTR];
 
820
        strcpy(szLogDir, m_szTargetDir);
 
821
        strcat(szLogDir, "\\");
 
822
        strcat(szLogDir, m_szMainDir);
 
823
        strcat(szLogDir, "\\");
 
824
        
 
825
        strcpy(szFileName, szLogDir);
 
826
        strcat(szFileName, UNINSTALL_FILE);
 
827
        lf = fopen(szFileName, "w");
 
828
        if (lf == (FILE *)NULL) {
 
829
                AddMessage("Can't create uninstall log");
 
830
                CleanUp();
 
831
                return FALSE;
 
832
        }
 
833
        fputs(szSection, lf);
 
834
        fputs("UninstallName\n", lf);
 
835
        fputs(m_szUninstallName, lf);
 
836
        fputs("\n\n", lf);
 
837
        
 
838
        if (strlen(m_szRegistryNew) &&
 
839
                (f = fopen(m_szRegistryNew, "r")) != (FILE *)NULL) {
 
840
                fputs(szSection, lf);
 
841
                fputs("RegistryNew\n", lf);
 
842
                CopyFileContents(lf, f);
 
843
                fputs("\n", lf);
 
844
                fclose(f);
 
845
                DeleteFile(m_szRegistryNew);
 
846
                m_szRegistryNew[0] = '\0';
 
847
        }
 
848
        
 
849
        if (strlen(m_szRegistryOld) &&
 
850
                (f = fopen(m_szRegistryOld, "r")) != (FILE *)NULL) {
 
851
                fputs(szSection, lf);
 
852
                fputs("RegistryOld\n", lf);
 
853
                CopyFileContents(lf, f);
 
854
                fputs("\n", lf);
 
855
                fclose(f);
 
856
                DeleteFile(m_szRegistryOld);
 
857
                m_szRegistryOld[0] = '\0';
 
858
        }
 
859
        
 
860
        if (strlen(m_szShellNew) &&
 
861
                (f = fopen(m_szShellNew, "r")) != (FILE *)NULL) {
 
862
                fputs(szSection, lf);
 
863
                fputs("ShellNew\n", lf);
 
864
                CopyFileContents(lf, f);
 
865
                fputs("\n", lf);
 
866
                fclose(f);
 
867
                DeleteFile(m_szShellNew);
 
868
                m_szShellNew[0] = '\0';
 
869
        }
 
870
        
 
871
        if (strlen(m_szShellOld) &&
 
872
                (f = fopen(m_szShellOld, "r")) != (FILE *)NULL) {
 
873
                fputs(szSection, lf);
 
874
                fputs("ShellOld\n", lf);
 
875
                CopyFileContents(lf, f);
 
876
                fputs("\n", lf);
 
877
                fclose(f);
 
878
                DeleteFile(m_szShellOld);
 
879
                m_szShellOld[0] = '\0';
 
880
        }
 
881
        
 
882
        if (strlen(m_szFileNew) &&
 
883
                (f = fopen(m_szFileNew, "r")) != (FILE *)NULL) {
 
884
                fputs(szSection, lf);
 
885
                fputs("FileNew\n", lf);
 
886
                CopyFileContents(lf, f);
 
887
                fputs("\n", lf);
 
888
                fclose(f);
 
889
                DeleteFile(m_szFileNew);
 
890
                m_szFileNew[0] = '\0';
 
891
        }
 
892
        
 
893
        fputs(szSection, lf);
 
894
        fclose(lf);
 
895
        
 
896
        return TRUE;
 
897
}
 
898
 
 
899
BOOL CInstall::GetPrograms(BOOL bUseCommon, char *buf, int buflen)
 
900
{
 
901
        // Get the directory for the Program menu. This is
 
902
        // stored in the Registry under HKEY_CURRENT_USER\Software\
 
903
        // Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Programs.
 
904
        LONG rc;
 
905
        HKEY hCU;    
 
906
        DWORD dwType;    
 
907
        ULONG ulSize = buflen;
 
908
        HKEY hrkey = HKEY_CURRENT_USER;
 
909
        if (bUseCommon)
 
910
                hrkey = HKEY_LOCAL_MACHINE;
 
911
        if (RegOpenKeyEx(hrkey, 
 
912
                "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 
 
913
                0,KEY_QUERY_VALUE,      
 
914
                &hCU) == ERROR_SUCCESS)    {
 
915
                rc = RegQueryValueEx( hCU,        
 
916
                        bUseCommon ? "Common Programs" : "Programs",        
 
917
                        NULL,        
 
918
                        &dwType,
 
919
                        (unsigned char *)buf,        
 
920
                        &ulSize);      
 
921
                RegCloseKey(hCU);    
 
922
                return TRUE;
 
923
        }
 
924
        return FALSE;
 
925
        
 
926
#ifdef NOTUSED
 
927
        // This is an alternate version, but it needs 
 
928
        // Internet Explorer 4.0 with Web Integrated Desktop.
 
929
        // It does not work with the standard 
 
930
        // Windows 95, Windows NT 4.0, Internet Explorer 3.0, 
 
931
        // and Internet Explorer 4.0 without Web Integrated Desktop.
 
932
        
 
933
        HRESULT rc;
 
934
        m_szPrograms[0] = '\0';
 
935
        int nFolder = CSIDL_PROGRAMS;
 
936
        if (bUseCommon)
 
937
                nFolder = CSIDL_COMMON_PROGRAMS;
 
938
        
 
939
        rc = SHGetSpecialFolderPath(HWND_DESKTOP, m_szPrograms, 
 
940
                nFolder, FALSE);
 
941
        return (rc == NOERROR);
 
942
#endif
 
943
        
 
944
}
 
945
 
 
946
BOOL CInstall::SetAllUsers(BOOL bUseCommon)
 
947
{
 
948
        m_bUseCommon = bUseCommon;
 
949
        return GetPrograms(bUseCommon, m_szPrograms, sizeof(m_szPrograms));
 
950
}
 
951
 
 
952
 
 
953
//////////////////////////////////////////////////////////////////////