Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1116 lines
33 KiB

//***************************************************************************
//* Copyright (c) Microsoft Corporation 1995. All rights reserved. *
//***************************************************************************
//* *
//* UTILS.C - Win32 Based Cabinet File Self-extractor and installer utils. *
//* *
//***************************************************************************
//* *
//* Originally written by Jeff Webber. *
//* *
//***************************************************************************
//***************************************************************************
//* INCLUDE FILES *
//***************************************************************************
#include "pch.h"
#pragma hdrstop
#include "wextract.h"
#include "regstr.h"
#include "global.h"
#include <commctrl.h>
static TCHAR szRegRunOnceKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
static TCHAR szNT4XDelayUntilReboot[] = "System\\CurrentControlSet\\Control\\Session Manager";
static TCHAR szNT4XPendingValue[] = "PendingFileRenameOperations";
static TCHAR szNT3XDelayUntilReboot[] = "System\\CurrentControlSet\\Control\\Session Manager\\FileRenameOperations";
static TCHAR szRegValNameTemplate[] = "wextract_cleanup%d";
static TCHAR szRegValTemplate[] = "%s /D:%s";
static TCHAR szRegValAdvpackTemplate[] = "rundll32.exe %sadvpack.dll,DelNodeRunDLL32 \"%s\"";
static TCHAR szBATCommand[] = "Command.com /c %s";
// store the RunOnce Clean-up reg keyname for this instance
//
TCHAR g_szRegValName[SMALL_BUF_LEN] = { 0 };
BOOL g_bConvertRunOnce = FALSE;
//***************************************************************************
//* Functions *
//***************************************************************************
typedef HRESULT (*CHECKTOKENMEMBERSHIP)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
BOOL CheckToken(BOOL *pfIsAdmin)
{
BOOL bNewNT5check = FALSE;
HINSTANCE hAdvapi32 = NULL;
CHECKTOKENMEMBERSHIP pf;
PSID AdministratorsGroup;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
hAdvapi32 = LoadLibrary("advapi32.dll");
if (hAdvapi32)
{
pf = (CHECKTOKENMEMBERSHIP)GetProcAddress(hAdvapi32, "CheckTokenMembership");
if (pf)
{
bNewNT5check = TRUE;
*pfIsAdmin = FALSE;
if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
{
pf(NULL, AdministratorsGroup, pfIsAdmin);
FreeSid(AdministratorsGroup);
}
}
FreeLibrary(hAdvapi32);
}
return bNewNT5check;
}
// IsNTAdmin();
// Returns true if our process has admin priviliges.
// Returns false otherwise.
BOOL IsNTAdmin()
{
static int fIsAdmin = 2;
HANDLE hAccessToken;
PTOKEN_GROUPS ptgGroups;
DWORD dwReqSize;
UINT i;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
BOOL bRet;
//
// If we have cached a value, return the cached value. Note I never
// set the cached value to false as I want to retry each time in
// case a previous failure was just a temp. problem (ie net access down)
//
bRet = FALSE;
ptgGroups = NULL;
if( fIsAdmin != 2 )
return (BOOL)fIsAdmin;
if (!CheckToken(&bRet))
{
if(!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hAccessToken ) )
return FALSE;
// See how big of a buffer we need for the token information
if(!GetTokenInformation( hAccessToken, TokenGroups, NULL, 0, &dwReqSize))
{
// GetTokenInfo should the buffer size we need - Alloc a buffer
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
ptgGroups = (PTOKEN_GROUPS) LocalAlloc(LMEM_FIXED, dwReqSize);
}
// ptgGroups could be NULL for a coupla reasons here:
// 1. The alloc above failed
// 2. GetTokenInformation actually managed to succeed the first time (possible?)
// 3. GetTokenInfo failed for a reason other than insufficient buffer
// Any of these seem justification for bailing.
// So, make sure it isn't null, then get the token info
if(ptgGroups && GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwReqSize, &dwReqSize))
{
if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
{
// Search thru all the groups this process belongs to looking for the
// Admistrators Group.
for( i=0; i < ptgGroups->GroupCount; i++ )
{
if( EqualSid(ptgGroups->Groups[i].Sid, AdministratorsGroup) )
{
// Yea! This guy looks like an admin
fIsAdmin = TRUE;
bRet = TRUE;
break;
}
}
FreeSid(AdministratorsGroup);
}
}
if(ptgGroups)
LocalFree(ptgGroups);
// BUGBUG: Close handle here? doc's aren't clear whether this is needed.
CloseHandle(hAccessToken);
}
else if (bRet)
fIsAdmin = TRUE;
return bRet;
}
//**************************************************************************
//
// WarningDlgProc()
//
// Dialog proc for handling a continue/Exit dialog.
//
//**************************************************************************
INT_PTR CALLBACK WarningDlgProc( HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
{
char szMsg[MAX_STRING];
switch( msg )
{
case WM_INITDIALOG:
CenterWindow( hwnd, GetDesktopWindow() );
*szMsg = 0;
LoadString(g_hInst, (UINT)lParam, szMsg, sizeof(szMsg));
SetDlgItemText(hwnd, IDC_WARN_TEXT, szMsg);
MessageBeep((UINT)-1);
return( TRUE ); // Let default control be chosen.
case WM_COMMAND:
switch( wParam )
{
case IDC_EXIT:
case IDC_CONTINUE:
EndDialog( hwnd, wParam );
break;
default:
return FALSE;
}
return TRUE;
default:
break;
}
return( FALSE ); // Let default dialog processing do all.
}
// returns start of next field (or null if null), sets start to begining of the first field,
// with fields separated by separaters and nulls first separater after the first field
TCHAR* ExtractField( TCHAR **pstart, TCHAR * separaters)
{
LPTSTR start = *pstart;
int x = 0;
while(ANSIStrChr(separaters, *start)) {
if(*start == 0)
return(NULL);
start++;
}
*pstart = start;
while(!ANSIStrChr(separaters, start[x]) && (start[x] != 0))
x++;
if(start[x] == 0)
return(start + x);
start[x] = 0;
return(start + x + 1);
}
BOOL AnalyzeCmd( LPTSTR szOrigiCommand, LPTSTR *lplpCommand, BOOL *pfInfCmd )
{
TCHAR szTmp[MAX_PATH];
TCHAR szINFFile[MAX_PATH];
LPTSTR szNextField, szCurrField, szExt;
UINT secLength;
LPTSTR lpTempCmd, pszINFEngine;
lstrcpy( szTmp, szOrigiCommand );
// check if the command is LFN name
if ( szTmp[0] == '"' )
{
szCurrField = &szTmp[1];
szNextField = ExtractField( &szCurrField, "\"" );
}
else
{
szCurrField = szTmp;
szNextField = ExtractField( &szCurrField, " " );
}
if ( !IsRootPath( szCurrField ) )
{
// BUGBUG: when IsRootPath Failed, we did not check if the givn
// szCurrField is valid name or not. If it is not valid, the result
// of the AddPath will produce invalid file path. The error will come out at
// either SETUP engine or CreateProcess
//
lstrcpy( szINFFile, g_Sess.achDestDir );
AddPath( szINFFile, szCurrField );
}
else
lstrcpy( szINFFile, szCurrField );
// check if this is a INF file command
if ( ((szExt = ANSIStrRChr( szCurrField, '.' )) != NULL) && !lstrcmpi( szExt, ".INF" ) )
{
// check to see if this valid command
if ( !FileExists( szINFFile ) )
{
ErrorMsg1Param( NULL, IDS_ERR_FILENOTEXIST, szINFFile );
return FALSE;
}
// check if there is INF section install, and get the sec start point
szCurrField = szNextField;
szNextField = ExtractField( &szCurrField, "[" ); // skip things between .INF and [ section beginning
secLength = lstrlen( achDefaultSection );
if ( szNextField )
{
// in the case of: .INF<single-blank>[abc]
// the szNextField is "" while in the case of: .INF<multiple-blanks>[abc]
// szNextField points to "abc]". Therefore, the conditional pointer switch added here
//
if ( *szNextField )
{
szCurrField = szNextField;
}
szNextField = ExtractField( &szCurrField, "]" ); // get INF InstallSection name
if ( *szCurrField )
{
secLength = lstrlen( szCurrField );
}
}
lpTempCmd = (LPSTR) LocalAlloc( LPTR, 512);
if ( ! lpTempCmd )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
// store INF name for reboot checking use
g_uInfRebootOn = GetPrivateProfileInt( *szCurrField ? szCurrField : achDefaultSection, "Reboot", 0, szINFFile );
*pfInfCmd = TRUE; // no RunOnce entry needed
// check if we need use Advanced INF dll handling
if ( GetPrivateProfileString( SEC_VERSION, KEY_ADVINF, "", lpTempCmd, 8, szINFFile )
> 0 )
{
g_Sess.uExtractOpt |= EXTRACTOPT_ADVDLL;
// re-use the buf here
lstrcpy( szOrigiCommand, *szCurrField ? szCurrField : achDefaultSection );
lstrcpy( lpTempCmd, szINFFile );
}
else
{
g_Sess.uExtractOpt &= ~(EXTRACTOPT_ADVDLL);
if (g_wOSVer == _OSVER_WIN9X)
{
pszINFEngine = "setupx.dll";
GetShortPathName( szINFFile, szINFFile, sizeof(szINFFile) );
}
else
pszINFEngine = "setupapi.dll";
wsprintf( lpTempCmd, achSETUPDLL, pszINFEngine,
*szCurrField ? szCurrField : achDefaultSection, szINFFile );
}
}
else if ( ((szExt = ANSIStrRChr( szCurrField, '.' )) != NULL) && !lstrcmpi( szExt, ".BAT" ) )
{
lpTempCmd = (LPSTR) LocalAlloc( LPTR, lstrlen( szBATCommand ) + lstrlen( szINFFile ) + 8 );
if ( ! lpTempCmd )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
wsprintf( lpTempCmd, szBATCommand, szINFFile );
}
else
{
// assume EXE command
// you are here, the szINFFile contains the command with fully qualified pathname enterred either
// by User or appended by wextract.exe to Temp extracting file location.
DWORD dwAttr;
CHAR szCmd[2*MAX_STRING];
lpTempCmd = (LPSTR) LocalAlloc( LPTR, 2*MAX_STRING ); // 1K buf
if ( ! lpTempCmd )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
return FALSE;
}
dwAttr = GetFileAttributes( szINFFile );
if ( (dwAttr == -1) || (dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
{
// file is not found as it IS. Run it as it WAS!
// IS and WAS may be the same if user enterred fully qaulified name. CreateProcess will buff it.
lstrcpy( szCmd, szOrigiCommand );
}
else
{
// found it. Run it as it IS. Need to append switches if there is any.
lstrcpy( szCmd, szINFFile );
if ( szNextField && *szNextField )
{
lstrcat( szCmd, " " );
lstrcat( szCmd, szNextField );
}
}
// replace the #D with the directory this module is loaded or
// #E with the fullpath of the running EXE
ExpandCmdParams( szCmd, lpTempCmd );
}
*lplpCommand = lpTempCmd;
return TRUE;
}
void DisplayHelp()
{
MsgBox1Param( NULL, IDS_HELPMSG, "", MB_ICONINFORMATION, MB_OK );
}
DWORD CheckReboot( VOID )
{
DWORD dwReturn = 0xFFFFFFFF;
if ( !g_uInfRebootOn )
{
if (NeedReboot(g_dwRebootCheck, g_wOSVer))
dwReturn = EWX_REBOOT;
}
else
dwReturn = EWX_REBOOT; // reboot = 1 in inf file
return dwReturn;
}
// NT reboot
//
BOOL MyNTReboot()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// get a token from this process
if ( !OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
ErrorMsg( NULL, IDS_ERR_OPENPROCTK );
return FALSE;
}
// get the LUID for the shutdown privilege
LookupPrivilegeValue( NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid );
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//get the shutdown privilege for this proces
if ( !AdjustTokenPrivileges( hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0 ) )
{
ErrorMsg( NULL, IDS_ERR_ADJTKPRIV );
return FALSE;
}
// shutdown the system and force all applications to close
if (!ExitWindowsEx( EWX_REBOOT, 0 ) )
{
ErrorMsg( NULL, IDS_ERR_EXITWINEX );
return FALSE;
}
return TRUE;
}
// Display a dialog asking the user to restart Windows, with a button that
// will do it for them if possible.
//
void MyRestartDialog( DWORD dwRebootMode )
{
UINT id = IDCANCEL;
DWORD dwReturn;
// only if you checked and REBOOT_YES is true, you are here
if ( dwRebootMode & REBOOT_ALWAYS )
{
dwReturn = EWX_REBOOT;
}
else
{
dwReturn = CheckReboot();
}
if ( dwReturn == EWX_REBOOT )
{
if ( dwRebootMode & REBOOT_SILENT )
id = IDYES;
else
{
id = MsgBox1Param( NULL, IDS_RESTARTYESNO, "", MB_ICONINFORMATION, MB_YESNO );
}
if ( id == IDYES )
{
if ( dwReturn == EWX_REBOOT )
{
if ( g_wOSVer == _OSVER_WIN9X )
{
// By default (all platforms), we assume powerdown is possible
id = ExitWindowsEx( EWX_REBOOT, 0 );
}
else
{
MyNTReboot();
}
}
}
}
return;
}
// CleanRegRunOnce()
//
void CleanRegRunOnce()
{
HKEY hKey;
if ( g_szRegValName[0] == 0 )
{
return;
}
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szRegRunOnceKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS )
{
RegDeleteValue( hKey, g_szRegValName );
RegCloseKey( hKey );
}
return;
}
void AddRegRunOnce()
{
HKEY hKey;
DWORD dwDisposition;
LPSTR szRegEntry;
TCHAR szBuf[MAX_PATH] = "";
TCHAR szAdvpack[MAX_PATH] = "";
int i;
DWORD dwTmp;
HANDLE hSetupLibrary;
BOOL fUseAdvpack = FALSE;
// prepare backup registry
if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegRunOnceKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
{
// reg problem, but not block the process
return;
}
// Check if key already exists -- if so, go with next number.
//
for (i=0; i<200; i++)
{
wsprintf( g_szRegValName, szRegValNameTemplate, i );
if ( RegQueryValueEx( hKey, g_szRegValName, 0, NULL, NULL, &dwTmp ) != ERROR_SUCCESS )
{
// g_szRegValName now has the key name we need for this instance
break;
}
}
if ( i == 200 )
{
// something is wrong, there are at lease 200 RunOnce enteries in the Registry
// bail out, don't add any more
RegCloseKey( hKey );
g_szRegValName[0] = 0;
return;
}
// check if ADVPACK in the system dir exports DelNodeRunDLL32;
// if so, use szRegValAdvpackTemplate, otherwise, use szRegValTemplate
GetSystemDirectory(szAdvpack, sizeof(szAdvpack));
AddPath(szAdvpack, ADVPACKDLL);
if ((hSetupLibrary = LoadLibrary(szAdvpack)) != NULL)
{
fUseAdvpack = GetProcAddress(hSetupLibrary, "DelNodeRunDLL32") != NULL;
FreeLibrary(hSetupLibrary);
}
if (fUseAdvpack)
{
if (GetSystemDirectory(szBuf, sizeof(szBuf)))
AddPath(szBuf, "");
}
else
{
// get current EXE filename
//
if ( !GetModuleFileName( g_hInst, szBuf, (DWORD)sizeof(szBuf) ) )
{
RegCloseKey( hKey );
return;
}
}
// alloc mem for store reg entry values
//
szRegEntry = (LPSTR) LocalAlloc( LPTR, lstrlen(szBuf) + lstrlen(g_Sess.achDestDir) + SMALL_BUF_LEN );
if ( !szRegEntry )
{
ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
RegCloseKey( hKey );
return;
}
g_bConvertRunOnce = !fUseAdvpack;
wsprintf(szRegEntry, fUseAdvpack ? szRegValAdvpackTemplate : szRegValTemplate, szBuf, g_Sess.achDestDir);
RegSetValueEx( hKey, g_szRegValName, 0, REG_SZ, (CONST BYTE*)szRegEntry, lstrlen(szRegEntry)+1);
RegCloseKey(hKey);
LocalFree( szRegEntry );
return;
}
// Change the RunOnce entry that cleans up extracted files to use ADVPACK instead of wextract
void ConvertRegRunOnce()
{
if (*g_szRegValName)
{
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegRunOnceKey, 0, KEY_READ | KEY_WRITE, &hKey) == ERROR_SUCCESS)
{
TCHAR szRegEntry[2 * MAX_PATH + sizeof(szRegValAdvpackTemplate)];
DWORD dwSize = sizeof(szRegEntry);
// read the old value data that uses wextract and get the extracted files dir
if (RegQueryValueEx(hKey, g_szRegValName, NULL, NULL, (LPBYTE) szRegEntry, &dwSize) == ERROR_SUCCESS)
{
TCHAR szSysDir[MAX_PATH] = "";
if (GetSystemDirectory(szSysDir, sizeof(szSysDir)))
AddPath(szSysDir, "");
wsprintf(szRegEntry, szRegValAdvpackTemplate, szSysDir, g_Sess.achDestDir);
RegSetValueEx(hKey, g_szRegValName, 0, REG_SZ, (CONST BYTE *) szRegEntry, lstrlen(szRegEntry) + 1);
}
RegCloseKey(hKey);
}
}
return;
}
void DeleteMyDir( LPSTR lpDir )
{
char szFile[MAX_PATH];
WIN32_FIND_DATA fileData;
HANDLE hFindFile;
if ( lpDir == NULL || *lpDir == '\0' )
return;
lstrcpy( szFile, lpDir );
lstrcat( szFile, "*" );
hFindFile = FindFirstFile( szFile, &fileData );
if ( hFindFile == INVALID_HANDLE_VALUE )
return;
do
{
lstrcpy( szFile, lpDir );
if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( lstrcmp( fileData.cFileName, "." ) == 0 ||
lstrcmp( fileData.cFileName, ".." ) == 0 )
continue;
// delete the sub-dir
lstrcat( szFile, fileData.cFileName );
AddPath( szFile, "");
DeleteMyDir( szFile );
}
else
{
// delete the file
lstrcat( szFile, fileData.cFileName );
SetFileAttributes( szFile, FILE_ATTRIBUTE_NORMAL );
DeleteFile( szFile );
}
} while ( FindNextFile( hFindFile, &fileData ) );
FindClose( hFindFile );
RemoveDirectory( lpDir );
}
#if 0
//==================================================================
// AddPath()
//
void AddPath(LPSTR szPath, LPCSTR szName )
{
LPSTR szTmp;
// Find end of the string
szTmp = szPath + lstrlen(szPath);
// If no trailing backslash then add one
if ( szTmp > szPath && *(AnsiPrev( szPath, szTmp )) != '\\' )
*(szTmp++) = '\\';
// Add new name to existing path string
while ( *szName == ' ' ) szName++;
lstrcpy( szTmp, szName );
}
#endif
//---------------------------------------------------------------------------
// Returns TRUE if the given string is a UNC path.
//
// check if a path is a root path
//
// returns:
// TRUE for "X:\..." "\\foo\asdf\..."
// FALSE for others
BOOL IsRootPath(LPCSTR pPath)
{
if ( !pPath || (lstrlen(pPath) < 3) )
{
return FALSE;
}
// BUGBUG: this just smell like UNC, possible invalid UNC. If so,
// user will get error when later create process
if ( ( (*(pPath+1) == ':') && (*(pPath+2) == '\\') ) || // "X:\" case
( (*pPath == '\\') && (*(pPath + 1) == '\\' ) ) ) // UNC \\.... case
return TRUE;
else
return FALSE;
}
// BUGBUG:BUGBUG:BUGBUG:BUGBUG
// The code below is duplicated in advpack.dll. If you do changed/fixes to this code
// make sure to also change the code in advpack.dll
// Returns the size of wininit.ini in the windows directory.
// 0 if not found
DWORD GetWininitSize()
{
TCHAR szPath[MAX_PATH];
HFILE hFile;
DWORD dwSize = (DWORD)0;
if ( GetWindowsDirectory( szPath, MAX_PATH ) )
{
AddPath( szPath, "wininit.ini" );
// Make sure all changes have been saved to disk for accurate size reading
WritePrivateProfileString(NULL, NULL, NULL, szPath);
if ((hFile = _lopen(szPath, OF_READ|OF_SHARE_DENY_NONE)) != HFILE_ERROR)
{
dwSize = _llseek(hFile, 0L, FILE_END);
_lclose(hFile);
}
}
return dwSize;
}
// Returns the size of the value lpcszValue under lpcszRegKey
// 0 if the registry key or the value were not found
DWORD GetRegValueSize(LPCSTR lpcszRegKey, LPCSTR lpcszValue)
{
HKEY hKey;
DWORD dwValueSize = (DWORD)0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpcszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, lpcszValue, NULL, NULL, NULL,&dwValueSize) != ERROR_SUCCESS)
dwValueSize = (DWORD)0;
RegCloseKey(hKey);
}
return dwValueSize;
}
// Returns the number of Values in the key
// 0 if the registry key was not found or RegQueryInfoKey failed
DWORD GetNumberOfValues(LPCSTR lpcszRegKey)
{
HKEY hKey;
DWORD dwValueSize = (DWORD)0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpcszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
if (RegQueryInfoKey(hKey,
NULL, NULL, NULL, NULL, NULL, NULL,
&dwValueSize,
NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
dwValueSize = (DWORD)0;
RegCloseKey(hKey);
}
return dwValueSize;
}
// Returns the rebootcheck value depending on the OS we get passed in.
DWORD NeedRebootInit(WORD wOSVer)
{
DWORD dwReturn = (DWORD)0;
switch (wOSVer)
{
case _OSVER_WIN9X:
dwReturn = GetWininitSize();
break;
case _OSVER_WINNT40:
case _OSVER_WINNT50:
dwReturn = GetRegValueSize(szNT4XDelayUntilReboot, szNT4XPendingValue);
break;
case _OSVER_WINNT3X:
dwReturn = GetNumberOfValues(szNT3XDelayUntilReboot);
break;
}
return dwReturn;
}
// Checks the passed in reboot check value against the current value.
// If they are different, we need to reboot.
// The reboot check value is dependend on the OS
BOOL NeedReboot(DWORD dwRebootCheck, WORD wOSVer)
{
return (dwRebootCheck != NeedRebootInit(wOSVer));
}
// check if Dir does not exist, create one.
//
BOOL IfNotExistCreateDir( LPTSTR lpDir )
{
DWORD attr;
if ( (attr = GetFileAttributes( lpDir )) == -1 )
{
return ( CreateDirectory( lpDir, NULL ) );
}
return (attr & FILE_ATTRIBUTE_DIRECTORY);
}
// check if the given dir is on Windows Drive
//
BOOL IsWindowsDrive( LPTSTR szPath )
{
TCHAR szWin[MAX_PATH];
if ( !GetWindowsDirectory( szWin, MAX_PATH ) )
{
ErrorMsg( NULL, IDS_ERR_GET_WIN_DIR );
ASSERT( FALSE );
}
return ( *szPath == szWin[0] );
}
PSTR MyULtoA( ULONG ulParam, PSTR pszOut )
{
wsprintf( pszOut, "%lu", ulParam );
return pszOut;
}
// display diskspace checking Error message
// it always return FALSE except that User answer YES on msgbox
//
BOOL DiskSpaceErrMsg( UINT msgType, ULONG ulExtractNeeded, DWORD dwInstNeeded, LPTSTR lpDrv )
{
TCHAR szSize[10];
BOOL bRet = FALSE;
// all the cases except one are returning FALSE, so we set Error code here
g_dwExitCode = ERROR_DISK_FULL;
if ( msgType == MSG_REQDSK_ERROR )
{
ErrorMsg1Param( NULL, IDS_ERR_NO_SPACE_ERR, MyULtoA((ulExtractNeeded+dwInstNeeded), szSize) );
}
else if ( msgType == MSG_REQDSK_RETRYCANCEL )
{
if ( MsgBox1Param( NULL, IDS_ERR_NO_SPACE_BOTH, MyULtoA( (ulExtractNeeded+dwInstNeeded), szSize),
MB_ICONQUESTION, MB_RETRYCANCEL|MB_DEFBUTTON1 ) == IDRETRY )
bRet = TRUE;
else
bRet = FALSE;
}
else if ( msgType == MSG_REQDSK_WARN )
{
// in /Q mode: MsgBox2Param return MB_OK which is not IDYES, so we fail the process.
//
if ( MsgBox2Param( NULL, IDS_ERR_NO_SPACE_INST, MyULtoA(dwInstNeeded, szSize), lpDrv,
MB_ICONINFORMATION, MB_YESNO | MB_DEFBUTTON2 ) == IDYES )
{
bRet = TRUE;
g_dwExitCode = S_OK;
}
}
//else ( msgType == MSG_REQDSK_NONE ) do nothing
return bRet;
}
BOOL GetFileTobeChecked( LPSTR szPath, int iSize, LPCSTR szNameStr )
{
char ch;
BOOL bComplete = FALSE;
szPath[0] = 0;
if ( *szNameStr == '#' )
{
ch = (CHAR)CharUpper((PSTR)*(++szNameStr));
szNameStr = CharNext( CharNext( szNameStr ) );
switch ( ch )
{
case 'S':
GetSystemDirectory( szPath, iSize );
break;
case 'W':
GetWindowsDirectory( szPath, iSize );
break;
case 'A':
default:
{
// look into reg AppPath
char szSubKey[MAX_PATH];
DWORD dwSize = sizeof( szSubKey );
HKEY hKey;
DWORD dwType;
lstrcpy( szSubKey, REGSTR_PATH_APPPATHS );
AddPath( szSubKey, szNameStr );
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey ) == ERROR_SUCCESS )
{
if ( RegQueryValueEx(hKey, "", NULL, &dwType, (LPBYTE)szPath, &dwSize) == ERROR_SUCCESS )
{
if ((dwType == REG_EXPAND_SZ) &&
(ExpandEnvironmentStrings(szPath, szSubKey, sizeof(szSubKey))))
{
lstrcpy(szPath, szSubKey);
bComplete = TRUE;
}
else if (dwType == REG_SZ)
bComplete = TRUE;
}
RegCloseKey( hKey );
}
}
break;
}
}
else
GetSystemDirectory( szPath, iSize );
if ( !bComplete )
AddPath( szPath, szNameStr );
return TRUE;
}
BOOL CheckFileVersion( PTARGETVERINFO ptargetVers, LPSTR szPath, int isize, int *pidx )
{
unsigned uiSize;
DWORD dwVerInfoSize;
DWORD dwHandle;
VS_FIXEDFILEINFO * lpVSFixedFileInfo;
void FAR *lpBuffer;
HGLOBAL hgbl = NULL;
BOOL bRet = FALSE;
int ifrAnswer[2], itoAnswer[2], i, j;
PVERCHECK pfileV;
for ( i=0; i< (int)(ptargetVers->dwNumFiles); i++ )
{
pfileV = (PVERCHECK)( ptargetVers->szBuf + ptargetVers->dwFileOffs + i*sizeof(VERCHECK) );
if ( !GetFileTobeChecked( szPath, isize, (ptargetVers->szBuf + pfileV->dwNameOffs) ) )
goto EXIT;
dwVerInfoSize = GetFileVersionInfoSize(szPath, &dwHandle);
if (dwVerInfoSize)
{
// Alloc the memory for the version stamping
hgbl = GlobalAlloc(GHND, dwVerInfoSize);
if (hgbl == NULL)
goto EXIT;
lpBuffer = GlobalLock(hgbl);
if (lpBuffer == NULL)
goto EXIT;
// Read version stamping info
if (GetFileVersionInfo(szPath, dwHandle, dwVerInfoSize, lpBuffer))
{
// Get the value for Translation
if ( VerQueryValue(lpBuffer, "\\", (void FAR*FAR*)&lpVSFixedFileInfo, &uiSize) && (uiSize) )
{
for ( j=0; j<2; j++ )
{
ifrAnswer[j] = CompareVersion( lpVSFixedFileInfo->dwFileVersionMS, lpVSFixedFileInfo->dwFileVersionLS,
pfileV->vr[j].frVer.dwMV, pfileV->vr[j].frVer.dwLV );
itoAnswer[j] = CompareVersion( lpVSFixedFileInfo->dwFileVersionMS, lpVSFixedFileInfo->dwFileVersionLS,
pfileV->vr[j].toVer.dwMV, pfileV->vr[j].toVer.dwLV );
}
if ( (ifrAnswer[0] >= 0 && itoAnswer[0] <= 0) || (ifrAnswer[1] >= 0 && itoAnswer[1] <= 0) )
;
else
{
GlobalUnlock(hgbl);
goto EXIT;
}
}
}
GlobalUnlock(hgbl);
}
else
{
// file not exist case, if author specify install 1st ranges from version 0 to 0. Then do it!
if ( pfileV->vr[0].frVer.dwMV || pfileV->vr[0].frVer.dwLV )
{
goto EXIT;
}
}
}
bRet = TRUE;
EXIT:
*pidx = i;
if ( hgbl )
GlobalFree( hgbl );
return bRet;
}
UINT GetMsgboxFlag( DWORD dwFlag )
{
UINT uButton;
if ( dwFlag & VERCHK_YESNO )
uButton = MB_YESNO | MB_DEFBUTTON2;
else if ( dwFlag & VERCHK_OKCANCEL )
uButton = MB_OKCANCEL | MB_DEFBUTTON2;
else
uButton = MB_OK;
return uButton;
}
int CompareVersion(DWORD dwMS1, DWORD dwLS1, DWORD dwMS2, DWORD dwLS2)
{
if (dwMS1 < dwMS2)
return -1 ;
if (dwMS1 > dwMS2)
return 1 ;
if (dwLS1 < dwLS2)
return -1 ;
if (dwLS1 > dwLS2)
return 1 ;
return 0 ;
}
void ExpandCmdParams( PCSTR pszInParam, PSTR pszOutParam )
{
CHAR szModulePath[MAX_PATH];
LPSTR pszTmp;
*pszOutParam = '\0';
if ( !pszInParam || !*pszInParam )
return;
// get Module path
GetModuleFileName( g_hInst, szModulePath, (DWORD)sizeof(szModulePath) );
while ( *pszInParam != '\0' )
{
if (IsDBCSLeadByte(*pszInParam))
{
*pszOutParam = *pszInParam;
*(pszOutParam+1) = *(pszInParam+1);
}
else
*pszOutParam = *pszInParam;
if ( *pszInParam == '#' )
{
pszInParam = CharNext(pszInParam);
if ( (CHAR)CharUpper((PSTR)*pszInParam) == 'D' )
{
GetParentDir( szModulePath );
pszTmp = CharPrev(szModulePath, &szModulePath[lstrlen(szModulePath)]);
if (pszTmp && (*pszTmp == '\\'))
*pszTmp = '\0';
lstrcpy( pszOutParam, szModulePath );
pszOutParam += lstrlen( szModulePath );
}
else if ( (CHAR)CharUpper((PSTR)*pszInParam) == 'E' )
{
lstrcpy( pszOutParam, szModulePath );
pszOutParam += lstrlen( szModulePath );
}
else if ( *pszInParam == '#' )
pszOutParam = CharNext( pszOutParam );
}
else
pszOutParam = CharNext( pszOutParam );
pszInParam = CharNext(pszInParam);
}
*pszOutParam = '\0';
}