//*************************************************************************** //* 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 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[abc] // the szNextField is "" while in the case of: .INF[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'; }