1
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/
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.
13
* The Original Code is Mozilla Communicator client code,
14
* released March 31, 1998.
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
22
* Troy Chevalier <troy@netscape.com>
23
* Sean Su <ssu@netscape.com>
28
// stdlib.h and malloc.h are needed to build with WIN32_LEAN_AND_MEAN
41
/* Mode of Setup to run in */
47
#define PP_FILENAME_ONLY 1
48
#define PP_PATH_ONLY 2
49
#define PP_ROOT_ONLY 3
51
#define CLASS_NAME_SETUP "MozillaSetup"
52
#define CLASS_NAME_SETUP_DLG "MozillaSetupDlg"
54
char szTitle[MAX_BUF];
55
char szCmdLineToSetup[MAX_BUF];
56
BOOL gbUncompressOnly;
59
char gszWizTempDir[20] = "ns_temp";
60
char gszFileToUncompress[MAX_BUF];
61
BOOL gbAllowMultipleInstalls = FALSE;
63
/////////////////////////////////////////////////////////////////////////////
64
// Global Declarations
66
static DWORD nTotalBytes = 0; // sum of all the FILE resources
68
struct ExtractFilesDlgInfo {
70
int nMaxBars; // maximum number of bars that can be displayed
71
int nBars; // current number of bars to display
74
/////////////////////////////////////////////////////////////////////////////
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
81
GetFullTempPathName(LPCTSTR lpszFileName, DWORD dwBufferLength, LPTSTR lpszBuffer)
85
dwLen = GetTempPath(dwBufferLength, lpszBuffer);
86
if (lpszBuffer[dwLen - 1] != '\\')
87
strcat(lpszBuffer, "\\");
88
strcat(lpszBuffer, gszWizTempDir);
90
dwLen = lstrlen(lpszBuffer);
91
if (lpszBuffer[dwLen - 1] != '\\')
92
strcat(lpszBuffer, "\\");
93
strcat(lpszBuffer, lpszFileName);
98
/* Function to remove quotes from a string */
99
void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize)
103
if(lstrlen(lpszSrc) > iDestSize)
107
lpszBegin = &lpszSrc[1];
111
lstrcpy(lpszDest, lpszBegin);
113
if(lpszDest[lstrlen(lpszDest) - 1] == '\"')
114
lpszDest[lstrlen(lpszDest) - 1] = '\0';
117
/* Function to locate the first non space character in a string,
118
* and return a pointer to it. */
119
LPSTR GetFirstNonSpace(LPSTR lpszString)
124
iStrLength = lstrlen(lpszString);
126
for(i = 0; i < iStrLength; i++)
128
if(!isspace(lpszString[i]))
129
return(&lpszString[i]);
135
/* Function to return the argument count given a command line input
137
int GetArgC(LPSTR lpszCommandLine)
147
lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
149
if(lpszBeginStr == NULL)
152
iStrLength = lstrlen(lpszBeginStr);
156
for(i = 0; i < iStrLength; i++)
158
if(lpszCommandLine[i] == '\"')
160
if(bFoundQuote == FALSE)
170
else if(bFoundQuote == FALSE)
172
if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
177
else if(isspace(lpszCommandLine[i]))
187
/* Function to return a specific argument parameter from a given command line input
189
LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize)
201
lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
205
if(lpszBeginStr == NULL)
208
lpszDestTemp = (char *)calloc(iDestSize, sizeof(char));
209
if(lpszDestTemp == NULL)
211
MessageBox(NULL, "Out of memory", NULL, MB_OK | MB_ICONEXCLAMATION);
215
iStrLength = lstrlen(lpszBeginStr);
220
for(i = 0; i < iStrLength; i++)
222
if(lpszCommandLine[i] == '\"')
224
if(bFoundQuote == FALSE)
234
else if(bFoundQuote == FALSE)
236
if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
241
else if(isspace(lpszCommandLine[i]))
247
if((iIndex == (iArgCount - 1)) &&
248
((bFoundQuote == TRUE) || (bFoundSpace == FALSE) ||
249
((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"'))))
253
lpszDestTemp[j] = lpszCommandLine[i];
258
lpszDestTemp[j] = '\0';
263
RemoveQuotes(lpszDestTemp, lpszDest, iDestSize);
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)
274
if(szInput[strlen(szInput) - 1] != '\\')
276
if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
278
lstrcat(szInput, "\\");
284
HRESULT CreateDirectoriesAll(char* szPath)
287
int iLen = lstrlen(szPath);
288
char szCreatePath[MAX_BUF];
291
ZeroMemory(szCreatePath, MAX_BUF);
292
memcpy(szCreatePath, szPath, iLen);
293
for(i = 0; i < iLen; i++)
296
((i != 0) && ((szPath[i] == '\\') || (szPath[i] == '/'))) &&
297
(!((szPath[0] == '\\') && (i == 1)) && !((szPath[1] == ':') && (i == 2))))
299
szCreatePath[i] = '\0';
300
hrResult = CreateDirectory(szCreatePath, NULL);
301
szCreatePath[i] = szPath[i];
307
// This function removes a directory and its subdirectories
308
HRESULT DirectoryRemove(LPSTR szDestination, BOOL bRemoveSubdirs)
311
WIN32_FIND_DATA fdFile;
312
char szDestTemp[MAX_BUF];
315
if(GetFileAttributes(szDestination) == -1)
318
if(bRemoveSubdirs == TRUE)
320
lstrcpy(szDestTemp, szDestination);
321
AppendBackSlash(szDestTemp, sizeof(szDestTemp));
322
lstrcat(szDestTemp, "*");
325
hFile = FindFirstFile(szDestTemp, &fdFile);
326
while((hFile != INVALID_HANDLE_VALUE) && (bFound == TRUE))
328
if((lstrcmpi(fdFile.cFileName, ".") != 0) && (lstrcmpi(fdFile.cFileName, "..") != 0))
330
/* create full path */
331
lstrcpy(szDestTemp, szDestination);
332
AppendBackSlash(szDestTemp, sizeof(szDestTemp));
333
lstrcat(szDestTemp, fdFile.cFileName);
335
if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
337
DirectoryRemove(szDestTemp, bRemoveSubdirs);
341
DeleteFile(szDestTemp);
345
bFound = FindNextFile(hFile, &fdFile);
351
RemoveDirectory(szDestination);
355
void RemoveBackSlash(LPSTR szInput)
362
dwInputLen = lstrlen(szInput);
364
for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--)
366
if(szInput[iCounter] == '\\')
367
szInput[iCounter] = '\0';
374
void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType)
381
if((szInput != NULL) && (szOutput != NULL))
384
dwInputLen = lstrlen(szInput);
385
ZeroMemory(szOutput, dwOutputSize);
387
if(dwInputLen < dwOutputSize)
391
case PP_FILENAME_ONLY:
392
for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
394
if(szInput[iCounter] == '\\')
396
lstrcpy(szOutput, &szInput[iCounter + 1]);
402
lstrcpy(szOutput, szInput);
407
for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
409
if(szInput[iCounter] == '\\')
411
lstrcpy(szOutput, szInput);
412
szOutput[iCounter + 1] = '\0';
418
lstrcpy(szOutput, szInput);
423
if(szInput[1] == ':')
425
szOutput[0] = szInput[0];
426
szOutput[1] = szInput[1];
427
AppendBackSlash(szOutput, dwOutputSize);
429
else if(szInput[1] == '\\')
431
int iFoundBackSlash = 0;
432
for(dwCounter = 0; dwCounter < dwInputLen; dwCounter++)
434
if(szInput[dwCounter] == '\\')
436
szOutput[dwCounter] = szInput[dwCounter];
440
if(iFoundBackSlash == 3)
444
if(iFoundBackSlash != 0)
445
AppendBackSlash(szOutput, dwOutputSize);
453
void ParseCommandLine(LPSTR lpszCmdLine)
455
char szArgVBuf[MAX_BUF];
459
*szCmdLineToSetup = '\0';
460
*gszFileToUncompress = '\0';
462
gbUncompressOnly = FALSE;
463
iArgC = GetArgC(lpszCmdLine);
467
GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
468
if((lstrcmpi(szArgVBuf, "-ms") == 0) || (lstrcmpi(szArgVBuf, "/ms") == 0))
472
else if((lstrcmpi(szArgVBuf, "-u") == 0) || (lstrcmpi(szArgVBuf, "/u") == 0))
474
gbUncompressOnly = TRUE;
475
GetArgV(lpszCmdLine, i + 1, szArgVBuf, sizeof(szArgVBuf));
476
if((*szArgVBuf != '\0') && (*szArgVBuf != '-'))
478
lstrcpy(gszFileToUncompress, szArgVBuf);
479
++i; // found filename to uncompress, update 'i' for the next iteration
482
else if((lstrcmpi(szArgVBuf, "-mmi") == 0) || (lstrcmpi(szArgVBuf, "/mmi") == 0))
484
gbAllowMultipleInstalls = TRUE;
490
lstrcpy(szCmdLineToSetup, " ");
491
lstrcat(szCmdLineToSetup, lpszCmdLine);
494
// Centers the specified window over the desktop. Assumes the window is
495
// smaller both horizontally and vertically than the desktop
497
CenterWindow(HWND hWndDlg)
502
GetWindowRect(hWndDlg, &rect);
503
iLeft = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
504
iTop = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
506
SetWindowPos(hWndDlg, NULL, iLeft, iTop, -1, -1,
507
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
510
/////////////////////////////////////////////////////////////////////////////
511
// Extract Files Dialog
513
// This routine processes windows messages that are in queue
514
void ProcessWindowsMessages()
518
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
520
TranslateMessage(&msg);
521
DispatchMessage(&msg);
525
// This routine updates the status string in the extracting dialog
527
SetStatusLine(LPCTSTR lpszStatus)
533
hWndLabel = GetDlgItem(dlgInfo.hWndDlg, IDC_STATUS);
534
SetWindowText(hWndLabel, lpszStatus);
535
UpdateWindow(hWndLabel);
539
// This routine will update the progress bar to the specified percentage
540
// (value between 0 and 100)
542
UpdateProgressBar(unsigned value)
548
// Figure out how many bars should be displayed
549
nBars = dlgInfo.nMaxBars * value / 100;
551
// Only paint if we need to display more bars
552
if (nBars > dlgInfo.nBars)
554
HWND hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE);
557
// Update the gauge state before painting
558
dlgInfo.nBars = nBars;
560
// Only invalidate the part that needs updating
561
GetClientRect(hWndGauge, &rect);
562
InvalidateRect(hWndGauge, &rect, FALSE);
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);
572
// Window proc for dialog
574
DialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
580
// Center the dialog over the desktop
581
CenterWindow(hWndDlg);
585
DestroyWindow(hWndDlg);
590
return FALSE; // didn't handle the message
593
/////////////////////////////////////////////////////////////////////////////
594
// Resource Callback Functions
597
DeleteTempFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
599
char szTmpFile[MAX_PATH];
601
// Get the path to the file in the temp directory
602
GetFullTempPathName(lpszName, sizeof(szTmpFile), szTmpFile);
605
DeleteFile(szTmpFile);
610
SizeOfResourcesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
615
hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType);
621
wsprintf(buf, "Error '%d' when loading FILE resource: %s", GetLastError(), lpszName);
622
MessageBox(NULL, buf, szTitle, MB_OK | MB_ICONEXCLAMATION);
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);
631
// Release the resource
632
FreeResource(hResInfo);
633
return TRUE; // keep enumerating
637
ExtractFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
639
char szTmpFile[MAX_PATH];
640
char szArcLstFile[MAX_PATH];
651
LoadString(hInst, IDS_STATUS_EXTRACTING, szText, sizeof(szText));
652
wsprintf(szStatus, szText, lpszName);
653
SetStatusLine(szStatus);
655
if(gbUncompressOnly == TRUE)
656
lstrcpy(szTmpFile, lpszName);
659
// Create a file in the temp directory
660
GetFullTempPathName(lpszName, sizeof(szTmpFile), szTmpFile);
661
CreateDirectoriesAll(szTmpFile);
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.
670
hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType);
671
hGlobal = LoadResource((HINSTANCE)hModule, hResInfo);
672
lpBytes = (LPBYTE)LockResource(hGlobal);
675
hFile = CreateFile(szTmpFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
677
if (hFile != INVALID_HANDLE_VALUE) {
682
GetFullTempPathName("Archive.lst", sizeof(szArcLstFile), szArcLstFile);
683
WritePrivateProfileString("Archives", lpszName, "TRUE", szArcLstFile);
685
lptr = (LPBYTE)malloc((*(LPDWORD)(lpBytes + sizeof(DWORD))) + 1);
690
LoadString(hInst, IDS_ERROR_OUT_OF_MEMORY, szBuf, sizeof(szBuf));
691
MessageBox(NULL, szBuf, NULL, MB_OK | MB_ICONEXCLAMATION);
696
dwSizeUnCmp = *(LPDWORD)(lpBytes + sizeof(DWORD));
698
// Copy the file. The first DWORD specifies the size of the file
699
dwSize = *(LPDWORD)lpBytes;
700
lpBytes += (sizeof(DWORD) * 2);
702
dwTemp = uncompress(lpBytesUnCmp, &dwSizeUnCmp, lpBytes, dwSize);
704
while (dwSizeUnCmp > 0)
706
DWORD dwBytesToWrite, dwBytesWritten;
708
ProcessWindowsMessages();
710
dwBytesToWrite = dwSizeUnCmp > 4096 ? 4096 : dwSizeUnCmp;
711
if (!WriteFile(hFile, lpBytesUnCmp, dwBytesToWrite, &dwBytesWritten, NULL))
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);
725
dwSizeUnCmp -= dwBytesWritten;
726
lpBytesUnCmp += dwBytesWritten;
728
// Update the UI to reflect the total number of bytes written
729
static DWORD nBytesWritten = 0;
731
nBytesWritten += dwBytesWritten;
732
UpdateProgressBar(nBytesWritten * 100 / nTotalBytes);
738
// Release the resource
739
FreeResource(hResInfo);
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.
748
return TRUE; // keep enumerating
751
/////////////////////////////////////////////////////////////////////////////
754
// Draws a recessed border around the gauge
756
DrawGaugeBorder(HWND hWnd)
758
HDC hDC = GetWindowDC(hWnd);
761
HPEN hShadowPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
764
GetWindowRect(hWnd, &rect);
765
cx = rect.right - rect.left;
766
cy = rect.bottom - rect.top;
768
// Draw a dark gray line segment
769
hOldPen = SelectObject(hDC, (HGDIOBJ)hShadowPen);
770
MoveToEx(hDC, 0, cy - 1, NULL);
772
LineTo(hDC, cx - 1, 0);
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);
780
SelectObject(hDC, hOldPen);
781
DeleteObject(hShadowPen);
782
ReleaseDC(hWnd, hDC);
785
// Draws the blue progress bar
787
DrawProgressBar(HWND hWnd)
790
HDC hDC = BeginPaint(hWnd, &ps);
792
HBRUSH hBlueBrush = CreateSolidBrush(RGB(0, 0, 128));
795
GetClientRect(hWnd, &rect);
796
rect.left = rect.top = BAR_MARGIN;
797
rect.bottom -= BAR_MARGIN;
798
rect.right = rect.left + BAR_WIDTH;
800
for (int i = 0; i < dlgInfo.nBars; i++) {
803
if (IntersectRect(&dest, &ps.rcPaint, &rect))
804
FillRect(hDC, &rect, hBlueBrush);
805
OffsetRect(&rect, BAR_WIDTH + BAR_SPACING, 0);
808
DeleteObject(hBlueBrush);
812
// Adjusts the width of the gauge based on the maximum number of bars
814
SizeToFitGauge(HWND hWnd)
819
// Get the window size in pixels
820
GetWindowRect(hWnd, &rect);
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;
826
SetWindowPos(hWnd, NULL, -1, -1, cx, rect.bottom - rect.top,
827
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
830
// Window proc for gauge
832
GaugeWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
839
dwStyle = GetWindowLong(hWnd, GWL_STYLE);
840
SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_BORDER);
844
// Figure out the maximum number of bars that can be displayed
845
GetClientRect(hWnd, &rect);
847
dlgInfo.nMaxBars = (rect.right - rect.left - 2 * BAR_MARGIN + BAR_SPACING) /
848
(BAR_WIDTH + BAR_SPACING);
850
// Size the gauge to exactly fit the maximum number of bars
851
SizeToFitGauge(hWnd);
855
DrawGaugeBorder(hWnd);
859
DrawProgressBar(hWnd);
863
return DefWindowProc(hWnd, msg, wParam, lParam);
866
HRESULT FileExists(LPSTR szFile)
870
if((rv = GetFileAttributes(szFile)) == -1)
880
/////////////////////////////////////////////////////////////////////////////
886
PROCESS_INFORMATION pi;
888
char szCmdLine[MAX_BUF];
889
char szSetupFile[MAX_BUF];
890
char szUninstallFile[MAX_BUF];
891
char szArcLstFile[MAX_BUF];
894
char szTempPath[MAX_BUF];
895
char szTmp[MAX_PATH];
896
char xpiDir[MAX_PATH];
897
char szFilename[MAX_BUF];
900
if(gbUncompressOnly == TRUE)
904
UpdateProgressBar(100);
905
LoadString(hInst, IDS_STATUS_LAUNCHING_SETUP, szText, sizeof(szText));
906
SetStatusLine(szText);
908
memset(&sti,0,sizeof(sti));
909
sti.cb = sizeof(STARTUPINFO);
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);
917
GetPrivateProfileString("Archives", "uninstall.exe", "", szBuf, sizeof(szBuf), szArcLstFile);
918
if((FileExists(szUninstallFile) != FALSE) && (*szBuf != '\0'))
920
lstrcpy(szCmdLine, szUninstallFile);
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))
931
GetShortPathName(xpiDir, szBuf, sizeof(szBuf));
932
lstrcat(szCmdLine, " -a ");
933
lstrcat(szCmdLine, szBuf);
935
lstrcat(szCmdLine, " -n ");
936
lstrcat(szCmdLine, szFilename);
939
if(szCmdLine != NULL)
940
lstrcat(szCmdLine, szCmdLineToSetup);
942
// Launch the installer
943
bRet = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, szTempPath, &sti, &pi);
948
CloseHandle(pi.hThread);
950
// Wait for the InstallShield UI to appear before taking down the dialog box
951
WaitForInputIdle(pi.hProcess, 3000); // wait up to 3 seconds
954
DestroyWindow(dlgInfo.hWndDlg);
957
// Wait for the installer to complete
958
WaitForSingleObject(pi.hProcess, INFINITE);
959
CloseHandle(pi.hProcess);
962
// Delete the files from the temp directory
963
EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)DeleteTempFilesProc, 0);
965
// delete archive.lst file in the temp directory
966
GetFullTempPathName("Archive.lst", sizeof(szTmp), szTmp);
968
GetFullTempPathName("xpcom.ns", sizeof(szTmp), szTmp);
969
DirectoryRemove(szTmp, TRUE);
970
DirectoryRemove(szTempPath, FALSE);
975
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
981
LoadString(hInst, IDS_TITLE, szTitle, MAX_BUF);
983
// Parse the command line
984
ParseCommandLine(lpCmdLine);
986
/* Allow multiple installer instances with the
987
provision that each instance is guaranteed
988
to have its own unique setup directory
990
if(FindWindow("NSExtracting", "Extracting...") != NULL ||
991
(hwndFW = FindWindow(CLASS_NAME_SETUP_DLG, NULL)) != NULL ||
992
(hwndFW = FindWindow(CLASS_NAME_SETUP, NULL)) != NULL)
994
if (gbAllowMultipleInstalls)
996
char szTempPath[MAX_BUF];
997
GetFullTempPathName("", MAX_BUF, szTempPath);
998
DWORD dwLen = lstrlen(gszWizTempDir);
1000
for(int i = 1; i <= 100 && (FileExists(szTempPath) != FALSE); i++)
1002
itoa(i, (gszWizTempDir + dwLen), 10);
1003
GetFullTempPathName("", MAX_BUF, szTempPath);
1006
if (FileExists(szTempPath) != FALSE)
1008
MessageBox(NULL, "Cannot create temp directory", NULL, MB_OK | MB_ICONEXCLAMATION);
1016
ShowWindow(hwndFW, SW_RESTORE);
1017
SetForegroundWindow(hwndFW);
1023
// Figure out the total size of the resources
1024
EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)SizeOfResourcesProc, 0);
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";
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;
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";
1046
if(dwMode != SILENT)
1048
// Display the dialog box
1049
dlgInfo.hWndDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_EXTRACTING), NULL, (DLGPROC)DialogProc);
1050
UpdateWindow(dlgInfo.hWndDlg);
1053
// Extract the files
1054
EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)ExtractFilesProc, 0);
1056
// Launch the install program and wait for it to finish