#include "inspch.h" #include "inseng.h" #include "resource.h" #include "insobj.h" #include "advpub.h" #include "capi.h" #include "util.h" #include "util2.h" #include TCHAR c_gszSetupAPI[] = "setupapi.dll"; TCHAR c_gszAdvpext[] = "advpext.dll"; // A reusable buffer for logging. Note there is a possible threading // issue here as two threads may use this at the same time! I am choosing // not to protect it for performance reasons but be careful!! char szLogBuf[512]; // NT reboot // #define MSDOWNLOAD "msdownld.tmp" #define DOWNLDSUB "download" // functions BOOL IfNotExistCreateDir( LPTSTR lpDir, BOOL bHidden, BOOL bRemoveFileIfExist ); BOOL CheckImageHlp_dll(); char g_szWindowsDir[MAX_PATH] = { 0 }; #define MAXRETRIES 100 BOOL GetUniqueFileName(LPCSTR pszRoot, LPCSTR pszPrefix, UINT uStartIndex, LPSTR pszBuffer) { char pszTemp[MAX_PATH]; char pszTempname[16]; // we now ignore the uStartIndex parameter, and create something random. uStartIndex = GetTickCount() % 0xFFFF9A; UINT uEndIndex = uStartIndex + MAXRETRIES; LPSTR pszEnd; pszBuffer[0] = 0; lstrcpy(pszTemp, pszRoot); pszEnd = pszTemp + lstrlen(pszTemp); do { wsprintf(pszTempname, "%s%06X.tmp", pszPrefix, uStartIndex); AddPath(pszTemp, pszTempname); if(GetFileAttributes(pszTemp) == 0xFFFFFFFF) break; uStartIndex++; *pszEnd = 0; } while (uStartIndex < uEndIndex); if(uStartIndex != uEndIndex) lstrcpy(pszBuffer, pszTemp); return ( pszBuffer[0] != 0 ); } #define MIN_DISKSIZE_FOR_EXTRACT 1024 * 100 #define MAX_DRIVES 26 BOOL IsUsableDrive(LPSTR szRoot) { static BYTE bDrives[MAX_DRIVES] = { 0 }; static UINT uUseRemovable = 0xffffffff; BOOL fUsable; UINT uType; DWORD dwOldErrorMode; if(uUseRemovable == 0xffffffff) { char sztemp[] = "X:\\"; for(char ch = 'A'; ch <= 'Z'; ch++) { sztemp[0] = ch; if(GetDriveType(sztemp) == DRIVE_FIXED) { uUseRemovable = FALSE; break; } } if(uUseRemovable == 0xffffffff) uUseRemovable = TRUE; } dwOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); uType = GetDriveType(szRoot); // the drive type is OK, if // it is fixed or removable AND // it is bigger than MIN_DISKSIZE_FOR_EXTRACT AND // GetFileAttributes succeeds // if ( (!bDrives[szRoot[0] - 'A']) && ((uType == DRIVE_REMOVABLE && uUseRemovable) || (uType == DRIVE_FIXED)) && ( GetFileAttributes( szRoot ) != 0xffffffff) && ( GetDriveSize(szRoot) >= MIN_DISKSIZE_FOR_EXTRACT ) ) { fUsable = TRUE; } else { bDrives[szRoot[0] - 'A'] = 1; fUsable = FALSE; } SetErrorMode(dwOldErrorMode); return fUsable; } BOOL IsDirWriteable(LPSTR lpDir) { char szFile[MAX_PATH]; HANDLE hFile; BOOL bWriteAccess = FALSE; lstrcpy(szFile, lpDir); AddPath(szFile, "~!~ie6.~!~"); hFile = CreateFile(szFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { bWriteAccess = TRUE; CloseHandle(hFile); DeleteFile(szFile); } return bWriteAccess; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // // BUGBUG: Currently we have two problems : // 1. Always assume cache drive == win drive // 2. Compression isn't accounted for on stuff going to cache HRESULT CreateTempDir( DWORD dwDownloadSize, DWORD dwExtractSize, char chInstallDrive, DWORD dwInstallSize, DWORD dwWindowsDriveSize, LPSTR pszBuf, DWORD dwBufSize, DWORD dwFlag ) { char szRoot[MAX_PATH]; char szUnique[MAX_PATH]; DWORD dwReqSize; DWORD dwReqSizeWin = 0; DWORD dwReqSizeOther = 0; DWORD dwVolFlags; DWORD dwCompressFactor; if ( !pszBuf || (dwBufSize==0) ) { return ( E_INVALIDARG ); } if(g_szWindowsDir[0] == 0) { GetWindowsDirectory(g_szWindowsDir, sizeof(g_szWindowsDir)); } // Make sure there is enough install space on drive dwReqSizeWin = dwWindowsDriveSize; if(chInstallDrive == g_szWindowsDir[0]) dwReqSizeWin += dwInstallSize; else dwReqSizeOther = dwInstallSize; if(dwReqSizeWin > 0) { lstrcpyn(szRoot, g_szWindowsDir, 4); if(!IsEnoughSpace(szRoot, dwReqSizeWin)) return E_FAIL; } if(dwReqSizeOther > 0) { lstrcpyn(szRoot, g_szWindowsDir, 4); szRoot[0] = chInstallDrive; if(!IsEnoughSpace(szRoot, dwReqSizeOther)) return E_FAIL; } lstrcpy( szRoot, "A:\\" ); while ( szRoot[0] <= 'Z' ) { UINT uType; uType = GetDriveType(szRoot); // even the drive type is OK, verify the drive has valid connection // if ( !IsUsableDrive(szRoot) ) { szRoot[0]++; continue; } if(!IsDirWriteable(szRoot)) { szRoot[0]++; continue; } if(!GetVolumeInformation(szRoot, NULL, 0, NULL, NULL, &dwVolFlags, NULL, 0)) { szRoot[0]++; continue; } if(dwVolFlags & FS_VOL_IS_COMPRESSED) dwCompressFactor = 19; else dwCompressFactor = 10; // suitable drive: dwReqSize = (dwDownloadSize * dwCompressFactor)/10; dwReqSize += dwExtractSize; if(g_szWindowsDir[0] == szRoot[0]) dwReqSize += dwReqSizeWin; else if(chInstallDrive == szRoot[0]) dwReqSize += dwReqSizeOther; if ( !IsEnoughSpace( szRoot, dwReqSize ) ) { szRoot[0]++; continue; } // if our suitable drive happens also to be the windows drive, // create msdownld.tmp of of it. if(szRoot[0] == g_szWindowsDir[0]) lstrcpy(szRoot, g_szWindowsDir); AddPath( szRoot, MSDOWNLOAD ); if ( !IfNotExistCreateDir( szRoot, TRUE, TRUE ) ) { TryNextDrive: szRoot[0]++; szRoot[3] = '\0'; continue; } // BUGBUG: On NT, it always tries with sequential numbers ASE1.TMP, ASE2.TMP // ASE3.TMP, etc. and if there is already a directory by this name // it fails the call instead of trying again with next number! // if ( !GetUniqueFileName(szRoot,"AS", 0, szUnique) ) goto TryNextDrive ; lstrcpy(szRoot, szUnique); if ( !IfNotExistCreateDir( szRoot, FALSE, FALSE) ) { goto TryNextDrive; } // you got the good dir AddPath( szRoot, "" ); if ( (DWORD) lstrlen(szRoot)+1 > dwBufSize ) { return ( E_INVALIDARG ); } // success lstrcpy( pszBuf, szRoot ); return S_OK; } // no drive has enough space return( E_FAIL ); } void CleanUpTempDir(LPCSTR szTemp) { char szBuf[MAX_PATH]; char szWinDir[MAX_PATH]; lstrcpy(szBuf, szTemp); DelNode(szBuf, 0); // clean up msdownld.tmp if its not the windows drive GetWindowsDirectory(szWinDir, sizeof(szWinDir)); if(!ANSIStrStrI(szBuf, szWinDir)) { GetParentDir(szBuf); DelNode(szBuf, ADN_DEL_IF_EMPTY); } } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // // Checks the install destination dir free disk space // BOOL IsEnoughSpace( LPCSTR szPath, DWORD dwInstNeedSize ) { char szRoot[4]; lstrcpyn(szRoot, szPath, 4); if( szRoot[0] == 0) return FALSE; if ( dwInstNeedSize + 1 > GetSpace(szRoot) ) return FALSE; else return TRUE; } void SafeAddPath(LPSTR szPath, LPCSTR szName, DWORD dwPathSize) { LPSTR szTmp; DWORD dwLen = lstrlen(szPath); if(dwLen + 1 >= dwPathSize) return; // Find end of the string szTmp = szPath + dwLen; // If no trailing backslash then add one if ( szTmp > szPath && *(AnsiPrev( szPath, szTmp )) != '\\' ) *(szTmp++) = '\\'; *szTmp = 0; // Add new name to existing path string while ( *szName == ' ' ) szName++; lstrcpyn( szTmp, szName, dwPathSize - lstrlen(szPath) ); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // BOOL IfNotExistCreateDir( LPTSTR lpDir, BOOL bHidden, BOOL bRemoveFileIfExist) { DWORD attr; attr = GetFileAttributes( lpDir ); if ((attr != -1) && !(attr & FILE_ATTRIBUTE_DIRECTORY)) { // lpDir does not have a directory attribute // If we are allowed to delete the file, try do that. if (bRemoveFileIfExist) { SetFileAttributes(lpDir, FILE_ATTRIBUTE_NORMAL); DeleteFile(lpDir); attr = GetFileAttributes( lpDir ); } } if (attr == -1) { if ( CreateDirectory( lpDir, NULL ) ) { if(bHidden) return (SetFileAttributes( lpDir, FILE_ATTRIBUTE_HIDDEN ) ); else return TRUE; } else return FALSE; } return (attr & FILE_ATTRIBUTE_DIRECTORY); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // HRESULT LaunchProcess(LPCSTR pszCmd, HANDLE *phProc, LPCSTR pszDir, UINT uShow) { STARTUPINFO startInfo; PROCESS_INFORMATION processInfo; HRESULT hr = S_OK; BOOL fRet; if(phProc) *phProc = NULL; // Create process on pszCmd ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags |= STARTF_USESHOWWINDOW; startInfo.wShowWindow = (USHORT)uShow; fRet = CreateProcess(NULL, (LPSTR) pszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, pszDir, &startInfo, &processInfo); if(!fRet) return E_FAIL; if(phProc) *phProc = processInfo.hProcess; else CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); return S_OK; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // HRESULT LaunchAndWait(LPSTR pszCmd, HANDLE hAbort, HANDLE *phProc, LPSTR pszDir, UINT uShow) { HRESULT hr = S_OK; hr = LaunchProcess(pszCmd, phProc, pszDir, uShow); if(SUCCEEDED(hr)) { HANDLE pHandles[2]; BOOL fQuit = FALSE; pHandles[0] = *phProc; if(hAbort) pHandles[1] = hAbort; DWORD dwRet; while(!fQuit) { dwRet = MsgWaitForMultipleObjects(hAbort ? 2 : 1, pHandles, FALSE, INFINITE, QS_ALLINPUT); // Give abort the highest priority if(dwRet == WAIT_OBJECT_0) { fQuit = TRUE; } else if((dwRet == WAIT_OBJECT_0 + 1) && hAbort) { // Any abort work? hr = E_ABORT; fQuit = TRUE; } else { MSG msg; // read all of the messages in this next loop // removing each message as we read it while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // if it's a quit message we're out of here if (msg.message == WM_QUIT) fQuit = TRUE; else { // otherwise dispatch it DispatchMessage(&msg); } // end of PeekMessage while loop } } } } return hr; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // void ConvertVersionStrToDwords(LPSTR pszVer, LPDWORD pdwVer, LPDWORD pdwBuild) { DWORD dwTemp1,dwTemp2; dwTemp1 = GetIntField(pszVer, 0, 0); dwTemp2 = GetIntField(pszVer, 1, 0); *pdwVer = (dwTemp1 << 16) + dwTemp2; dwTemp1 = GetIntField(pszVer, 2, 0); dwTemp2 = GetIntField(pszVer, 3, 0); *pdwBuild = (dwTemp1 << 16) + dwTemp2; } /* void ConvertVersionStr(LPSTR pszVer, WORD rwVer[]) { LPSTR pszMyVer = MakeAnsiStrFromAnsi(pszVer); LPSTR pszEnd = pszMyVer + lstrlen(pszMyVer); LPSTR pszTemp = pszMyVer; LPSTR pszBegin; for(int i = 0; i < NUM_VERSION_ENTRIES; i++) rwVer[i] = 0; for(i = 0; i < 4 && pszTemp < pszEnd; i++) { pszBegin = pszTemp; while(pszTemp < pszEnd && *pszTemp != ',') pszTemp++; *pszTemp = 0; rwVer[i] = (WORD) AtoL(pszBegin); pszTemp++; } CoTaskMemFree(pszMyVer); } */ //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // -1 Ver1 < Ver2 // 0 Ver1 == Ver2 // 1 Ver1 > Ver2 // Notes: int VersionCmp(WORD rwVer1[], WORD rwVer2[]) { /* for(int i = 0; i < NUM_VERSION_ENTRIES; i++) { if(rwVer1[i] < rwVer2[i]) return -1; if(rwVer1[i] > rwVer2[i]) return 1; } */ return 0; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // int ErrMsgBox(LPSTR pszText, LPCSTR pszTitle, UINT mbFlags) { HWND hwndActive; int id; hwndActive = GetActiveWindow(); id = MessageBox(hwndActive, pszText, pszTitle, mbFlags | MB_ICONERROR | MB_TASKMODAL); return id; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // int LoadSz(UINT id, LPSTR pszBuf, UINT cMaxSize) { if(cMaxSize == 0) return 0; pszBuf[0] = 0; return LoadString(g_hInstance, id, pszBuf, cMaxSize); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPSTR FindChar(LPSTR pszStr, char ch) { while( *pszStr != 0 && *pszStr != ch ) { if (*pszStr == '\"') { // Move past the first " pszStr++; // Now keep scanning till find the closing ". After that return to scanning // for the user-given delimiter 'ch'. while( *pszStr != 0 && *pszStr != '\"' ) pszStr++; // Have reached end of string without finding closing ", return now. if (*pszStr == 0) break; } pszStr++; } return pszStr; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // This is a very hacky function that will strip quotes. // Note it chages the contents of the buffer passed to it!! LPSTR StripQuotes(LPSTR pszStr) { if(!pszStr) return NULL; UINT uEnd = lstrlenA(pszStr); if(uEnd > 0 && pszStr[uEnd-1] == '"' && *pszStr == '"') { pszStr[uEnd-1] = 0; pszStr++; } return pszStr; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // DWORD WINAPI LaunchInfCommand(void *p) { HRESULT hr = S_OK; INF_ARGUEMENTS *pinfArgs = (INF_ARGUEMENTS *)p; if(pinfArgs->dwType == InfExCommand) { CABINFO cabinfo; cabinfo.pszCab = pinfArgs->szCab; cabinfo.pszInf = pinfArgs->szInfname; cabinfo.pszSection = pinfArgs->szSection; lstrcpy(cabinfo.szSrcPath, pinfArgs->szDir); cabinfo.dwFlags = pinfArgs->dwFlags; hr = ExecuteCab(NULL, &cabinfo, 0); } else { hr = RunSetupCommand(NULL, pinfArgs->szInfname, lstrlen(pinfArgs->szSection) ? pinfArgs->szSection : NULL, pinfArgs->szDir, NULL, NULL, pinfArgs->dwFlags, NULL ); } return hr; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // #define ABOUTTWODAYSTIME 0x000000C9 void CleanupDir(LPSTR lpDir) { char szFile[MAX_PATH]; WIN32_FIND_DATA fileData; HANDLE hFindFile; FILETIME currenttime; if ( lpDir == NULL || *lpDir == '\0' ) return; lstrcpy( szFile, lpDir ); if ( szFile[ lstrlen(szFile)-1 ] != '\\' ) lstrcat( szFile, "\\" ); lstrcat( szFile, "*.tmp" ); hFindFile = FindFirstFile( szFile, &fileData ); if ( hFindFile == INVALID_HANDLE_VALUE ) return; do { if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { if ( lstrcmp( fileData.cFileName, "." ) == 0 || lstrcmp( fileData.cFileName, ".." ) == 0 ) continue; GetSystemTimeAsFileTime(¤ttime); if( ( currenttime.dwHighDateTime > fileData.ftLastWriteTime.dwHighDateTime ) && ( currenttime.dwHighDateTime - fileData.ftLastWriteTime.dwHighDateTime > ABOUTTWODAYSTIME)) { lstrcpy( szFile, lpDir ); if ( szFile[ lstrlen(szFile)-1 ] != '\\' ) lstrcat( szFile, "\\" ); // delete the sub-dir lstrcat( szFile, fileData.cFileName ); SetFileAttributes(szFile, FILE_ATTRIBUTE_NORMAL ); DelNode( szFile, 0 ); } } else continue; } while ( FindNextFile( hFindFile, &fileData ) ); FindClose( hFindFile ); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // DWORD WINAPI CleanUpAllDirs(LPVOID pv) { char szDir[MAX_PATH]; UINT uType; DllAddRef(); if(g_szWindowsDir[0] == 0) { GetWindowsDirectory(g_szWindowsDir, sizeof(g_szWindowsDir)); } lstrcpy( szDir, "X:\\" ); for(char chDrive = 'A'; chDrive <= 'Z'; chDrive++) { szDir[0] = chDrive; if (IsUsableDrive(szDir)) { if(chDrive == g_szWindowsDir[0]) lstrcpy(szDir, g_szWindowsDir); AddPath(szDir, MSDOWNLOAD); CleanupDir(szDir); szDir[3] = 0; } } DllRelease(); return 0; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // BOOL IsCabFile(LPCSTR pszFile) { DWORD dwLen = lstrlenA(pszFile); if(dwLen <= 3) return FALSE; LPCSTR pszExt = pszFile + (dwLen - 4); if(lstrcmpiA(pszExt, ".cab") == 0) { return TRUE; } return FALSE; } typedef HRESULT (WINAPI *WINVERIFYTRUST) (HWND hwnd, GUID *pgActionID, LPVOID pWintrustData); // BUGBUG: get rid of this once moved to winbase.h!!! // #define WIN_TRUST_SUBJTYPE_CABINET \ // { 0xd17c5374, \ // 0xa392, \ // 0x11cf, \ // { 0x9d, 0xf5, 0x0, 0xaa, 0x0, 0xc1, 0x84, 0xe0 } \ // } // PublishedSoftwareNoBad {C6B2E8D0-E005-11cf-A134-00C04FD7BF43} #define WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI \ { 0xc6b2e8d0, \ 0xe005, \ 0x11cf, \ { 0xa1, 0x34, 0x0, 0xc0, 0x4f, 0xd7, 0xbf, 0x43 } \ } #define WINTRUST "wintrust.dll" // Verion number 5.0 #define AUTHENTICODE2_MS_VERSION 0x00050000 // Build number 1542.32 #define AUTHENTICODE2_LS_VERSION 0x06050020 //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // HRESULT CheckTrustIE3(LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI, WINVERIFYTRUST pwvt); HRESULT CheckTrustIE4(LPCSTR szURL, LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI, WINVERIFYTRUST pwvt); HRESULT WINAPI CheckTrustEx(LPCSTR szURL, LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI, DWORD dwReserved) { WINVERIFYTRUST pwvt; HINSTANCE hinst; char szPath[MAX_PATH] = { 0 }; DWORD dwVerMS = 0; DWORD dwVerLS = 0; HRESULT hr = S_OK; static BOOL st_CheckTrust = TRUE ; static BOOL st_Auth2Checked = FALSE; if (!st_CheckTrust) return S_FALSE ; if (!CheckImageHlp_dll()) { st_CheckTrust = FALSE; return S_FALSE ; } hinst = LoadLibrary(WINTRUST); if(!hinst) { // st_CheckTrust = FALSE ; return S_FALSE; } if (!st_Auth2Checked) { // If we get here, we know we can load Wintrust.dll GetSystemDirectory(szPath, sizeof(szPath)); AddPath(szPath, "Softpub.dll"); GetVersionFromFile(szPath, &dwVerMS, &dwVerLS, TRUE); // If softpubs version is less then the authenticode2 version don't call WinverifyTrust. if ((dwVerMS < AUTHENTICODE2_MS_VERSION) || ((dwVerMS == AUTHENTICODE2_MS_VERSION) && (dwVerLS < AUTHENTICODE2_LS_VERSION)) ) { hr = S_FALSE; st_CheckTrust = FALSE; } st_Auth2Checked = TRUE; } if (st_CheckTrust) { pwvt = (WINVERIFYTRUST) GetProcAddress(hinst, "WinVerifyTrust"); if(!pwvt) { FreeLibrary(hinst); st_CheckTrust = FALSE ; return S_FALSE; } // If we don't have a URL, use the IE3 methode of CheckTrust. hr = TRUST_E_PROVIDER_UNKNOWN; if (szURL) { // The new way of calling into WinVerifyTrust wll return TRUST_E_PROVIDER_UNKNOWN // if the new methode is not implemented on the system. __try { hr = CheckTrustIE4(szURL, szFilename, hwndForUI, bShowBadUI, pwvt); } __except(EXCEPTION_EXECUTE_HANDLER) { //Corrupted Java. hr = TRUST_E_FAIL; } } if (hr == TRUST_E_PROVIDER_UNKNOWN || hr == E_FAIL) { hr = CheckTrustIE3(szFilename, hwndForUI, bShowBadUI, pwvt); if (hr == S_FALSE) st_CheckTrust = FALSE; } } FreeLibrary(hinst); return hr; } HRESULT CheckTrustIE3(LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI, WINVERIFYTRUST pwvt) { HRESULT hr; LPWSTR pwszFilename = NULL; GUID PublishedSoftware = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE; GUID PublishedSoftwareNoBadUI = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI; GUID * ActionGUID; if(bShowBadUI) ActionGUID = &PublishedSoftware; else ActionGUID = &PublishedSoftwareNoBadUI; GUID SubjectPeImage = WIN_TRUST_SUBJTYPE_PE_IMAGE; GUID SubjectCAB = WIN_TRUST_SUBJTYPE_CABINET; WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT ActionData; WIN_TRUST_SUBJECT_FILE Subject; Subject.hFile = INVALID_HANDLE_VALUE; pwszFilename = OLESTRFROMANSI(szFilename); Subject.lpPath = pwszFilename; if (IsCabFile(szFilename)) { ActionData.SubjectType = &SubjectCAB; } else { ActionData.SubjectType = &SubjectPeImage; } ActionData.Subject = &Subject; ActionData.hClientToken = NULL; hr = pwvt( hwndForUI, ActionGUID, &ActionData); if(hr == E_FAIL) { // Hopefully, this is a general "trust is screwy" error. We will put // up our own ui to see if we can continue // Is this UI OK char szTitle[128]; char szMess[256]; LoadSz(IDS_SECURITYTITLE, szTitle, 128); LoadSz(IDS_SECURITY, szMess, 256); if(MessageBox(hwndForUI, szMess, szTitle, MB_YESNO | MB_ICONQUESTION) == IDYES) { hr = S_FALSE; } } if(pwszFilename) CoTaskMemFree(pwszFilename); return hr; } // {D41E4F1D-A407-11d1-8BC9-00C04FA30A41} #define COR_POLICY_PROVIDER_DOWNLOAD \ { 0xd41e4f1d, 0xa407, 0x11d1, {0x8b, 0xc9, 0x0, 0xc0, 0x4f, 0xa3, 0xa, 0x41 } } typedef HRESULT (WINAPI *COINTERNETCREATESECURITYMANAGER) ( IServiceProvider *pSP, IInternetSecurityManager **ppSM, DWORD dwReserved); HRESULT CheckTrustIE4(LPCSTR szURL, LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI, WINVERIFYTRUST pwvt) { GUID guidCor = COR_POLICY_PROVIDER_DOWNLOAD; GUID *pguidActionIDCor = &guidCor; LPWSTR pwszURL = NULL; GUID guidJava = JAVA_POLICY_PROVIDER_DOWNLOAD; GUID *pguidActionIDJava = &guidJava; WINTRUST_DATA wintrustData; WINTRUST_FILE_INFO fileData; JAVA_POLICY_PROVIDER javaPolicyData; HRESULT hr = S_OK; HANDLE hFile = INVALID_HANDLE_VALUE; HINSTANCE hUrlmon = NULL; IInternetSecurityManager *pSecMgr = NULL; DWORD dwZone; hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { if (hwndForUI == INVALID_HANDLE_VALUE) bShowBadUI = FALSE; pwszURL = OLESTRFROMANSI(szURL); memset(&wintrustData, 0, sizeof(wintrustData)); memset(&fileData, 0, sizeof(fileData)); memset(&javaPolicyData, 0, sizeof(javaPolicyData)); javaPolicyData.cbSize = sizeof(JAVA_POLICY_PROVIDER); javaPolicyData.VMBased = FALSE; // obsolete: noone pays attention to this javaPolicyData.fNoBadUI = !bShowBadUI; javaPolicyData.pwszZone = pwszURL; javaPolicyData.pZoneManager = NULL; // Use a file handle, so that in case trust has to put up UI the path // to the local file does not show in hte UI if we actually downloaded the // file from a URL. fileData.cbStruct = sizeof(WINTRUST_FILE_INFO); fileData.pcwszFilePath = pwszURL; fileData.hFile = hFile; wintrustData.cbStruct = sizeof(WINTRUST_DATA); wintrustData.pPolicyCallbackData = &javaPolicyData; if (hwndForUI == INVALID_HANDLE_VALUE) wintrustData.dwUIChoice = WTD_UI_NONE; else if(bShowBadUI) wintrustData.dwUIChoice = WTD_UI_ALL; else wintrustData.dwUIChoice = WTD_UI_NOBAD; wintrustData.dwUnionChoice = WTD_CHOICE_FILE; wintrustData.pFile = &fileData; hr = pwvt( hwndForUI, pguidActionIDCor, &wintrustData); if (hr == TRUST_E_PROVIDER_UNKNOWN) { hr = pwvt( hwndForUI, pguidActionIDJava, &wintrustData); } // BUGBUG: Check with Vatsan about this bugbug. // this works around a wvt bug that returns 0x57 (success) when // you hit No to an unsigned control if (SUCCEEDED(hr) && hr != S_OK) { hr = TRUST_E_FAIL; } if (SUCCEEDED(hr)) { hUrlmon = LoadLibrary("urlmon.dll"); if (hUrlmon) { COINTERNETCREATESECURITYMANAGER pcicsm; pcicsm = (COINTERNETCREATESECURITYMANAGER) GetProcAddress(hUrlmon, "CoInternetCreateSecurityManager"); if (pcicsm) pcicsm(NULL, &pSecMgr, NULL); } if ((javaPolicyData.pbJavaTrust == NULL) || (!javaPolicyData.pbJavaTrust->fAllActiveXPermissions) || (pSecMgr && SUCCEEDED(pSecMgr->MapUrlToZone(pwszURL, &dwZone, 0)) && dwZone == URLZONE_LOCAL_MACHINE && FAILED(javaPolicyData.pbJavaTrust->hVerify))) hr = TRUST_E_FAIL; if (hUrlmon) FreeLibrary(hUrlmon); } if (javaPolicyData.pbJavaTrust) CoTaskMemFree(javaPolicyData.pbJavaTrust); if(pwszURL) CoTaskMemFree(pwszURL); CloseHandle(hFile); if (pSecMgr) pSecMgr->Release(); } return hr; } HRESULT WINAPI CheckTrust(LPCSTR szFilename, HWND hwndForUI, BOOL bShowBadUI) { return CheckTrustEx(NULL, szFilename, hwndForUI, bShowBadUI, NULL); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // DWORD GetStringField(LPSTR szStr, UINT uField, LPSTR szBuf, UINT cBufSize) { LPSTR pszBegin = szStr; LPSTR pszEnd; UINT i = 0; DWORD dwToCopy; if(cBufSize == 0) return 0; szBuf[0] = 0; if(szStr == NULL) return 0; while(*pszBegin != 0 && i < uField) { pszBegin = FindChar(pszBegin, ','); if(*pszBegin != 0) pszBegin++; i++; } // we reached end of string, no field if(*pszBegin == 0) { return 0; } pszEnd = FindChar(pszBegin, ','); while(pszBegin <= pszEnd && *pszBegin == ' ') pszBegin++; while(pszEnd > pszBegin && *(pszEnd - 1) == ' ') pszEnd--; if(pszEnd > (pszBegin + 1) && *pszBegin == '"' && *(pszEnd-1) == '"') { pszBegin++; pszEnd--; } dwToCopy = (DWORD)(pszEnd - pszBegin + 1); if(dwToCopy > cBufSize) dwToCopy = cBufSize; lstrcpynA(szBuf, pszBegin, dwToCopy); return dwToCopy - 1; } DWORD GetIntField(LPSTR szStr, UINT uField, DWORD dwDefault) { char szNumBuf[16]; if(GetStringField(szStr, uField, szNumBuf, sizeof(szNumBuf)) == 0) return dwDefault; else return AtoL(szNumBuf); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPSTR BuildDependencyString(LPSTR pszName,LPSTR pszOwner) { LPSTR pszRet = NULL; if(pszOwner) { char szBuf[128]; LoadSz(IDS_DEPENDNAME, szBuf, sizeof(szBuf)); pszRet = new char[lstrlenA(pszName) + lstrlenA(szBuf) + lstrlenA(pszOwner) + 25]; if(pszRet) wsprintf(pszRet, szBuf, pszName, pszOwner); } else { pszRet = new char[lstrlenA(pszName) + 1]; if(pszRet) lstrcpyA(pszRet, pszName); } return pszRet; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPWSTR ParseURLW(BSTR str) { LPWSTR pwszTemp; if(str == NULL || *str == '\0') return NULL; pwszTemp = str + SysStringLen(str) - 1; while(pwszTemp >= str && *pwszTemp != '\\' && *pwszTemp != '/') pwszTemp--; return pwszTemp + 1; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPSTR ParseURLA(LPCSTR str) { LPSTR pszTemp; if(str == NULL || *str == '\0') return NULL; pszTemp = (LPSTR)str + lstrlen(str) - 1; while(pszTemp >= str && *pszTemp != '\\' && *pszTemp != '/') pszTemp--; return pszTemp + 1; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPSTR MakeAnsiStrFromAnsi(LPSTR psz) { LPSTR pszTmp; if(psz == NULL) return NULL; pszTmp = (LPSTR) CoTaskMemAlloc(lstrlenA(psz) + 1); if(pszTmp) lstrcpyA(pszTmp, psz); return pszTmp; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPSTR CopyAnsiStr(LPCSTR psz) { LPSTR pszTmp; if(psz == NULL) return NULL; pszTmp = (LPSTR) new char[lstrlenA(psz) + 1]; if(pszTmp) lstrcpyA(pszTmp, psz); return pszTmp; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // BOOL DeleteKeyAndSubKeys(HKEY hkIn, LPSTR pszSubKey) { HKEY hk; TCHAR szTmp[MAX_PATH]; DWORD dwTmpSize; long l; BOOL f; l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_READ | KEY_WRITE, &hk); if (l != ERROR_SUCCESS) return FALSE; // loop through all subkeys, blowing them away. // f = TRUE; while (f) { dwTmpSize = MAX_PATH; l = RegEnumKeyEx(hk, 0, szTmp, &dwTmpSize, 0, NULL, NULL, NULL); if (l != ERROR_SUCCESS) break; f = DeleteKeyAndSubKeys(hk, szTmp); } // there are no subkeys left, [or we'll just generate an error and return FALSE]. // let's go blow this dude away. // RegCloseKey(hk); l = RegDeleteKey(hkIn, pszSubKey); return (l == ERROR_SUCCESS) ? TRUE : FALSE; } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // int StringFromGuid(const CLSID* piid, LPTSTR pszBuf) { return wsprintf(pszBuf, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), piid->Data1, piid->Data2, piid->Data3, piid->Data4[0], piid->Data4[1], piid->Data4[2],piid->Data4[3], piid->Data4[4], piid->Data4[5], piid->Data4[6], piid->Data4[7]); } //=--------------------------------------------------------------------------= // Function name here //=--------------------------------------------------------------------------= // Function description // // Parameters: // // Returns: // // Notes: // LPWSTR MakeWideStrFromAnsi(LPSTR psz, BYTE bType) { LPWSTR pwsz; int i; // arg checking. // if (!psz) return NULL; // compute the length of the required BSTR // i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0); if (i <= 0) return NULL; // allocate the widestr // switch (bType) { case STR_BSTR: // -1 since it'll add it's own space for a NULL terminator // pwsz = (LPWSTR) SysAllocStringLen(NULL, i - 1); break; case STR_OLESTR: pwsz = (LPWSTR) CoTaskMemAlloc(i * sizeof(WCHAR)); break; default: break; } if (!pwsz) return NULL; MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i); pwsz[i - 1] = 0; return pwsz; } #define UNINSTALL_BRANCH "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" BOOL UninstallKeyExists(LPCSTR pszUninstallKey) { HKEY hUninstallKey = NULL; char szUninstallStr[512]; if (!pszUninstallKey) // If the pointer is NULL, assume installed return TRUE; lstrcpyA(szUninstallStr, UNINSTALL_BRANCH); lstrcatA(szUninstallStr, "\\"); lstrcatA(szUninstallStr, pszUninstallKey); if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, szUninstallStr, 0, KEY_READ, &hUninstallKey) == ERROR_SUCCESS) { RegCloseKey(hUninstallKey); return TRUE; } else return FALSE; } void AddTempToLikelyExtractDrive(DWORD dwTempDLSpace, DWORD dwTempExSpace, char chInstallDrive, char chDownloadDrive, DWORD *pdwWinDirReq, DWORD *pdwInsDirReq, DWORD *pdwDownloadDirReq) { DWORD dwExNeeded, dwNeeded; DWORD dwVolFlags, dwCompressFactor; char szRoot[4]; DWORD dwInsDirNeeded = dwTempDLSpace + dwTempExSpace; DWORD dwInstallDriveCompress = 10; lstrcpy(szRoot, "A:\\"); while ( szRoot[0] <= 'Z' ) { if (!IsUsableDrive( szRoot ) ) { szRoot[0]++; continue; } if(!GetVolumeInformation(szRoot, NULL, 0, NULL, NULL, &dwVolFlags, NULL, 0)) { szRoot[0]++; continue; } if(dwVolFlags & FS_VOL_IS_COMPRESSED) { dwCompressFactor = 19; if(szRoot[0] == chInstallDrive) dwInstallDriveCompress = 19; } else dwCompressFactor = 10; // Decide how much we need if we extract to this drive dwExNeeded = (dwTempDLSpace * dwCompressFactor)/10 + dwTempExSpace; dwNeeded = 0; // if the install dir, add what is going to install dir if(szRoot[0] == chInstallDrive) dwNeeded += *pdwInsDirReq; // if it is the windows dir, add what goes to win dir if(szRoot[0] == g_szWindowsDir[0]) dwNeeded += *pdwWinDirReq; // BUGBUG: compression on this guy? if(szRoot[0] == chDownloadDrive) dwNeeded += ((*pdwDownloadDirReq * dwCompressFactor)/10); dwNeeded += dwExNeeded; // if this drive has enough bump Req if appropiate if(IsEnoughSpace(szRoot, dwNeeded )) { if(szRoot[0] == chInstallDrive) { *pdwInsDirReq += dwExNeeded; } else if(szRoot[0] == chDownloadDrive) *pdwDownloadDirReq += dwExNeeded; else if(szRoot[0] == g_szWindowsDir[0]) *pdwWinDirReq += dwExNeeded; return; } szRoot[0]++; } // if we get here, NO drive has enough space. // Add to install dir here *pdwInsDirReq += (dwTempDLSpace * dwCompressFactor)/10 + dwTempExSpace; } #define INSTALLCHECK_VALUE 0 #define INSTALLCHECK_DATA 1 #define INSTALLCHECK_NOTSUPPORTED 2 // If you change the string below you also have to tell all clients which use this feature to change. // The clients are writing there success values under this key. #define REGSTR_SUCCESS_KEY "Software\\Microsoft\\Active Setup\\Install Check" BOOL SuccessCheck(LPSTR pszSuccessKey) { HKEY hKey = NULL; char szRegKey[512]; char szRegData[512]; DWORD dwSize; BOOL bInstalledSuccessfull = FALSE; if (!pszSuccessKey) // If the pointer is NULL, assume installed return TRUE; if (GetStringField(pszSuccessKey, INSTALLCHECK_NOTSUPPORTED, szRegKey, sizeof(szRegKey))) return FALSE; // This format is not yet supported if (GetStringField(pszSuccessKey, INSTALLCHECK_VALUE, szRegKey, sizeof(szRegKey)) == 0) return TRUE; // There is not Registry value to check for. Assume OK if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_SUCCESS_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(szRegData); if (RegQueryValueEx(hKey, szRegKey, NULL, NULL, (LPBYTE)szRegData, &dwSize) == ERROR_SUCCESS) { bInstalledSuccessfull = TRUE; // If a data filed is specified, check if the value data compare if (GetStringField(pszSuccessKey, INSTALLCHECK_DATA, szRegKey, sizeof(szRegKey))) { bInstalledSuccessfull = (lstrcmpi(szRegKey, szRegData) == 0); } } RegCloseKey(hKey); } return bInstalledSuccessfull; } DWORD WaitForEvent(HANDLE hEvent, HWND hwnd) { BOOL fQuit = FALSE; BOOL fDone = FALSE; DWORD dwRet; while(!fQuit && !fDone) { dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); // Give abort the highest priority if(dwRet == WAIT_OBJECT_0) { fDone = TRUE; } else { MSG msg; // read all of the messages in this next loop // removing each message as we read it while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(!hwnd || !IsDialogMessage(hwnd, &msg)) { // if it's a quit message we're out of here if (msg.message == WM_QUIT) fQuit = TRUE; else { // otherwise dispatch it TranslateMessage(&msg); DispatchMessage(&msg); } } // end of PeekMessage while loop } } } return (fQuit ? EVENTWAIT_QUIT : EVENTWAIT_DONE); } // If .CIF command switch has #W or #w, expand it to Windows directory. Otherwise, do nothing. // Input: lpBuf : the original switches // dwSize : buffer size // Outout: lpBuf : expanded switches // void ExpandString( LPSTR lpBuf, DWORD dwSize ) { LPSTR pTmp, pTmp1; char ch; if ( !lpBuf || !*lpBuf || !dwSize ) return; pTmp = ANSIStrChr( lpBuf, '#' ); if ( pTmp ) { pTmp1 = CharNext( pTmp ); ch = (char)CharUpper((LPSTR) *pTmp1); if ( ch == 'W' ) { PSTR pTmpBuf; // #W... => ... if ( dwSize < (DWORD)( lstrlen(lpBuf) + lstrlen(g_szWindowsDir) - 1 ) ) return; // should never be here pTmpBuf = (LPSTR)LocalAlloc( LPTR, dwSize ); if ( pTmpBuf ) { *pTmp = '\0'; lstrcpy( pTmpBuf, lpBuf ); lstrcat( pTmpBuf, g_szWindowsDir ); lstrcat( pTmpBuf, CharNext(pTmp1) ); // re-set the output string lstrcpy( lpBuf, pTmpBuf ); LocalFree( pTmpBuf ); } } else if ( ch == '#' ) { // ##... => #... MoveMemory( pTmp, pTmp1, lstrlen(pTmp1)+1 ); } } } void DeleteFilelist(LPCSTR pszFilelist) { LPSTR pszSections, pszSectionsPreFail, pszTemp; DWORD dwSize = ALLOC_CHUNK_SIZE; DWORD dwRead; // Get a list of all sections // // BUGBUG: Write this so only one call to GetPrivateProfile exists pszSections = (LPSTR) malloc(dwSize); // Bail out if no memory if(!pszSections) return; dwRead = GetPrivateProfileStringA(NULL, NULL, "", pszSections, dwSize, pszFilelist); while( dwRead >= (dwSize - 2) ) { dwSize += ALLOC_CHUNK_SIZE; pszSectionsPreFail = pszSections; #pragma prefast(suppress: 308, "Noise - pointer was saved") pszSections = (LPSTR) realloc(pszSections, dwSize); if(!pszSections) { free(pszSectionsPreFail); dwRead = 0; break; } dwRead = GetPrivateProfileStringA(NULL, NULL, "", pszSections, dwSize, pszFilelist); } pszTemp = pszSections; dwSize = lstrlenA(pszTemp); while(dwSize != 0) { WritePrivateProfileSection(pszTemp, NULL, pszFilelist); pszTemp += (dwSize + 1); dwSize = lstrlenA(pszTemp); } free(pszSections); } BOOL WaitForMutex(HANDLE hMutex) { BOOL fQuit = FALSE; while (MsgWaitForMultipleObjects(1, &hMutex, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0) { MSG msg; while (!fQuit && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) fQuit = TRUE; else { TranslateMessage(&msg); DispatchMessage(&msg); } } } return fQuit; } BOOL IsNT() { static int st_IsNT = 0xffff; if(st_IsNT == 0xffff) { OSVERSIONINFO verinfo; // Version Check verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if ( GetVersionEx( &verinfo ) != FALSE ) { if( verinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) st_IsNT = 0; else if ( verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) st_IsNT = 1; } } return (st_IsNT == 1) ? TRUE : FALSE; } HINSTANCE InitSetupLib(LPCSTR pszInfName, HINF *phinf) { HINSTANCE hInst = NULL; *phinf = NULL; if( IsNT() ) { hInst = LoadLibrary("setupapi.dll"); OpenINFEngine( pszInfName, NULL, 0, phinf, NULL ); } else { hInst = LoadLibrary("w95inf32.dll"); } return hInst; } void FreeSetupLib(HINSTANCE hInst, HINF hInf) { if(hInf) CloseINFEngine(hInf); if(hInst) FreeLibrary(hInst); } HRESULT MyTranslateInfString( PCSTR pszInfFilename, PCSTR pszInstallSection, PCSTR pszTranslateSection, PCSTR pszTranslateKey, PSTR pszBuffer, DWORD dwBufferSize, PDWORD pdwRequiredSize, HINF hInf ) { HRESULT hr; if(IsNT() && hInf) { hr = TranslateInfStringEx( hInf, pszInfFilename, pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize, pdwRequiredSize, NULL ); } else { hr = TranslateInfString( pszInfFilename, pszInstallSection, pszTranslateSection, pszTranslateKey, pszBuffer, dwBufferSize, pdwRequiredSize, NULL); } return hr; } #define UNUSED_STRING "xxx" HRESULT MyTranslateString( LPCSTR pszCif, LPCSTR pszID, LPCSTR pszTranslateKey, LPSTR pszBuffer, DWORD dwBufferSize) { HRESULT hr = E_FAIL; char szTemp[512]; if(GetPrivateProfileString(pszID, pszTranslateKey, "", pszBuffer, dwBufferSize, pszCif)) { //bad code DWORD dwLen = lstrlen(pszBuffer); if(dwLen > 2) { // Cut the last %, and then look up in string section if(pszBuffer[0] == '%' && pszBuffer[dwLen - 1] == '%') { pszBuffer[dwLen - 1] = 0; GetPrivateProfileString("Strings", pszBuffer + 1, UNUSED_STRING, szTemp, sizeof(szTemp), pszCif); if(lstrcmp(UNUSED_STRING, szTemp) != 0) lstrcpyn(pszBuffer, szTemp, dwBufferSize); else pszBuffer[dwLen - 1] = '%'; } } hr = NOERROR; } return hr; } // add the quotes around the string DWORD MyWritePrivateProfileString( LPCSTR pszSec, LPCSTR pszKey, LPCSTR pszData, LPCSTR pszFile) { LPSTR pszBuf; DWORD dwOut = 0; pszBuf = (LPSTR)LocalAlloc( LPTR, lstrlen(pszData)+8 ); if ( !pszBuf ) return dwOut; lstrcpy( pszBuf, "\"" ); lstrcat( pszBuf, pszData ); lstrcat( pszBuf, "\"" ); dwOut = WritePrivateProfileString(pszSec, pszKey, pszBuf, pszFile); LocalFree(pszBuf); return dwOut; } HRESULT WriteTokenizeString(LPCSTR pszCif, LPCSTR pszID, LPCSTR pszTranslateKey, LPCSTR pszBuffer) { HRESULT hr = E_FAIL; char szTemp[MAX_PATH]; LPCSTR pszKeyname, pszSecname; pszKeyname = pszTranslateKey; pszSecname = pszID; if(GetPrivateProfileString(pszID, pszTranslateKey, "", szTemp, sizeof(szTemp), pszCif)) { //bad code DWORD dwLen = lstrlen(szTemp); if(dwLen > 2) { // Cut the last %, and then look up in string section if(szTemp[0] == '%' && szTemp[dwLen - 1] == '%') { szTemp[dwLen - 1] = 0; pszKeyname = &szTemp[1]; pszSecname = "strings"; } } } if (MyWritePrivateProfileString(pszSecname, pszKeyname, pszBuffer, pszCif)) hr = NOERROR; return hr; } HWND GetVersionConflictHWND() { char szBuf[256]; LoadSz(IDS_VERSIONCONFLICT, szBuf, sizeof(szBuf)); HWND hVersionConflict = FindWindowEx(NULL, NULL, (LPCSTR) SEARCHFORCONFLICT_CLASS, szBuf ); if(!hVersionConflict) { LoadSz(IDS_VERSIONCONFLICTNT, szBuf, sizeof(szBuf)); hVersionConflict = FindWindowEx(NULL, NULL, (LPCSTR) SEARCHFORCONFLICT_CLASS, szBuf ); } return hVersionConflict; } HRESULT WINAPI CheckForVersionConflict() { HWND hVersionConflict = GetVersionConflictHWND(); if(hVersionConflict) BOOL foo = SetForegroundWindow(hVersionConflict); return S_OK; } int CompareLocales(LPCSTR pcszLoc1, LPCSTR pcszLoc2) { int ret; if(pcszLoc1[0] == '*' || pcszLoc2[0] == '*') ret = 0; else ret = lstrcmpi(pcszLoc1, pcszLoc2); return ret; } HRESULT CreateTempDirOnMaxDrive(LPSTR pszDir, DWORD dwBufSize) { char szRoot[] = "A:\\"; char szDownloadDrive[] = "?:\\"; char szDir[MAX_PATH]; char szUnique[MAX_PATH]; DWORD dwMaxFree = 0; DWORD dwDriveFree; if(pszDir) pszDir[0] = 0; // Check all loacle drives for diskspace and take the one with the most. while ( szRoot[0] <= 'Z' ) { // even the drive type is OK, verify the drive has valid connection // if (!IsUsableDrive( szRoot ) ) { szRoot[0]++; continue; } if(!IsDirWriteable(szRoot)) { szRoot[0]++; continue; } dwDriveFree = GetSpace(szRoot); if (dwDriveFree > dwMaxFree) { dwMaxFree = dwDriveFree; szDownloadDrive[0] = szRoot[0]; } szRoot[0]++; } if(szDownloadDrive[0] == '?') return E_FAIL; lstrcpy(szDir, szDownloadDrive); // if our suitable drive happens also to be the windows drive, // create msdownld.tmp of of it. if(szDownloadDrive[0] == g_szWindowsDir[0]) lstrcpy(szDir, g_szWindowsDir); AddPath( szDir, MSDOWNLOAD ); if ( !IfNotExistCreateDir( szDir, TRUE, TRUE) ) return E_FAIL; // if ( !GetUniqueFileName(szDir,"AS", 0, szUnique) ) return E_FAIL; lstrcpy(szDir, szUnique); if ( !IfNotExistCreateDir( szDir, FALSE, FALSE) ) return E_FAIL; AddPath( szDir, "" ); if ( (DWORD) lstrlen(szDir)+1 > dwBufSize ) return ( E_INVALIDARG ); // success lstrcpy( pszDir, szDir ); return S_OK; } /* * enabled or restores Sage * bRestore TRUE means restore, otherwise disable */ void EnableSage(BOOL bRestore) { //MBD 6-22: MUST USE stdcall convention when accessing sage.dll typedef long (__stdcall *PFNDLL)(int); HINSTANCE hSageAPI; PFNDLL pfnSageEnable; static int restore = ENABLE_AGENT; //initialize to valid value... hSageAPI = LoadLibrary("SAGE.DLL"); if (hSageAPI != NULL) { pfnSageEnable = (PFNDLL) GetProcAddress(hSageAPI,"System_Agent_Enable"); if(pfnSageEnable) { if(bRestore) { (pfnSageEnable)(restore); } else { if(ENABLE_AGENT == (restore = (pfnSageEnable)(GET_AGENT_STATUS))) { (pfnSageEnable)(DISABLE_AGENT); } } } FreeLibrary(hSageAPI); } } void EnableScreenSaver(BOOL bRestore) { static BOOL bScreenSaver = FALSE; if (bRestore) { SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, bScreenSaver, 0 , 0); bScreenSaver = FALSE; // reset the static to be able to disable the screensaver again. } else { // Only if the static is false call this again, // otherwise we did call this function already. if (!bScreenSaver) { SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, FALSE, &bScreenSaver, 0); SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0 , 0); } } } void EnableDiskCleaner(BOOL bRestore) { static HANDLE hDiskCleaner = NULL; if (bRestore) { if (hDiskCleaner) { CloseHandle(hDiskCleaner); hDiskCleaner = NULL; } } else { hDiskCleaner = CreateEvent(NULL, FALSE, FALSE, "DisableLowDiskWarning"); } } #if 0 typedef HRESULT (WINAPI *COINTERNETCREATESECURITYMANAGER) ( IServiceProvider *pSP, IInternetSecurityManager **ppSM, DWORD dwReserved); DWORD IsUrlSaveToDownloadFrom(LPSTR lpszURL) { HRESULT hr; BOOL bOK = FALSE; DWORD dwPolicy = URLPOLICY_QUERY; // In the default case we do checktrust HINSTANCE hUrlmon; COINTERNETCREATESECURITYMANAGER pcicsm; hUrlmon = LoadLibrary("urlmon.dll"); if (hUrlmon) { pcicsm = (COINTERNETCREATESECURITYMANAGER) GetProcAddress(hUrlmon, "CoInternetCreateSecurityManager"); if (pcicsm) { IInternetSecurityManager *InternetSecurityManager; LPWSTR lpwszURL = NULL; DWORD dwSize; hr = pcicsm(NULL, &InternetSecurityManager, NULL); if (SUCCEEDED(hr)) { dwSize = sizeof(dwPolicy); lpwszURL = MakeWideStrFromAnsi(lpszURL, STR_OLESTR); hr = InternetSecurityManager->ProcessUrlAction(lpwszURL, URLACTION_DOWNLOAD_SIGNED_ACTIVEX, (BYTE*)&dwPolicy, dwSize, NULL, NULL, PUAF_NOUI, NULL); wsprintf(szLogBuf, "InternetSecurityManager->ProcessUrlAction on :%s: Policy :%ld:", lpszURL, dwPolicy); MessageBox(NULL, szLogBuf, "TEST", MB_OK| MB_SETFOREGROUND); if (GetUrlPolicyPermissions(dwPolicy) != URLPOLICY_ALLOW) { hr = InternetSecurityManager->ProcessUrlAction(lpwszURL, URLACTION_DOWNLOAD_UNSIGNED_ACTIVEX, (BYTE*)&dwPolicy, dwSize, NULL, NULL, PUAF_NOUI, NULL); wsprintf(szLogBuf, "InternetSecurityManager->ProcessUrlAction on :%s: Policy :%ld:", lpszURL, dwPolicy); MessageBox(NULL, szLogBuf, "TEST", MB_OK| MB_SETFOREGROUND); } if (lpwszURL) CoTaskMemFree(lpwszURL); InternetSecurityManager->Release(); } } FreeLibrary(hUrlmon); } return dwPolicy; } #endif BOOL PathIsFileSpec(LPCSTR lpszPath) { for (; *lpszPath; lpszPath = CharNext(lpszPath)) { if (*lpszPath == '\\' || *lpszPath == ':') return FALSE; } return TRUE; } const char c_gszRegstrPathIExplore[] = REGSTR_PATH_APPPATHS "\\iexplore.exe"; HRESULT GetIEPath(LPSTR pszPath, DWORD dwSize) { HRESULT hr = NOERROR; UINT i; DWORD dwType; HKEY hKey; // findout where ie is, append on cif name if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_gszRegstrPathIExplore, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { if ((RegQueryValueEx(hKey, NULL, 0, &dwType, (LPBYTE)pszPath, &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ)) { GetParentDir(pszPath); } else hr = E_INVALIDARG; RegCloseKey(hKey); } else hr = E_FAIL; return hr; } DWORD MyGetFileSize(LPCSTR pszFilename) { DWORD dwSize; WIN32_FIND_DATA fileData; HANDLE hFindFile; dwSize = 0; hFindFile = FindFirstFile( pszFilename, &fileData ); if ( hFindFile != INVALID_HANDLE_VALUE ) { if (fileData.nFileSizeHigh == 0) dwSize = fileData.nFileSizeLow; else dwSize = (DWORD)-1; FindClose( hFindFile ); } return dwSize; } WORD GetNTProcessorArchitecture(void) { static WORD wNTProcArch = -1 ; SYSTEM_INFO System_info; // If we have calculated this before just pass that back. // else find it now. // if (wNTProcArch == (WORD)-1) { GetSystemInfo(&System_info); wNTProcArch = System_info.wProcessorArchitecture; } return wNTProcArch; } DWORD GetCurrentPlatform() { static DWORD dwPlatform = 0xffffffff; if(dwPlatform != 0xffffffff) return dwPlatform; OSVERSIONINFO VerInfo; VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&VerInfo); if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { // Running NT if (GetNTProcessorArchitecture() == PROCESSOR_ARCHITECTURE_ALPHA) { dwPlatform = PLATFORM_NT5ALPHA; if (VerInfo.dwMajorVersion == 4) dwPlatform = PLATFORM_NT4ALPHA; } else { dwPlatform = PLATFORM_NT5; if (VerInfo.dwMajorVersion == 4) dwPlatform = PLATFORM_NT4; } } else { // Running Windows 9x dwPlatform = PLATFORM_WIN98; if (VerInfo.dwMinorVersion == 0) dwPlatform = PLATFORM_WIN95; else if (VerInfo.dwMinorVersion == 90) dwPlatform = PLATFORM_MILLEN; } return dwPlatform; } BOOL FNeedGrpConv() { char szSetupIni[MAX_PATH]; if(GetWindowsDirectory(szSetupIni, sizeof(szSetupIni))) { AddPath(szSetupIni, "setup.ini"); return(GetFileAttributes(szSetupIni) != 0xffffffff); } return FALSE; } void CopyCifString(LPCSTR pcszSect, LPCSTR pcszKey, LPCSTR pcszCifSrc, LPCSTR pcszCifDest) { char szField[MAX_PATH]; char szString[MAX_PATH]; LPSTR pszPercent; if (GetPrivateProfileString(pcszSect, pcszKey, "", szField, sizeof(szField), pcszCifSrc) && (szField[0] == '%')) { pszPercent = ANSIStrChr(&szField[1], '%'); if (pszPercent) { *pszPercent = '\0'; GetPrivateProfileString("Strings", &szField[1], "", szString, sizeof(szString), pcszCifSrc); WritePrivateProfileString("Strings", &szField[1], szString, pcszCifDest); } } } //--------------------------------------------------------- // Function to log the Date/Time stamp for each Component. //--------------------------------------------------------- void GetTimeDateStamp(LPSTR lpLogBuf) { SYSTEMTIME SystemTime; GetLocalTime(&SystemTime); wsprintf(lpLogBuf, "Date:%d/%d/%d (M/D/Y) Time:%d:%d:%d", SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); } HRESULT WINAPI DownloadFile(LPCSTR szURL, LPCSTR szFilename, HWND hwnd, BOOL bCheckTrust, BOOL bShowBadUI) { HRESULT hr; char szTempfile[MAX_PATH]; char szTemp[MAX_PATH]; CDownloader *pDL = new CDownloader(); if(!pDL) return E_OUTOFMEMORY; hr = pDL->SetupDownload(szURL, NULL, 0, NULL); szTempfile[0] = 0; if(SUCCEEDED(hr)) { hr = pDL->DoDownload(szTempfile, sizeof(szTempfile)); } pDL->Release(); if(SUCCEEDED(hr)) { if (bCheckTrust) { hr = ::CheckTrustEx(szURL, szTempfile, bShowBadUI?hwnd:(HWND)INVALID_HANDLE_VALUE, bShowBadUI, NULL); } if(!CopyFile(szTempfile, szFilename, FALSE)) { hr = HRESULT_FROM_WIN32(GetLastError()); } } if(szTempfile[0] != 0) { GetParentDir(szTempfile); CleanUpTempDir(szTempfile); } return hr; } BOOL IsPatchableINF(LPTSTR pszInf) { TCHAR szBuf[MAX_PATH]; if (GetPrivateProfileInt("DefaultInstall", "Patching", 0, pszInf) || GetPrivateProfileString("DownloadFileSection", NULL, "", szBuf, sizeof(szBuf), pszInf)) return TRUE; else return FALSE; } PFNGETFILELIST g_pfnGetFileList = NULL; PFNDOWNLOADANDPATCHFILES g_pfnDownloadAndPatchFiles = NULL; PFNPROCESSFILESECTION g_pfnProcessFileSection = NULL; BOOL InitSRLiteLibs() { HINSTANCE hAdvpext = LoadLibrary(c_gszAdvpext); if (hAdvpext == NULL) return FALSE; g_pfnGetFileList = (PFNGETFILELIST) GetProcAddress(hAdvpext, "GetFileList"); g_pfnDownloadAndPatchFiles = (PFNDOWNLOADANDPATCHFILES) GetProcAddress(hAdvpext, "DownloadAndPatchFiles"); g_pfnProcessFileSection = (PFNPROCESSFILESECTION) GetProcAddress(hAdvpext, "ProcessFileSection"); if (g_pfnGetFileList == NULL || g_pfnDownloadAndPatchFiles == NULL || g_pfnProcessFileSection == NULL ) { FreeLibrary(hAdvpext); return FALSE; } else return TRUE; } void FreeSRLiteLibs() { HMODULE hMod; hMod = GetModuleHandle(c_gszAdvpext); if (hMod) FreeLibrary(hMod); } // For now, we're patching on any IE5 version, so we might // as well perform a check similar to ie5wzd BOOL IsPatchableIEVersion() { char szIE[MAX_PATH] = { 0 }; DWORD dwMSVer, dwLSVer; GetSystemDirectory(szIE, sizeof(szIE)); AddPath(szIE, "shdocvw.dll"); GetVersionFromFile(szIE, &dwMSVer, &dwLSVer, TRUE); return (dwMSVer >= 0x00050000); } BOOL IsCorrectAdvpExt() { DWORD dwMSVer, dwLSVer; GetVersionFromFile(c_gszAdvpext, &dwMSVer, &dwLSVer, TRUE); return (dwMSVer >= 0x00050032); } BOOL CheckImageHlp_dll() { char szFile[MAX_PATH] = { 0 }; DWORD dwMSVer, dwLSVer; GetSystemDirectory(szFile, sizeof(szFile)); AddPath(szFile, "imagehlp.dll"); GetVersionFromFile(szFile, &dwMSVer, &dwLSVer, TRUE); return (!(dwMSVer == 0x00040000) || !(dwLSVer == 0x04C90001)); }