~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpinstall/wizard/windows/nsinstall/nsinstall.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/*
 
3
 * The contents of this file are subject to the Netscape Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/NPL/
 
7
 *
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 *
 
13
 * The Original Code is Mozilla Communicator client code,
 
14
 * released March 31, 1998.
 
15
 *
 
16
 * The Initial Developer of the Original Code is Netscape Communications
 
17
 * Corporation.  Portions created by Netscape are
 
18
 * Copyright (C) 1999 Netscape Communications Corporation. All
 
19
 * Rights Reserved.
 
20
 *
 
21
 * Contributor(s): 
 
22
 *     Troy Chevalier <troy@netscape.com>
 
23
 *     Sean Su <ssu@netscape.com>
 
24
 */
 
25
 
 
26
#include <windows.h>
 
27
 
 
28
// stdlib.h and malloc.h are needed to build with WIN32_LEAN_AND_MEAN
 
29
#include <stdlib.h>
 
30
#include <malloc.h>
 
31
#include <ctype.h>
 
32
 
 
33
#include "resource.h"
 
34
#include "zlib.h"
 
35
 
 
36
#define BAR_MARGIN    1
 
37
#define BAR_SPACING   0
 
38
#define BAR_WIDTH     6
 
39
#define MAX_BUF       4096
 
40
 
 
41
/* Mode of Setup to run in */
 
42
#define NORMAL                          0
 
43
#define SILENT                          1
 
44
#define AUTO                            2
 
45
 
 
46
/* PP: Parse Path */
 
47
#define PP_FILENAME_ONLY                1
 
48
#define PP_PATH_ONLY                    2
 
49
#define PP_ROOT_ONLY                    3
 
50
 
 
51
#define CLASS_NAME_SETUP                "MozillaSetup"
 
52
#define CLASS_NAME_SETUP_DLG            "MozillaSetupDlg"
 
53
 
 
54
char      szTitle[MAX_BUF];
 
55
char      szCmdLineToSetup[MAX_BUF];
 
56
BOOL      gbUncompressOnly;
 
57
DWORD     dwMode;
 
58
HINSTANCE hInst;
 
59
char      gszWizTempDir[20] = "ns_temp";
 
60
char      gszFileToUncompress[MAX_BUF];
 
61
BOOL      gbAllowMultipleInstalls = FALSE;
 
62
 
 
63
/////////////////////////////////////////////////////////////////////////////
 
64
// Global Declarations
 
65
 
 
66
static DWORD    nTotalBytes = 0;  // sum of all the FILE resources
 
67
 
 
68
struct ExtractFilesDlgInfo {
 
69
        HWND    hWndDlg;
 
70
        int             nMaxBars;       // maximum number of bars that can be displayed
 
71
        int             nBars;          // current number of bars to display
 
72
} dlgInfo;
 
73
 
 
74
/////////////////////////////////////////////////////////////////////////////
 
75
// Utility Functions
 
76
 
 
77
// This function is similar to GetFullPathName except instead of
 
78
// using the current drive and directory it uses the path of the
 
79
// directory designated for temporary files
 
80
static BOOL
 
81
GetFullTempPathName(LPCTSTR lpszFileName, DWORD dwBufferLength, LPTSTR lpszBuffer)
 
82
{
 
83
        DWORD   dwLen;
 
84
 
 
85
        dwLen = GetTempPath(dwBufferLength, lpszBuffer);
 
86
        if (lpszBuffer[dwLen - 1] != '\\')
 
87
                strcat(lpszBuffer, "\\");
 
88
        strcat(lpszBuffer, gszWizTempDir);
 
89
 
 
90
  dwLen = lstrlen(lpszBuffer);
 
91
        if (lpszBuffer[dwLen - 1] != '\\')
 
92
                strcat(lpszBuffer, "\\");
 
93
        strcat(lpszBuffer, lpszFileName);
 
94
 
 
95
        return TRUE;
 
96
}
 
97
 
 
98
/* Function to remove quotes from a string */
 
99
void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize)
 
100
{
 
101
  char *lpszBegin;
 
102
 
 
103
  if(lstrlen(lpszSrc) > iDestSize)
 
104
    return;
 
105
 
 
106
  if(*lpszSrc == '\"')
 
107
    lpszBegin = &lpszSrc[1];
 
108
  else
 
109
    lpszBegin = lpszSrc;
 
110
 
 
111
  lstrcpy(lpszDest, lpszBegin);
 
112
 
 
113
  if(lpszDest[lstrlen(lpszDest) - 1] == '\"')
 
114
    lpszDest[lstrlen(lpszDest) - 1] = '\0';
 
115
}
 
116
 
 
117
/* Function to locate the first non space character in a string,
 
118
 * and return a pointer to it. */
 
119
LPSTR GetFirstNonSpace(LPSTR lpszString)
 
120
{
 
121
  int   i;
 
122
  int   iStrLength;
 
123
 
 
124
  iStrLength = lstrlen(lpszString);
 
125
 
 
126
  for(i = 0; i < iStrLength; i++)
 
127
  {
 
128
    if(!isspace(lpszString[i]))
 
129
      return(&lpszString[i]);
 
130
  }
 
131
 
 
132
  return(NULL);
 
133
}
 
134
 
 
135
/* Function to return the argument count given a command line input
 
136
 * format string */
 
137
int GetArgC(LPSTR lpszCommandLine)
 
138
{
 
139
  int   i;
 
140
  int   iArgCount;
 
141
  int   iStrLength;
 
142
  LPSTR lpszBeginStr;
 
143
  BOOL  bFoundQuote;
 
144
  BOOL  bFoundSpace;
 
145
 
 
146
  iArgCount    = 0;
 
147
  lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
 
148
 
 
149
  if(lpszBeginStr == NULL)
 
150
    return(iArgCount);
 
151
 
 
152
  iStrLength   = lstrlen(lpszBeginStr);
 
153
  bFoundQuote  = FALSE;
 
154
  bFoundSpace  = TRUE;
 
155
 
 
156
  for(i = 0; i < iStrLength; i++)
 
157
  {
 
158
    if(lpszCommandLine[i] == '\"')
 
159
    {
 
160
      if(bFoundQuote == FALSE)
 
161
      {
 
162
        ++iArgCount;
 
163
        bFoundQuote = TRUE;
 
164
      }
 
165
      else
 
166
      {
 
167
        bFoundQuote = FALSE;
 
168
      }
 
169
    }
 
170
    else if(bFoundQuote == FALSE)
 
171
    {
 
172
      if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
 
173
      {
 
174
        ++iArgCount;
 
175
        bFoundSpace = FALSE;
 
176
      }
 
177
      else if(isspace(lpszCommandLine[i]))
 
178
      {
 
179
        bFoundSpace = TRUE;
 
180
      }
 
181
    }
 
182
  }
 
183
 
 
184
  return(iArgCount);
 
185
}
 
186
 
 
187
/* Function to return a specific argument parameter from a given command line input
 
188
 * format string. */
 
189
LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize)
 
190
{
 
191
  int   i;
 
192
  int   j;
 
193
  int   iArgCount;
 
194
  int   iStrLength;
 
195
  LPSTR lpszBeginStr;
 
196
  LPSTR lpszDestTemp;
 
197
  BOOL  bFoundQuote;
 
198
  BOOL  bFoundSpace;
 
199
 
 
200
  iArgCount    = 0;
 
201
  lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
 
202
 
 
203
  if(lpszDest)
 
204
    *lpszDest = '\0';
 
205
  if(lpszBeginStr == NULL)
 
206
    return(NULL);
 
207
 
 
208
  lpszDestTemp = (char *)calloc(iDestSize, sizeof(char));
 
209
  if(lpszDestTemp == NULL)
 
210
  {
 
211
    MessageBox(NULL, "Out of memory", NULL, MB_OK | MB_ICONEXCLAMATION);
 
212
    exit(1);
 
213
  }
 
214
 
 
215
  iStrLength    = lstrlen(lpszBeginStr);
 
216
  bFoundQuote   = FALSE;
 
217
  bFoundSpace   = TRUE;
 
218
  j             = 0;
 
219
 
 
220
  for(i = 0; i < iStrLength; i++)
 
221
  {
 
222
    if(lpszCommandLine[i] == '\"')
 
223
    {
 
224
      if(bFoundQuote == FALSE)
 
225
      {
 
226
        ++iArgCount;
 
227
        bFoundQuote = TRUE;
 
228
      }
 
229
      else
 
230
      {
 
231
        bFoundQuote = FALSE;
 
232
      }
 
233
    }
 
234
    else if(bFoundQuote == FALSE)
 
235
    {
 
236
      if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
 
237
      {
 
238
        ++iArgCount;
 
239
        bFoundSpace = FALSE;
 
240
      }
 
241
      else if(isspace(lpszCommandLine[i]))
 
242
      {
 
243
        bFoundSpace = TRUE;
 
244
      }
 
245
    }
 
246
 
 
247
    if((iIndex == (iArgCount - 1)) &&
 
248
      ((bFoundQuote == TRUE) || (bFoundSpace == FALSE) ||
 
249
      ((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"'))))
 
250
    {
 
251
      if(j < iDestSize)
 
252
      {
 
253
        lpszDestTemp[j] = lpszCommandLine[i];
 
254
        ++j;
 
255
      }
 
256
      else
 
257
      {
 
258
        lpszDestTemp[j] = '\0';
 
259
      }
 
260
    }
 
261
  }
 
262
 
 
263
  RemoveQuotes(lpszDestTemp, lpszDest, iDestSize);
 
264
  free(lpszDestTemp);
 
265
  return(lpszDest);
 
266
}
 
267
 
 
268
// this function appends a backslash at the end of a string,
 
269
// if one does not already exists.
 
270
void AppendBackSlash(LPSTR szInput, DWORD dwInputSize)
 
271
{
 
272
  if(szInput != NULL)
 
273
  {
 
274
    if(szInput[strlen(szInput) - 1] != '\\')
 
275
    {
 
276
      if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
 
277
      {
 
278
        lstrcat(szInput, "\\");
 
279
      }
 
280
    }
 
281
  }
 
282
}
 
283
 
 
284
HRESULT CreateDirectoriesAll(char* szPath)
 
285
{
 
286
  int     i;
 
287
  int     iLen = lstrlen(szPath);
 
288
  char    szCreatePath[MAX_BUF];
 
289
  HRESULT hrResult;
 
290
 
 
291
  ZeroMemory(szCreatePath, MAX_BUF);
 
292
  memcpy(szCreatePath, szPath, iLen);
 
293
  for(i = 0; i < iLen; i++)
 
294
  {
 
295
    if((iLen > 1) &&
 
296
      ((i != 0) && ((szPath[i] == '\\') || (szPath[i] == '/'))) &&
 
297
      (!((szPath[0] == '\\') && (i == 1)) && !((szPath[1] == ':') && (i == 2))))
 
298
    {
 
299
      szCreatePath[i] = '\0';
 
300
      hrResult        = CreateDirectory(szCreatePath, NULL);
 
301
      szCreatePath[i] = szPath[i];
 
302
    }
 
303
  }
 
304
  return(hrResult);
 
305
}
 
306
 
 
307
// This function removes a directory and its subdirectories
 
308
HRESULT DirectoryRemove(LPSTR szDestination, BOOL bRemoveSubdirs)
 
309
{
 
310
  HANDLE          hFile;
 
311
  WIN32_FIND_DATA fdFile;
 
312
  char            szDestTemp[MAX_BUF];
 
313
  BOOL            bFound;
 
314
 
 
315
  if(GetFileAttributes(szDestination) == -1)
 
316
    return(0);
 
317
 
 
318
  if(bRemoveSubdirs == TRUE)
 
319
  {
 
320
    lstrcpy(szDestTemp, szDestination);
 
321
    AppendBackSlash(szDestTemp, sizeof(szDestTemp));
 
322
    lstrcat(szDestTemp, "*");
 
323
 
 
324
    bFound = TRUE;
 
325
    hFile = FindFirstFile(szDestTemp, &fdFile);
 
326
    while((hFile != INVALID_HANDLE_VALUE) && (bFound == TRUE))
 
327
    {
 
328
      if((lstrcmpi(fdFile.cFileName, ".") != 0) && (lstrcmpi(fdFile.cFileName, "..") != 0))
 
329
      {
 
330
        /* create full path */
 
331
        lstrcpy(szDestTemp, szDestination);
 
332
        AppendBackSlash(szDestTemp, sizeof(szDestTemp));
 
333
        lstrcat(szDestTemp, fdFile.cFileName);
 
334
 
 
335
        if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 
336
        {
 
337
          DirectoryRemove(szDestTemp, bRemoveSubdirs);
 
338
        }
 
339
        else
 
340
        {
 
341
          DeleteFile(szDestTemp);
 
342
        }
 
343
      }
 
344
 
 
345
      bFound = FindNextFile(hFile, &fdFile);
 
346
    }
 
347
 
 
348
    FindClose(hFile);
 
349
  }
 
350
  
 
351
  RemoveDirectory(szDestination);
 
352
  return(0);
 
353
}
 
354
 
 
355
void RemoveBackSlash(LPSTR szInput)
 
356
{
 
357
  int   iCounter;
 
358
  DWORD dwInputLen;
 
359
 
 
360
  if(szInput != NULL)
 
361
  {
 
362
    dwInputLen = lstrlen(szInput);
 
363
 
 
364
    for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--)
 
365
    {
 
366
      if(szInput[iCounter] == '\\')
 
367
        szInput[iCounter] = '\0';
 
368
      else
 
369
        break;
 
370
    }
 
371
  }
 
372
}
 
373
 
 
374
void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType)
 
375
{
 
376
  int   iCounter;
 
377
  DWORD dwCounter;
 
378
  DWORD dwInputLen;
 
379
  BOOL  bFound;
 
380
 
 
381
  if((szInput != NULL) && (szOutput != NULL))
 
382
  {
 
383
    bFound        = TRUE;
 
384
    dwInputLen    = lstrlen(szInput);
 
385
    ZeroMemory(szOutput, dwOutputSize);
 
386
 
 
387
    if(dwInputLen < dwOutputSize)
 
388
    {
 
389
      switch(dwType)
 
390
      {
 
391
        case PP_FILENAME_ONLY:
 
392
          for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
 
393
          {
 
394
            if(szInput[iCounter] == '\\')
 
395
            {
 
396
              lstrcpy(szOutput, &szInput[iCounter + 1]);
 
397
              bFound = TRUE;
 
398
              break;
 
399
            }
 
400
          }
 
401
          if(bFound == FALSE)
 
402
            lstrcpy(szOutput, szInput);
 
403
 
 
404
          break;
 
405
 
 
406
        case PP_PATH_ONLY:
 
407
          for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
 
408
          {
 
409
            if(szInput[iCounter] == '\\')
 
410
            {
 
411
              lstrcpy(szOutput, szInput);
 
412
              szOutput[iCounter + 1] = '\0';
 
413
              bFound = TRUE;
 
414
              break;
 
415
            }
 
416
          }
 
417
          if(bFound == FALSE)
 
418
            lstrcpy(szOutput, szInput);
 
419
 
 
420
          break;
 
421
 
 
422
        case PP_ROOT_ONLY:
 
423
          if(szInput[1] == ':')
 
424
          {
 
425
            szOutput[0] = szInput[0];
 
426
            szOutput[1] = szInput[1];
 
427
            AppendBackSlash(szOutput, dwOutputSize);
 
428
          }
 
429
          else if(szInput[1] == '\\')
 
430
          {
 
431
            int iFoundBackSlash = 0;
 
432
            for(dwCounter = 0; dwCounter < dwInputLen; dwCounter++)
 
433
            {
 
434
              if(szInput[dwCounter] == '\\')
 
435
              {
 
436
                szOutput[dwCounter] = szInput[dwCounter];
 
437
                ++iFoundBackSlash;
 
438
              }
 
439
 
 
440
              if(iFoundBackSlash == 3)
 
441
                break;
 
442
            }
 
443
 
 
444
            if(iFoundBackSlash != 0)
 
445
              AppendBackSlash(szOutput, dwOutputSize);
 
446
          }
 
447
          break;
 
448
      }
 
449
    }
 
450
  }
 
451
}
 
452
 
 
453
void ParseCommandLine(LPSTR lpszCmdLine)
 
454
{
 
455
  char  szArgVBuf[MAX_BUF];
 
456
  int   i;
 
457
  int   iArgC;
 
458
 
 
459
  *szCmdLineToSetup = '\0';
 
460
  *gszFileToUncompress = '\0';
 
461
  dwMode = NORMAL;
 
462
  gbUncompressOnly = FALSE;
 
463
  iArgC  = GetArgC(lpszCmdLine);
 
464
  i      = 0;
 
465
  while(i < iArgC)
 
466
  {
 
467
    GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
 
468
    if((lstrcmpi(szArgVBuf, "-ms") == 0) || (lstrcmpi(szArgVBuf, "/ms") == 0))
 
469
    {
 
470
      dwMode = SILENT;
 
471
    }
 
472
    else if((lstrcmpi(szArgVBuf, "-u") == 0) || (lstrcmpi(szArgVBuf, "/u") == 0))
 
473
    {
 
474
      gbUncompressOnly = TRUE;
 
475
      GetArgV(lpszCmdLine, i + 1, szArgVBuf, sizeof(szArgVBuf));
 
476
      if((*szArgVBuf != '\0') && (*szArgVBuf != '-'))
 
477
      {
 
478
        lstrcpy(gszFileToUncompress, szArgVBuf);
 
479
        ++i; // found filename to uncompress, update 'i' for the next iteration
 
480
      }
 
481
    }
 
482
    else if((lstrcmpi(szArgVBuf, "-mmi") == 0) || (lstrcmpi(szArgVBuf, "/mmi") == 0))
 
483
    {
 
484
      gbAllowMultipleInstalls = TRUE;
 
485
    }
 
486
 
 
487
    ++i;
 
488
  }
 
489
 
 
490
  lstrcpy(szCmdLineToSetup, " ");
 
491
  lstrcat(szCmdLineToSetup, lpszCmdLine);
 
492
}
 
493
 
 
494
// Centers the specified window over the desktop. Assumes the window is
 
495
// smaller both horizontally and vertically than the desktop
 
496
static void
 
497
CenterWindow(HWND hWndDlg)
 
498
{
 
499
        RECT    rect;
 
500
        int             iLeft, iTop;
 
501
 
 
502
        GetWindowRect(hWndDlg, &rect);
 
503
        iLeft = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
 
504
        iTop = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
 
505
 
 
506
        SetWindowPos(hWndDlg, NULL, iLeft, iTop, -1, -1,
 
507
                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
 
508
}
 
509
 
 
510
/////////////////////////////////////////////////////////////////////////////
 
511
// Extract Files Dialog
 
512
 
 
513
// This routine processes windows messages that are in queue
 
514
void ProcessWindowsMessages()
 
515
{
 
516
  MSG msg;
 
517
 
 
518
  while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
 
519
  {
 
520
    TranslateMessage(&msg);
 
521
    DispatchMessage(&msg);
 
522
  }
 
523
}
 
524
 
 
525
// This routine updates the status string in the extracting dialog
 
526
static void
 
527
SetStatusLine(LPCTSTR lpszStatus)
 
528
{
 
529
        HWND    hWndLabel;
 
530
 
 
531
  if(dwMode != SILENT)
 
532
  {
 
533
          hWndLabel = GetDlgItem(dlgInfo.hWndDlg, IDC_STATUS);
 
534
          SetWindowText(hWndLabel, lpszStatus);
 
535
          UpdateWindow(hWndLabel);
 
536
  }
 
537
}
 
538
 
 
539
// This routine will update the progress bar to the specified percentage
 
540
// (value between 0 and 100)
 
541
static void
 
542
UpdateProgressBar(unsigned value)
 
543
{
 
544
        int     nBars;
 
545
 
 
546
  if(dwMode != SILENT)
 
547
  {
 
548
    // Figure out how many bars should be displayed
 
549
    nBars = dlgInfo.nMaxBars * value / 100;
 
550
 
 
551
    // Only paint if we need to display more bars
 
552
    if (nBars > dlgInfo.nBars)
 
553
    {
 
554
      HWND      hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE);
 
555
      RECT      rect;
 
556
 
 
557
      // Update the gauge state before painting
 
558
      dlgInfo.nBars = nBars;
 
559
 
 
560
      // Only invalidate the part that needs updating
 
561
      GetClientRect(hWndGauge, &rect);
 
562
      InvalidateRect(hWndGauge, &rect, FALSE);
 
563
    
 
564
      // Update the whole extracting dialog. We do this because we don't
 
565
      // have a message loop to process WM_PAINT messages in case the
 
566
      // extracting dialog was exposed
 
567
      UpdateWindow(dlgInfo.hWndDlg);
 
568
    }
 
569
  }
 
570
}
 
571
 
 
572
// Window proc for dialog
 
573
BOOL APIENTRY
 
574
DialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 
575
{
 
576
  if(dwMode != SILENT)
 
577
  {
 
578
    switch (msg) {
 
579
      case WM_INITDIALOG:
 
580
        // Center the dialog over the desktop
 
581
        CenterWindow(hWndDlg);
 
582
        return FALSE;
 
583
 
 
584
      case WM_COMMAND:
 
585
        DestroyWindow(hWndDlg);
 
586
        return TRUE;
 
587
    }
 
588
  }
 
589
 
 
590
        return FALSE;  // didn't handle the message
 
591
}
 
592
 
 
593
/////////////////////////////////////////////////////////////////////////////
 
594
// Resource Callback Functions
 
595
 
 
596
BOOL APIENTRY
 
597
DeleteTempFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
 
598
{
 
599
        char    szTmpFile[MAX_PATH];
 
600
 
 
601
        // Get the path to the file in the temp directory
 
602
        GetFullTempPathName(lpszName, sizeof(szTmpFile), szTmpFile);
 
603
 
 
604
        // Delete the file
 
605
        DeleteFile(szTmpFile);
 
606
        return TRUE;
 
607
}
 
608
 
 
609
BOOL APIENTRY
 
610
SizeOfResourcesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
 
611
{
 
612
        HRSRC   hResInfo;
 
613
 
 
614
        // Find the resource
 
615
        hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType);
 
616
 
 
617
#ifdef _DEBUG
 
618
        if (!hResInfo) {
 
619
                char    buf[512];
 
620
 
 
621
                wsprintf(buf, "Error '%d' when loading FILE resource: %s", GetLastError(), lpszName);
 
622
                MessageBox(NULL, buf, szTitle, MB_OK | MB_ICONEXCLAMATION);
 
623
                return FALSE;
 
624
        }
 
625
#endif
 
626
 
 
627
        // Add its size to the total size. Note that the return value is subject
 
628
        // to alignment rounding, but it's close enough for our purposes
 
629
        nTotalBytes += SizeofResource(NULL, hResInfo);
 
630
 
 
631
        // Release the resource
 
632
        FreeResource(hResInfo);
 
633
        return TRUE;  // keep enumerating
 
634
}
 
635
 
 
636
BOOL APIENTRY
 
637
ExtractFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
 
638
{
 
639
        char    szTmpFile[MAX_PATH];
 
640
        char    szArcLstFile[MAX_PATH];
 
641
        HRSRC   hResInfo;
 
642
        HGLOBAL hGlobal;
 
643
        LPBYTE  lpBytes;
 
644
        LPBYTE  lptr;
 
645
        LPBYTE  lpBytesUnCmp;
 
646
        HANDLE  hFile;
 
647
        char    szStatus[128];
 
648
        char    szText[4096];
 
649
        
 
650
        // Update the UI
 
651
        LoadString(hInst, IDS_STATUS_EXTRACTING, szText, sizeof(szText));
 
652
        wsprintf(szStatus, szText, lpszName);
 
653
        SetStatusLine(szStatus);
 
654
 
 
655
  if(gbUncompressOnly == TRUE)
 
656
    lstrcpy(szTmpFile, lpszName);
 
657
  else
 
658
  {
 
659
          // Create a file in the temp directory
 
660
          GetFullTempPathName(lpszName, sizeof(szTmpFile), szTmpFile);
 
661
    CreateDirectoriesAll(szTmpFile);
 
662
  }
 
663
 
 
664
  if((*gszFileToUncompress != '\0') && (lstrcmpi(lpszName, gszFileToUncompress) != 0))
 
665
    // We have a file to uncompress, but the one found is not the one we want,
 
666
    // so return TRUE to continue looking for the right one.
 
667
    return TRUE;
 
668
 
 
669
        // Extract the file
 
670
        hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType);
 
671
        hGlobal = LoadResource((HINSTANCE)hModule, hResInfo);
 
672
        lpBytes = (LPBYTE)LockResource(hGlobal);
 
673
 
 
674
        // Create the file
 
675
        hFile = CreateFile(szTmpFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
 
676
 
 
677
        if (hFile != INVALID_HANDLE_VALUE) {
 
678
                DWORD   dwSize;
 
679
                DWORD   dwSizeUnCmp;
 
680
    DWORD dwTemp;
 
681
 
 
682
          GetFullTempPathName("Archive.lst", sizeof(szArcLstFile), szArcLstFile);
 
683
    WritePrivateProfileString("Archives", lpszName, "TRUE", szArcLstFile);
 
684
 
 
685
    lptr = (LPBYTE)malloc((*(LPDWORD)(lpBytes + sizeof(DWORD))) + 1);
 
686
    if(!lptr)
 
687
    {
 
688
      char szBuf[512];
 
689
 
 
690
      LoadString(hInst, IDS_ERROR_OUT_OF_MEMORY, szBuf, sizeof(szBuf));
 
691
      MessageBox(NULL, szBuf, NULL, MB_OK | MB_ICONEXCLAMATION);
 
692
      return FALSE;
 
693
    }
 
694
 
 
695
    lpBytesUnCmp = lptr;
 
696
    dwSizeUnCmp  = *(LPDWORD)(lpBytes + sizeof(DWORD));
 
697
 
 
698
                // Copy the file. The first DWORD specifies the size of the file
 
699
                dwSize = *(LPDWORD)lpBytes;
 
700
                lpBytes += (sizeof(DWORD) * 2);
 
701
 
 
702
    dwTemp = uncompress(lpBytesUnCmp, &dwSizeUnCmp, lpBytes, dwSize);
 
703
 
 
704
    while (dwSizeUnCmp > 0)
 
705
    {
 
706
                        DWORD   dwBytesToWrite, dwBytesWritten;
 
707
 
 
708
      ProcessWindowsMessages();
 
709
 
 
710
                        dwBytesToWrite = dwSizeUnCmp > 4096 ? 4096 : dwSizeUnCmp;
 
711
                        if (!WriteFile(hFile, lpBytesUnCmp, dwBytesToWrite, &dwBytesWritten, NULL))
 
712
      {
 
713
                                char szBuf[512];
 
714
 
 
715
        LoadString(hInst, IDS_STATUS_EXTRACTING, szText, sizeof(szText));
 
716
                                wsprintf(szBuf, szText, szTmpFile);
 
717
                                MessageBox(NULL, szBuf, szTitle, MB_OK | MB_ICONEXCLAMATION);
 
718
                                FreeResource(hResInfo);
 
719
        if(lptr)
 
720
          free(lptr);
 
721
 
 
722
                                return FALSE;
 
723
                        }
 
724
 
 
725
                        dwSizeUnCmp -= dwBytesWritten;
 
726
                        lpBytesUnCmp += dwBytesWritten;
 
727
 
 
728
                        // Update the UI to reflect the total number of bytes written
 
729
                        static DWORD    nBytesWritten = 0;
 
730
 
 
731
                        nBytesWritten += dwBytesWritten;
 
732
                        UpdateProgressBar(nBytesWritten * 100 / nTotalBytes);
 
733
                }
 
734
 
 
735
                CloseHandle(hFile);
 
736
        }
 
737
 
 
738
        // Release the resource
 
739
        FreeResource(hResInfo);
 
740
  if(lptr)
 
741
    free(lptr);
 
742
 
 
743
  if((*gszFileToUncompress != '\0') && (lstrcmpi(lpszName, gszFileToUncompress) == 0))
 
744
    // We have a file to uncompress, and we have uncompressed it,
 
745
    // so return FALSE to stop uncompressing any other file.
 
746
    return FALSE;
 
747
 
 
748
        return TRUE;  // keep enumerating
 
749
}
 
750
 
 
751
/////////////////////////////////////////////////////////////////////////////
 
752
// Progress bar
 
753
 
 
754
// Draws a recessed border around the gauge
 
755
static void
 
756
DrawGaugeBorder(HWND hWnd)
 
757
{
 
758
        HDC             hDC = GetWindowDC(hWnd);
 
759
        RECT    rect;
 
760
        int             cx, cy;
 
761
        HPEN    hShadowPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
 
762
        HGDIOBJ hOldPen;
 
763
 
 
764
        GetWindowRect(hWnd, &rect);
 
765
        cx = rect.right - rect.left;
 
766
        cy = rect.bottom - rect.top;
 
767
 
 
768
        // Draw a dark gray line segment
 
769
        hOldPen = SelectObject(hDC, (HGDIOBJ)hShadowPen);
 
770
        MoveToEx(hDC, 0, cy - 1, NULL);
 
771
        LineTo(hDC, 0, 0);
 
772
        LineTo(hDC, cx - 1, 0);
 
773
 
 
774
        // Draw a white line segment
 
775
        SelectObject(hDC, GetStockObject(WHITE_PEN));
 
776
        MoveToEx(hDC, 0, cy - 1, NULL);
 
777
        LineTo(hDC, cx - 1, cy - 1);
 
778
        LineTo(hDC, cx - 1, 0);
 
779
 
 
780
        SelectObject(hDC, hOldPen);
 
781
        DeleteObject(hShadowPen);
 
782
        ReleaseDC(hWnd, hDC);
 
783
}
 
784
 
 
785
// Draws the blue progress bar
 
786
static void
 
787
DrawProgressBar(HWND hWnd)
 
788
{
 
789
        PAINTSTRUCT     ps;
 
790
        HDC                     hDC = BeginPaint(hWnd, &ps);
 
791
        RECT            rect;
 
792
        HBRUSH          hBlueBrush = CreateSolidBrush(RGB(0, 0, 128));
 
793
 
 
794
        // Draw the bars
 
795
        GetClientRect(hWnd, &rect);
 
796
        rect.left = rect.top = BAR_MARGIN;
 
797
        rect.bottom -= BAR_MARGIN;
 
798
        rect.right = rect.left + BAR_WIDTH;
 
799
 
 
800
        for (int i = 0; i < dlgInfo.nBars; i++) {
 
801
                RECT    dest;
 
802
 
 
803
                if (IntersectRect(&dest, &ps.rcPaint, &rect))
 
804
                        FillRect(hDC, &rect, hBlueBrush);
 
805
                OffsetRect(&rect, BAR_WIDTH + BAR_SPACING, 0);
 
806
        }
 
807
 
 
808
        DeleteObject(hBlueBrush);
 
809
        EndPaint(hWnd, &ps);
 
810
}
 
811
 
 
812
// Adjusts the width of the gauge based on the maximum number of bars
 
813
static void
 
814
SizeToFitGauge(HWND hWnd)
 
815
{
 
816
        RECT    rect;
 
817
        int             cx;
 
818
 
 
819
        // Get the window size in pixels
 
820
        GetWindowRect(hWnd, &rect);
 
821
 
 
822
        // Size the width to fit
 
823
        cx = 2 * GetSystemMetrics(SM_CXBORDER) + 2 * BAR_MARGIN +
 
824
                dlgInfo.nMaxBars * BAR_WIDTH + (dlgInfo.nMaxBars - 1) * BAR_SPACING;
 
825
 
 
826
        SetWindowPos(hWnd, NULL, -1, -1, cx, rect.bottom - rect.top,
 
827
                SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
 
828
}
 
829
 
 
830
// Window proc for gauge
 
831
LRESULT APIENTRY
 
832
GaugeWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
833
{
 
834
        DWORD   dwStyle;
 
835
        RECT    rect;
 
836
 
 
837
        switch (msg) {
 
838
                case WM_NCCREATE:
 
839
                        dwStyle = GetWindowLong(hWnd, GWL_STYLE);
 
840
                        SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_BORDER);
 
841
                        return TRUE;
 
842
 
 
843
                case WM_CREATE:
 
844
                        // Figure out the maximum number of bars that can be displayed
 
845
                        GetClientRect(hWnd, &rect);
 
846
                        dlgInfo.nBars = 0;
 
847
                        dlgInfo.nMaxBars = (rect.right - rect.left - 2 * BAR_MARGIN + BAR_SPACING) /
 
848
                                (BAR_WIDTH + BAR_SPACING);
 
849
 
 
850
                        // Size the gauge to exactly fit the maximum number of bars
 
851
                        SizeToFitGauge(hWnd);
 
852
                        return TRUE;
 
853
 
 
854
                case WM_NCPAINT:
 
855
                        DrawGaugeBorder(hWnd);
 
856
                        return TRUE;
 
857
 
 
858
                case WM_PAINT:
 
859
                        DrawProgressBar(hWnd);
 
860
                        return TRUE;
 
861
        }
 
862
 
 
863
        return DefWindowProc(hWnd, msg, wParam, lParam);
 
864
}
 
865
 
 
866
HRESULT FileExists(LPSTR szFile)
 
867
{
 
868
  DWORD rv;
 
869
 
 
870
  if((rv = GetFileAttributes(szFile)) == -1)
 
871
  {
 
872
    return(FALSE);
 
873
  }
 
874
  else
 
875
  {
 
876
    return(rv);
 
877
  }
 
878
}
 
879
 
 
880
/////////////////////////////////////////////////////////////////////////////
 
881
// WinMain
 
882
 
 
883
static BOOL
 
884
RunInstaller()
 
885
{
 
886
  PROCESS_INFORMATION pi;
 
887
  STARTUPINFO         sti;
 
888
  char                szCmdLine[MAX_BUF];
 
889
  char                szSetupFile[MAX_BUF];
 
890
  char                szUninstallFile[MAX_BUF];
 
891
  char                szArcLstFile[MAX_BUF];
 
892
  BOOL                bRet;
 
893
  char                szText[256];
 
894
  char                szTempPath[MAX_BUF];
 
895
  char                szTmp[MAX_PATH];
 
896
  char                xpiDir[MAX_PATH];
 
897
  char                szFilename[MAX_BUF];
 
898
  char                szBuf[MAX_BUF];
 
899
 
 
900
  if(gbUncompressOnly == TRUE)
 
901
    return(TRUE);
 
902
 
 
903
  // Update UI
 
904
  UpdateProgressBar(100);
 
905
  LoadString(hInst, IDS_STATUS_LAUNCHING_SETUP, szText, sizeof(szText));
 
906
  SetStatusLine(szText);
 
907
 
 
908
  memset(&sti,0,sizeof(sti));
 
909
  sti.cb = sizeof(STARTUPINFO);
 
910
 
 
911
  // Setup program is in the directory specified for temporary files
 
912
  GetFullTempPathName("", MAX_BUF, szTempPath);
 
913
        GetFullTempPathName("Archive.lst",   sizeof(szArcLstFile),    szArcLstFile);
 
914
  GetFullTempPathName("SETUP.EXE",     sizeof(szSetupFile),     szSetupFile);
 
915
  GetFullTempPathName("uninstall.exe", sizeof(szUninstallFile), szUninstallFile);
 
916
 
 
917
  GetPrivateProfileString("Archives", "uninstall.exe", "", szBuf, sizeof(szBuf), szArcLstFile);
 
918
  if((FileExists(szUninstallFile) != FALSE) && (*szBuf != '\0'))
 
919
  {
 
920
    lstrcpy(szCmdLine, szUninstallFile);
 
921
  }
 
922
  else
 
923
  {
 
924
    lstrcpy(szCmdLine, szSetupFile);
 
925
    GetModuleFileName(NULL, szFilename, sizeof(szFilename));
 
926
    ParsePath(szFilename, xpiDir, sizeof(xpiDir), PP_PATH_ONLY);
 
927
    AppendBackSlash(xpiDir, sizeof(xpiDir));
 
928
    lstrcat(xpiDir, "xpi");
 
929
    if(FileExists(xpiDir))
 
930
    {
 
931
      GetShortPathName(xpiDir, szBuf, sizeof(szBuf));
 
932
      lstrcat(szCmdLine, " -a ");
 
933
      lstrcat(szCmdLine, szBuf);
 
934
    }
 
935
    lstrcat(szCmdLine, " -n ");
 
936
    lstrcat(szCmdLine, szFilename);
 
937
  }
 
938
 
 
939
  if(szCmdLine != NULL)
 
940
    lstrcat(szCmdLine, szCmdLineToSetup);
 
941
 
 
942
  // Launch the installer
 
943
  bRet = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, szTempPath, &sti, &pi);
 
944
 
 
945
  if (!bRet)
 
946
    return FALSE;
 
947
 
 
948
  CloseHandle(pi.hThread);
 
949
 
 
950
  // Wait for the InstallShield UI to appear before taking down the dialog box
 
951
  WaitForInputIdle(pi.hProcess, 3000);  // wait up to 3 seconds
 
952
  if(dwMode != SILENT)
 
953
  {
 
954
    DestroyWindow(dlgInfo.hWndDlg);
 
955
  }
 
956
 
 
957
  // Wait for the installer to complete
 
958
  WaitForSingleObject(pi.hProcess, INFINITE);
 
959
  CloseHandle(pi.hProcess);
 
960
 
 
961
 
 
962
  // Delete the files from the temp directory
 
963
  EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)DeleteTempFilesProc, 0);
 
964
 
 
965
  // delete archive.lst file in the temp directory
 
966
  GetFullTempPathName("Archive.lst", sizeof(szTmp), szTmp);
 
967
  DeleteFile(szTmp);
 
968
  GetFullTempPathName("xpcom.ns", sizeof(szTmp), szTmp);
 
969
  DirectoryRemove(szTmp, TRUE);
 
970
  DirectoryRemove(szTempPath, FALSE);
 
971
  return TRUE;
 
972
}
 
973
 
 
974
int APIENTRY
 
975
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 
976
{
 
977
  WNDCLASS  wc;
 
978
  HWND      hwndFW;
 
979
 
 
980
        hInst = hInstance;
 
981
        LoadString(hInst, IDS_TITLE, szTitle, MAX_BUF);
 
982
 
 
983
  // Parse the command line
 
984
  ParseCommandLine(lpCmdLine);
 
985
  
 
986
  /*  Allow multiple installer instances with the 
 
987
      provision that each instance is guaranteed 
 
988
      to have its own unique setup directory 
 
989
   */
 
990
  if(FindWindow("NSExtracting", "Extracting...") != NULL ||
 
991
    (hwndFW = FindWindow(CLASS_NAME_SETUP_DLG, NULL)) != NULL ||
 
992
    (hwndFW = FindWindow(CLASS_NAME_SETUP, NULL)) != NULL)
 
993
  {
 
994
    if (gbAllowMultipleInstalls)
 
995
    {
 
996
      char szTempPath[MAX_BUF];
 
997
      GetFullTempPathName("", MAX_BUF, szTempPath);
 
998
      DWORD dwLen = lstrlen(gszWizTempDir);
 
999
 
 
1000
      for(int i = 1; i <= 100 && (FileExists(szTempPath) != FALSE); i++)
 
1001
      {
 
1002
        itoa(i, (gszWizTempDir + dwLen), 10);
 
1003
        GetFullTempPathName("", MAX_BUF, szTempPath);
 
1004
      }
 
1005
 
 
1006
      if (FileExists(szTempPath) != FALSE)
 
1007
      {
 
1008
        MessageBox(NULL, "Cannot create temp directory", NULL, MB_OK | MB_ICONEXCLAMATION);
 
1009
        exit(1);
 
1010
      }
 
1011
    }
 
1012
    else
 
1013
    {
 
1014
      if (hwndFW!=NULL)
 
1015
      {
 
1016
        ShowWindow(hwndFW, SW_RESTORE);
 
1017
        SetForegroundWindow(hwndFW);
 
1018
      }
 
1019
      return(1);
 
1020
    }
 
1021
  }
 
1022
 
 
1023
        // Figure out the total size of the resources
 
1024
        EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)SizeOfResourcesProc, 0);
 
1025
 
 
1026
  // Register a class for the gauge
 
1027
  memset(&wc, 0, sizeof(wc));
 
1028
  wc.lpfnWndProc   = (WNDPROC)GaugeWndProc;
 
1029
  wc.hInstance     = hInstance;
 
1030
  wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
 
1031
  wc.lpszClassName = "NSGauge";
 
1032
  RegisterClass(&wc);
 
1033
 
 
1034
  // Register a class for the main dialog
 
1035
  memset(&wc, 0, sizeof(wc));
 
1036
  wc.style         = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
 
1037
  wc.lpfnWndProc   = DefDlgProc;
 
1038
  wc.cbClsExtra    = 0;
 
1039
  wc.cbWndExtra    = DLGWINDOWEXTRA;
 
1040
  wc.hInstance     = hInstance;
 
1041
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
 
1042
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
 
1043
  wc.lpszClassName = "NSExtracting";
 
1044
  RegisterClass(&wc);
 
1045
 
 
1046
  if(dwMode != SILENT)
 
1047
  {
 
1048
          // Display the dialog box
 
1049
          dlgInfo.hWndDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_EXTRACTING), NULL, (DLGPROC)DialogProc);
 
1050
          UpdateWindow(dlgInfo.hWndDlg);
 
1051
  }
 
1052
 
 
1053
        // Extract the files
 
1054
        EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)ExtractFilesProc, 0);
 
1055
        
 
1056
        // Launch the install program and wait for it to finish
 
1057
        RunInstaller();
 
1058
        return 0;  
 
1059
}