mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
649 lines
17 KiB
649 lines
17 KiB
//+------------------------------------------------------------------
|
|
//
|
|
// Project: Windows NT4 DS Client Setup Wizard
|
|
//
|
|
// Purpose: Installs the Windows NT4 DS Client Files
|
|
//
|
|
// File: dscsetup.cpp
|
|
//
|
|
// History: March 1998 Zeyong Xu Created
|
|
// Jan 2000 Jeff Jones (JeffJon) Modified
|
|
// - changed to be an NT setup
|
|
//
|
|
//------------------------------------------------------------------
|
|
|
|
|
|
#include <windows.h>
|
|
#include <prsht.h>
|
|
#include <setupapi.h>
|
|
#include <tchar.h>
|
|
#include <stdlib.h>
|
|
#include "resource.h"
|
|
#include "dscsetup.h"
|
|
#include "wizard.h"
|
|
|
|
#include "doinst.h"
|
|
|
|
|
|
SInstallVariables g_sInstVar;
|
|
|
|
|
|
// DllMain Entry
|
|
BOOL APIENTRY DllMain( HINSTANCE hInstance,
|
|
DWORD ul_reason_for_call,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
switch (ul_reason_for_call)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// This is an exported function.
|
|
DWORD WINAPI DoDscSetup(LPCSTR lpCmdLine)
|
|
{
|
|
// initialize the variables of installation
|
|
InitVariables();
|
|
|
|
ParseCmdline(const_cast<PSTR>(lpCmdLine));
|
|
|
|
//
|
|
// Go through setup if we are installing with anything but
|
|
// the /a flag
|
|
//
|
|
if (g_sInstVar.m_bSysDlls || g_sInstVar.m_bWabInst)
|
|
{
|
|
// create objects
|
|
if(!CreateObjects())
|
|
return SETUP_ERROR;
|
|
|
|
// Launch setup wizard
|
|
if(!DSCSetupWizard())
|
|
{
|
|
TCHAR szMessage[MAX_MESSAGE + 1];
|
|
TCHAR szTitle[MAX_TITLE + 1];
|
|
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_WIZARD,
|
|
szMessage,
|
|
MAX_MESSAGE);
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_TITLE,
|
|
szTitle,
|
|
MAX_TITLE);
|
|
|
|
// display a error message - Failure to load Setup Wizard
|
|
MessageBox(NULL,
|
|
szMessage, // address of text in message box
|
|
szTitle, // address of title of message box
|
|
MB_OK | MB_TOPMOST | MB_ICONERROR); // style of message box
|
|
|
|
g_sInstVar.m_nSetupResult = SETUP_ERROR;
|
|
}
|
|
|
|
// destroy objects
|
|
DestroyObjects();
|
|
|
|
if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS &&
|
|
!g_sInstVar.m_bQuietMode
|
|
#ifdef MERRILL_LYNCH
|
|
&& !g_sInstVar.m_bNoReboot
|
|
#endif
|
|
)
|
|
{
|
|
// prompt reboot
|
|
SetupPromptReboot(NULL, // optional, handle to a file queue
|
|
NULL, // parent window of this dialog box
|
|
FALSE); // optional, do not prompt user);
|
|
}
|
|
else if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS &&
|
|
g_sInstVar.m_bQuietMode
|
|
#ifdef MERRILL_LYNCH
|
|
&& !g_sInstVar.m_bNoReboot
|
|
#endif
|
|
)
|
|
{
|
|
HANDLE htoken = INVALID_HANDLE_VALUE;
|
|
|
|
do
|
|
{
|
|
// twiddle our process privileges to enable SE_SHUTDOWN_NAME
|
|
HRESULT hr = OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES,
|
|
&htoken);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
LUID luid;
|
|
memset(&luid, 0, sizeof(luid));
|
|
hr = LookupPrivilegeValue(0, SE_SHUTDOWN_NAME, &luid);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
TOKEN_PRIVILEGES privs;
|
|
memset(&privs, 0, sizeof(privs));
|
|
privs.PrivilegeCount = 1;
|
|
privs.Privileges[0].Luid = luid;
|
|
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
hr = AdjustTokenPrivileges(htoken, 0, &privs, 0, 0, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
hr = ExitWindowsEx(EWX_REBOOT, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
while (0);
|
|
|
|
if (htoken != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(htoken);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Setup was run with the /a flag. This means we
|
|
// don't want to show the UI and let the adsix86.inf
|
|
// handle the install for us
|
|
//
|
|
if (!LaunchProcess(STR_INSTALL_ADSIWREMOVE))
|
|
{
|
|
g_sInstVar.m_nSetupResult = SETUP_ERROR;
|
|
}
|
|
}
|
|
return g_sInstVar.m_nSetupResult;
|
|
}
|
|
|
|
|
|
VOID ParseCmdline(LPSTR lpCmdLine)
|
|
{
|
|
PCTSTR ptszTok = _tcstok(lpCmdLine, _T(" "));
|
|
do
|
|
{
|
|
if (ptszTok != NULL)
|
|
{
|
|
if (_tcsicmp(ptszTok, _T("/q")) == 0)
|
|
{
|
|
g_sInstVar.m_bQuietMode = TRUE;
|
|
}
|
|
|
|
if (_tcsicmp(ptszTok, _T("/a")) == 0)
|
|
{
|
|
g_sInstVar.m_bWabInst = FALSE;
|
|
g_sInstVar.m_bSysDlls = FALSE;
|
|
}
|
|
|
|
if (_tcsicmp(ptszTok, _T("/d")) == 0)
|
|
{
|
|
g_sInstVar.m_bWabInst = FALSE;
|
|
}
|
|
#ifdef MERRILL_LYNCH
|
|
if (_tcsicmp(ptszTok, _T("/n")) == 0)
|
|
{
|
|
g_sInstVar.m_bNoReboot = TRUE;
|
|
}
|
|
#endif
|
|
}
|
|
ptszTok = _tcstok(NULL, _T(" "));
|
|
} while (ptszTok != NULL);
|
|
}
|
|
|
|
|
|
// initialize the variables of installation
|
|
VOID InitVariables()
|
|
{
|
|
g_sInstVar.m_hInstance = GetModuleHandle(STR_DLL_NAME);
|
|
g_sInstVar.m_hInstallThread = NULL;
|
|
g_sInstVar.m_uTimerID = 0;
|
|
g_sInstVar.m_hBigBoldFont = NULL;
|
|
g_sInstVar.m_hProgress = NULL;
|
|
g_sInstVar.m_hFileNameItem = NULL;
|
|
|
|
g_sInstVar.m_bDCOMInstalled = FALSE;
|
|
|
|
g_sInstVar.m_bQuietMode = FALSE;
|
|
g_sInstVar.m_bWabInst = TRUE;
|
|
g_sInstVar.m_bSysDlls = TRUE;
|
|
#ifdef MERRILL_LYNCH
|
|
g_sInstVar.m_bNoReboot = FALSE;
|
|
#endif
|
|
g_sInstVar.m_nSetupResult = SETUP_SUCCESS;
|
|
|
|
// get source path
|
|
GetModuleFileName(g_sInstVar.m_hInstance,
|
|
g_sInstVar.m_szSourcePath,
|
|
MAX_PATH);
|
|
*(_tcsrchr(g_sInstVar.m_szSourcePath, CHAR_BACKSLASH) + 1) = TEXT('\0'); // Strip setup.exe off path
|
|
}
|
|
|
|
// start setup wizard
|
|
BOOL DSCSetupWizard()
|
|
{
|
|
PROPSHEETHEADER psh;
|
|
PROPSHEETPAGE psPage[SIZE_WIZARD_PAGE];
|
|
int i = 0;
|
|
|
|
//
|
|
// Setup the Welcome page
|
|
//
|
|
i=0;
|
|
ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
|
|
psPage[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
psPage[i].dwFlags = PSP_USETITLE | PSP_HIDEHEADER;
|
|
psPage[i].hInstance = g_sInstVar.m_hInstance;
|
|
psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_WELCOME);
|
|
psPage[i].pfnDlgProc = (DLGPROC) WelcomeDialogProc;
|
|
psPage[i].lParam = (LPARAM) 0;
|
|
psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
|
|
|
|
/* ntbug#337931: remove license page
|
|
//
|
|
// Setup the License Page
|
|
//
|
|
i++;
|
|
ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
|
|
psPage[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
psPage[i].dwFlags = PSP_USETITLE |
|
|
PSP_USEHEADERTITLE |
|
|
PSP_USEHEADERSUBTITLE;
|
|
psPage[i].hInstance = g_sInstVar.m_hInstance;
|
|
psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_LICENSE);
|
|
psPage[i].pfnDlgProc = (DLGPROC) LicenseDialogProc;
|
|
psPage[i].lParam = (LPARAM) 0;
|
|
psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
|
|
psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_LICENSE);
|
|
psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_LICENSE);
|
|
*/
|
|
//
|
|
// Setup the Select Page
|
|
//
|
|
i++;
|
|
ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
|
|
psPage[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
psPage[i].dwFlags = PSP_USETITLE |
|
|
PSP_USEHEADERTITLE |
|
|
PSP_USEHEADERSUBTITLE;
|
|
psPage[i].hInstance = g_sInstVar.m_hInstance;
|
|
psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_CONFIRM);
|
|
psPage[i].pfnDlgProc = (DLGPROC) ConfirmDialogProc;
|
|
psPage[i].lParam = (LPARAM) 0;
|
|
psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
|
|
psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_CONFIRM);
|
|
psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_CONFIRM);
|
|
|
|
//
|
|
// Setup the Confirm Page
|
|
//
|
|
i++;
|
|
ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
|
|
psPage[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
psPage[i].dwFlags = PSP_USETITLE |
|
|
PSP_USEHEADERTITLE |
|
|
PSP_USEHEADERSUBTITLE;
|
|
psPage[i].hInstance = g_sInstVar.m_hInstance;
|
|
psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_INSTALL);
|
|
psPage[i].pfnDlgProc = (DLGPROC) InstallDialogProc;
|
|
psPage[i].lParam = (LPARAM) 0;
|
|
psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
|
|
psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_INSTALL);
|
|
psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_INSTALL);
|
|
|
|
//
|
|
// Setup the Completion page
|
|
//
|
|
i++;
|
|
ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
|
|
psPage[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
psPage[i].dwFlags = PSP_USETITLE | PSP_HIDEHEADER;
|
|
psPage[i].hInstance = g_sInstVar.m_hInstance;
|
|
psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_COMPLETION);
|
|
psPage[i].pfnDlgProc = (DLGPROC) CompletionDialogProc;
|
|
psPage[i].lParam = (LPARAM) 0;
|
|
psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
|
|
|
|
//
|
|
// Setup the wizard
|
|
//
|
|
ZeroMemory(&psh,sizeof(PROPSHEETHEADER));
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
// Windows 98 with 16 color display mode crashes when PSH_STRETCHWATERMARK flag is on.
|
|
psh.dwFlags = PSH_USEICONID |
|
|
PSH_PROPSHEETPAGE |
|
|
PSH_WIZARD97 |
|
|
PSH_WATERMARK |
|
|
PSH_HEADER; // | PSH_STRETCHWATERMARK;
|
|
psh.pszIcon = MAKEINTRESOURCE(IDI_ICON_APP);
|
|
psh.hInstance = g_sInstVar.m_hInstance;
|
|
psh.pszCaption = MAKEINTRESOURCE(IDS_WIZARD_TITLE);;
|
|
psh.nStartPage = 0;
|
|
psh.nPages = SIZE_WIZARD_PAGE;
|
|
psh.ppsp = (LPCPROPSHEETPAGE) &psPage;
|
|
|
|
//
|
|
// Run the wizard
|
|
//
|
|
if(g_sInstVar.m_bQuietMode)
|
|
{
|
|
if(!CheckDiskSpace())
|
|
return FALSE;
|
|
|
|
psh.nStartPage = 2;
|
|
}
|
|
else
|
|
psh.nStartPage = 0;
|
|
|
|
if( PropertySheet(&psh) < 0 ) // failure to load wizard
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Because SetWindowLongPtr(hWnd, DWL_MSGRESULT, IDD_COMPLETION)
|
|
// doesn't work on Win95 (when users click Cancel, the wizard can't
|
|
// be routed to the Completion page), I added the following code to
|
|
// open the Completion page
|
|
//
|
|
if(!g_sInstVar.m_bQuietMode)
|
|
{
|
|
psh.nStartPage = 3;
|
|
if( PropertySheet(&psh) < 0 ) // failure to load wizard
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// check for DCOM installed
|
|
void CheckDCOMInstalled()
|
|
{
|
|
HKEY hSubKey;
|
|
|
|
// check if IE 4.0 has been installed
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT,
|
|
STR_DCOM_REGKEY,
|
|
0,
|
|
KEY_READ,
|
|
&hSubKey) )
|
|
{
|
|
g_sInstVar.m_bDCOMInstalled = TRUE;
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
}
|
|
|
|
// gets Disk Free space
|
|
DWORD64 SetupGetDiskFreeSpace()
|
|
{
|
|
DWORD dwSectorsPerCluster;
|
|
DWORD dwBytesPerSector;
|
|
DWORD dwNumberOfFreeClusters;
|
|
DWORD dwTotalNumberOfClusters;
|
|
DWORD64 d64FreeSpace = 0;
|
|
TCHAR szPathName[MAX_PATH + 1]; // address of root path
|
|
|
|
if(GetSystemDirectory(szPathName, // address of buffer for system directory
|
|
MAX_PATH)) // size of directory buffer);
|
|
{
|
|
if ( szPathName[1] == TEXT(':'))
|
|
{
|
|
// this is a drive letter
|
|
// assume it is of for d:backslash
|
|
szPathName[3] = TEXT('\0');
|
|
|
|
//get free space, GetDiskFreeSpaceEx() don't support in older Win95
|
|
if (GetDiskFreeSpace(szPathName, // address of root path
|
|
&dwSectorsPerCluster, // address of sectors per cluster
|
|
&dwBytesPerSector, // address of bytes per sector
|
|
&dwNumberOfFreeClusters, // address of number of free clusters
|
|
&dwTotalNumberOfClusters)) // address of total number of clusters
|
|
{
|
|
// calc total size
|
|
d64FreeSpace = DWORD64(dwSectorsPerCluster)
|
|
* dwBytesPerSector
|
|
* dwNumberOfFreeClusters;
|
|
}
|
|
}
|
|
}
|
|
|
|
return d64FreeSpace;
|
|
}
|
|
|
|
// check if DSClient has been installed
|
|
BOOL CheckDSClientInstalled()
|
|
{
|
|
HKEY hSubKey;
|
|
BOOL bResult = FALSE;
|
|
|
|
// open reg key of DS Client
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
STR_DSCLIENT_REGKEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hSubKey) )
|
|
{
|
|
bResult = TRUE;
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/* ntbug#337931: remove license page
|
|
// load "License Agreement" text from license file
|
|
BOOL LoadLicenseFile(HWND hDlg)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
TCHAR szTitle[MAX_TITLE + 1];
|
|
TCHAR szTempBuffer[MAX_MESSAGE + 1];
|
|
TCHAR szLicenseFile[MAX_PATH + 1];
|
|
TCHAR szReturnTextBuffer[MAX_MESSAGE + 1];
|
|
LPTSTR lpszLicenseText = NULL;
|
|
HANDLE hFile;
|
|
DWORD dwNumberOfBytesRead, dwFileSize;
|
|
|
|
//
|
|
// Determine where we are installing from
|
|
// and specific the license file there
|
|
//
|
|
lstrcpy(szLicenseFile, g_sInstVar.m_szSourcePath);
|
|
lstrcat(szLicenseFile, STR_LICENSEFILE);
|
|
|
|
// Open License file
|
|
hFile = CreateFile(szLicenseFile, // pointer to name of the file
|
|
GENERIC_READ, // access (read-write) mode
|
|
FILE_SHARE_READ, // share mode
|
|
NULL, // pointer to security descriptor
|
|
OPEN_EXISTING, // how to create
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes
|
|
NULL); // handle to file with attributes to copy
|
|
|
|
if(INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
|
|
// Read License file into string
|
|
// setup memory, get file size in bytes
|
|
dwFileSize = GetFileSize (hFile, NULL) ;
|
|
|
|
if (dwFileSize != 0xFFFFFFFF)
|
|
{
|
|
// this program is for Win98/95, it will work in MBCS not UNICODE
|
|
// this code is for ANSI US version, license.txt file uses the single byte character set(ANSI)
|
|
// if doing locolization, license.txt file should use the double byte character set(DBCS/MBCS)
|
|
lpszLicenseText = (LPTSTR) calloc (dwFileSize + sizeof(TCHAR),
|
|
sizeof(BYTE));
|
|
}
|
|
|
|
if(lpszLicenseText)
|
|
{
|
|
//read file
|
|
if (ReadFile(hFile, // handle of file to read
|
|
lpszLicenseText, // address of buffer that receives data
|
|
dwFileSize, // number of bytes to read
|
|
&dwNumberOfBytesRead, // address of number of bytes read
|
|
NULL)) // address of structure for data
|
|
{
|
|
// display license on dialog
|
|
SetDlgItemText(hDlg, IDC_LICENSE_TEXT, lpszLicenseText);
|
|
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
// so free the memory
|
|
free(lpszLicenseText);
|
|
}
|
|
|
|
//close file handle
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
if(!bReturn)
|
|
{
|
|
// load string
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_TITLE,
|
|
szTitle,
|
|
MAX_TITLE);
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_LICENSEFILE,
|
|
szTempBuffer,
|
|
MAX_MESSAGE);
|
|
wsprintf(szReturnTextBuffer,
|
|
TEXT("%s %s"),
|
|
szTempBuffer,
|
|
szLicenseFile);
|
|
|
|
MessageBox(hDlg,
|
|
szReturnTextBuffer,
|
|
szTitle,
|
|
MB_OK | MB_TOPMOST | MB_ICONERROR);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
*/
|
|
|
|
// check disk space
|
|
BOOL CheckDiskSpace()
|
|
{
|
|
BOOL bResult = TRUE;
|
|
TCHAR szString[MAX_MESSAGE + MAX_TITLE + 1];
|
|
TCHAR szTitle[MAX_TITLE + 1];
|
|
TCHAR szMessage[MAX_MESSAGE + 1];
|
|
|
|
if(SIZE_TOTAL*MB_TO_BYTE > SetupGetDiskFreeSpace())
|
|
{
|
|
// load string
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_NODISKSPACE,
|
|
szMessage,
|
|
MAX_MESSAGE);
|
|
LoadString(g_sInstVar.m_hInstance,
|
|
IDS_ERROR_TITLE,
|
|
szTitle,
|
|
MAX_TITLE);
|
|
wsprintf(szString,
|
|
TEXT("%s %d MB."),
|
|
szMessage,
|
|
SIZE_TOTAL);
|
|
|
|
MessageBox(NULL,
|
|
szString,
|
|
szTitle,
|
|
MB_OK | MB_TOPMOST | MB_ICONERROR);
|
|
|
|
bResult = FALSE;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
// create objects
|
|
BOOL CreateObjects()
|
|
{
|
|
try
|
|
{
|
|
// initialize the synchronizing object
|
|
InitializeCriticalSection(&g_sInstVar.m_oCriticalSection);
|
|
}
|
|
catch(...)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// create a 12 pt big font
|
|
CreateBigFont();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// destroy objects
|
|
VOID DestroyObjects()
|
|
{
|
|
// wait to finish the runing setup process
|
|
if(g_sInstVar.m_hInstallThread)
|
|
{
|
|
// wait the installation thread to finish
|
|
WaitForSingleObject(g_sInstVar.m_hInstallThread,INFINITE);
|
|
CloseHandle(g_sInstVar.m_hInstallThread);
|
|
}
|
|
|
|
// delete the synchronizing object
|
|
DeleteCriticalSection(&g_sInstVar.m_oCriticalSection);
|
|
|
|
//Frees up the space used by loading the fonts
|
|
if( g_sInstVar.m_hBigBoldFont )
|
|
{
|
|
DeleteObject( g_sInstVar.m_hBigBoldFont );
|
|
}
|
|
|
|
}
|
|
|
|
//create a big font for dialog title
|
|
VOID CreateBigFont()
|
|
{
|
|
NONCLIENTMETRICS ncm;
|
|
LOGFONT BigBoldLogFont;
|
|
HDC hdc;
|
|
|
|
// Create the fonts we need based on the dialog font
|
|
ZeroMemory(&ncm,sizeof(NONCLIENTMETRICS));
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
|
BigBoldLogFont = ncm.lfMessageFont;
|
|
BigBoldLogFont.lfWeight = FW_BOLD;
|
|
|
|
hdc = GetDC(NULL);
|
|
if( hdc )
|
|
{
|
|
BigBoldLogFont.lfHeight = 0 -
|
|
(GetDeviceCaps(hdc,LOGPIXELSY) *
|
|
SIZE_TITLE_FONT /
|
|
72);
|
|
|
|
g_sInstVar.m_hBigBoldFont = CreateFontIndirect(&BigBoldLogFont);
|
|
|
|
ReleaseDC(NULL,hdc);
|
|
}
|
|
}
|
|
|