////////////////////////////////////////////////////////////////////////////// // // SYSTEM: Windows Update AutoUpdate Client // // CLASS: N/A // MODULE: // FILE: helpers.CPP // DESC: This file contains utility functions // ////////////////////////////////////////////////////////////////////////////// #include "pch.h" #pragma hdrstop const LPTSTR HIDDEN_ITEMS_FILE = _T("hidden.xml"); const LPCTSTR AU_ENV_VARS::s_AUENVVARNAMES[] = {_T("AUCLTEXITEVT"),_T("EnableNo"), _T("EnableYes"), _T("RebootWarningMode"), _T("ManualReboot"), _T("StartTickCount")}; BOOL AU_ENV_VARS::ReadIn(void) { BOOL fRet = TRUE; if (!GetBOOLEnvironmentVar(s_AUENVVARNAMES[3], &m_fRebootWarningMode)) { // if not set, implies regular mode m_fRebootWarningMode = FALSE; } if (m_fRebootWarningMode) { if (!GetBOOLEnvironmentVar(s_AUENVVARNAMES[1], &m_fEnableNo) ||!GetBOOLEnvironmentVar(s_AUENVVARNAMES[2], &m_fEnableYes) ||!GetBOOLEnvironmentVar(s_AUENVVARNAMES[4], &m_fManualReboot) ||!GetDWordEnvironmentVar(s_AUENVVARNAMES[5], &m_dwStartTickCount) ||!GetStringEnvironmentVar(s_AUENVVARNAMES[0], m_szClientExitEvtName, ARRAYSIZE(m_szClientExitEvtName))) { DEBUGMSG("AU_ENV_VARS fails to read in"); return FALSE; } // DEBUGMSG("AU_ENV_VARS read in fEnableYes = %d, fEnableNo = %d, fManualReboot = %d, dwStartTickCount = %d", // m_fEnableYes, m_fEnableNo, m_fManualReboot, m_dwStartTickCount); } // DEBUGMSG("AU_ENV_VARS read in fRebootWarningMode = %d", m_fRebootWarningMode); return TRUE; } BOOL AU_ENV_VARS::WriteOut(LPTSTR szEnvBuf, size_t IN cchEnvBuf, BOOL IN fEnableYes, BOOL IN fEnableNo, BOOL IN fManualReboot, DWORD IN dwStartTickCount, LPCTSTR IN szClientExitEvtName) { TCHAR buf2[s_AUENVVARBUFSIZE]; m_fEnableNo = fEnableNo; m_fEnableYes = fEnableYes; m_fManualReboot = fManualReboot; m_dwStartTickCount = dwStartTickCount; m_fRebootWarningMode = TRUE; // DEBUGMSG("AU_ENV_VARS write out fEnableYes = %d, fEnableNo = %d, fManualReboot = %d, dwStartTickCount = %d", // fEnableYes, fEnableNo, fManualReboot, dwStartTickCount); if (FAILED(StringCchCopyEx( m_szClientExitEvtName, ARRAYSIZE(m_szClientExitEvtName), szClientExitEvtName, NULL, NULL, MISTSAFE_STRING_FLAGS))) { return FALSE; } *szEnvBuf = _T('\0'); for (int i = 0 ; i < ARRAYSIZE(s_AUENVVARNAMES); i++) { if (FAILED(GetStringValue(i, buf2, ARRAYSIZE(buf2))) || FAILED(StringCchCatEx(szEnvBuf, cchEnvBuf, s_AUENVVARNAMES[i], NULL, NULL, MISTSAFE_STRING_FLAGS)) || FAILED(StringCchCatEx(szEnvBuf, cchEnvBuf, _T("="), NULL, NULL, MISTSAFE_STRING_FLAGS)) || FAILED(StringCchCatEx(szEnvBuf, cchEnvBuf, buf2, NULL, NULL, MISTSAFE_STRING_FLAGS)) || FAILED(StringCchCatEx(szEnvBuf, cchEnvBuf, _T("&"), NULL, NULL, MISTSAFE_STRING_FLAGS))) { return FALSE; } } // DEBUGMSG("AU Env variable is %S", szEnvBuf); return TRUE; } HRESULT AU_ENV_VARS::GetStringValue(int index, LPTSTR buf, DWORD dwCchSize) { HRESULT hr = E_INVALIDARG; switch (index) { case 0: hr = StringCchCopyEx(buf, dwCchSize, m_szClientExitEvtName, NULL, NULL, MISTSAFE_STRING_FLAGS); break; case 1: hr = StringCchCopyEx(buf, dwCchSize, m_fEnableNo? _T("true") : _T("false"), NULL, NULL, MISTSAFE_STRING_FLAGS); break; case 2: hr = StringCchCopyEx(buf, dwCchSize, m_fEnableYes? _T("true") : _T("false"), NULL, NULL, MISTSAFE_STRING_FLAGS); break; case 3: hr = StringCchCopyEx(buf, dwCchSize, m_fRebootWarningMode ? _T("true") : _T("false"), NULL, NULL, MISTSAFE_STRING_FLAGS); break; case 4: hr = StringCchCopyEx(buf, dwCchSize, m_fManualReboot ? _T("true") : _T("false"), NULL, NULL, MISTSAFE_STRING_FLAGS); break; case 5: hr = StringCchPrintfEx(buf, dwCchSize, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("%lu"), m_dwStartTickCount); break; default: AUASSERT(FALSE); //should never be here break; } return hr; } BOOL AU_ENV_VARS::GetDWordEnvironmentVar(LPCTSTR szEnvVar, DWORD *pdwVal) { TCHAR szBuf[20]; *pdwVal = 0; if (GetStringEnvironmentVar(szEnvVar, szBuf, ARRAYSIZE(szBuf))) { // DEBUGMSG("WUAUCLT got environment variable %S = %S ", szEnvVar, szBuf); *pdwVal = wcstoul(szBuf, NULL , 10); return TRUE; } return FALSE; } BOOL AU_ENV_VARS::GetBOOLEnvironmentVar(LPCTSTR szEnvVar, BOOL *pfVal) { TCHAR szBuf[20]; if (GetStringEnvironmentVar(szEnvVar, szBuf, ARRAYSIZE(szBuf))) { // DEBUGMSG("WUAUCLT got environment variable %S = %S ", szEnvVar, szBuf); *pfVal =(0 == lstrcmpi(szBuf, _T("true"))); return TRUE; } return FALSE; } ///////////////////////////////////////////////////////////////////////////////////////////// // dwSize: size of szBuf in number of characters //////////////////////////////////////////////////////////////////////////////////////////// BOOL AU_ENV_VARS::GetStringEnvironmentVar(LPCTSTR szEnvVar, LPTSTR szBuf, DWORD dwSize) { // Assume szEnvVar is not a proper substring in for any parameters in szCmdLine. LPTSTR szCmdLine = GetCommandLine(); LPTSTR pTmp; DWORD index = 0; // DEBUGMSG("WUAUCLT read in command line %S", szCmdLine); if (NULL == szCmdLine || 0 == dwSize || (NULL == (pTmp = StrStr(szCmdLine, szEnvVar)))) { return FALSE; } pTmp += lstrlen(szEnvVar) + 1; //skip '=' while (_T('\0') != *pTmp && _T('&') != *pTmp) { if (index + 1 >= dwSize) { // insufficent buffer return FALSE; } szBuf[index++] = *pTmp++; } szBuf[index] = _T('\0'); // DEBUGMSG(" read in %S = %S", szEnvVar, szBuf); return TRUE; } #if 0 #ifdef DBG void DBGCheckEventState(LPSTR szName, HANDLE hEvt) { DWORD dwRet = WaitForSingleObject(hEvt, 0); DEBUGMSG("WUAU Event %s is %s signalled", szName,( WAIT_OBJECT_0 == dwRet) ? "" : "NOT"); return; } #endif #endif //////////////////////////////////////////////////////////////////////////////////////// // check whether it is win2k for the current system //////////////////////////////////////////////////////////////////////////////////////// BOOL IsWin2K(void) { static int iIsWin2K = -1; // force first time path if (iIsWin2K == -1) { OSVERSIONINFOEX osvi; DWORDLONG dwlConditionMask = 0; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); // This is information that identifies win2K osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osvi.dwMajorVersion = 5; osvi.dwMinorVersion = 0; // Initialize the condition mask. VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_EQUAL ); VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_EQUAL ); // Perform the test. iIsWin2K = (VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask)? 1 : 0); } return iIsWin2K; } ///////////////////////////////////////////////////////////////////////////////////// // check whether a policy is set to deny current user access to AU ///////////////////////////////////////////////////////////////////////////////////// BOOL fAccessibleToAU(void) { BOOL fAccessible = TRUE; DWORD dwType; DWORD dwValue; DWORD dwSize = sizeof(dwValue); DWORD dwResult = SHGetValue(HKEY_CURRENT_USER, AUREGKEY_HKCU_USER_POLICY, AUREGVALUE_DISABLE_WINDOWS_UPDATE_ACCESS, &dwType, &dwValue, &dwSize); if (ERROR_SUCCESS == dwResult && REG_DWORD == dwType && 1 == dwValue) { fAccessible = FALSE; } return fAccessible; } /* BOOL IsAdministrator() { SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; PSID pSID = NULL; BOOL bResult = FALSE; if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID) || !CheckTokenMembership(NULL, pSID, &bResult)) { bResult = FALSE; } if(pSID) { FreeSid(pSID); } return bResult; } */ // following are hidden item related functions BOOL FHiddenItemsExist(void) { //USES_CONVERSION; DEBUGMSG("FHiddenItemsExist()"); TCHAR szFile[MAX_PATH]; //Initialize the global path to WU Dir if(!CreateWUDirectory(TRUE)) { return FALSE; } return SUCCEEDED(StringCchCopyEx(szFile, ARRAYSIZE(szFile), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) && SUCCEEDED(StringCchCatEx(szFile, ARRAYSIZE(szFile), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) && fFileExists(szFile); } BOOL RemoveHiddenItems(void) { //USES_CONVERSION DEBUGMSG("RemoveHiddenItems()"); TCHAR szFile[MAX_PATH]; AUASSERT(_T('\0') != g_szWUDir[0]); return SUCCEEDED(StringCchCopyEx(szFile, ARRAYSIZE(szFile), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) && SUCCEEDED(StringCchCatEx(szFile, ARRAYSIZE(szFile), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) && AUDelFileOrDir(szFile); } ///////////////////////////////////////////////////////////////////////////////// // bstrRTFPath is URL for the RTF file on internet // langid is the language id for the process who download this RTF //////////////////////////////////////////////////////////////////////////////// BOOL IsRTFDownloaded(BSTR bstrRTFPath, LANGID langid) { TCHAR tszLocalFullFileName[MAX_PATH]; if (NULL == bstrRTFPath) { return FALSE; } if (FAILED(GetRTFDownloadPath(tszLocalFullFileName, ARRAYSIZE(tszLocalFullFileName), langid)) || FAILED(PathCchAppend(tszLocalFullFileName, ARRAYSIZE(tszLocalFullFileName), W2T(PathFindFileNameW(bstrRTFPath))))) { return FALSE; } // DEBUGMSG("Checking existence of local RTF file %S", T2W(tszLocalFullFileName)); BOOL fIsDir = TRUE; BOOL fExists = fFileExists(tszLocalFullFileName, &fIsDir); return fExists && !fIsDir; } void DisableUserInput(HWND hwnd) { int ControlIDs[] = { IDC_CHK_KEEPUPTODATE, IDC_OPTION1, IDC_OPTION2, IDC_OPTION3, IDC_CMB_DAYS, IDC_CMB_HOURS,IDC_RESTOREHIDDEN }; for (int i = 0; i < ARRAYSIZE(ControlIDs); i++) { EnableWindow(GetDlgItem(hwnd, ControlIDs[i]), FALSE); } } //////////////////////////////////////////////////////////////////////////// // // Helper Function Hours2LocalizedString() // helper function to standardized the way AU formats time string // for a given time. For example "3:00 AM" // // Parameters: // pst - ptr to SYSTEMTIME for localizing the time component // ptszBuffer - buffer to hold the resulting localized string // cbSize - size of buffer in TCHARs // Return: TRUE if successful; FALSE otherwise // //////////////////////////////////////////////////////////////////////////// BOOL Hours2LocalizedString(SYSTEMTIME *pst, LPTSTR ptszBuffer, DWORD cbSize) { return (0 != GetTimeFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE | TIME_NOSECONDS, pst, NULL, ptszBuffer, cbSize)); } //////////////////////////////////////////////////////////////////////////// // // Helper Function FillHrsCombo() // helper function to standardized the way AU sets up the list // of hour values in a combo box. // // Parameters: // hwnd - handle to obtain the handle to the combobox // dwSchedInstallTime - hour value to default the combobox selection to // 3:00 AM will be used if this value is not valid. // Return: TRUE if successful; FALSE otherwise // //////////////////////////////////////////////////////////////////////////// BOOL FillHrsCombo(HWND hwnd, DWORD dwSchedInstallTime) { HWND hComboHrs = GetDlgItem(hwnd,IDC_CMB_HOURS); DWORD dwCurrentIndex = 3; SYSTEMTIME st = {2000, 1, 5, 1, 0, 0, 0, 0}; // 01/01/2000 00:00:00 can be any valid date/time for (WORD i = 0; i < 24; i++) { TCHAR tszHrs[30]; st.wHour = i; if (!Hours2LocalizedString(&st, tszHrs, ARRAYSIZE(tszHrs))) { return FALSE; } LRESULT nIndex = SendMessage(hComboHrs,CB_ADDSTRING,0,(LPARAM)tszHrs); SendMessage(hComboHrs,CB_SETITEMDATA,nIndex,i); if( dwSchedInstallTime == i ) { dwCurrentIndex = (DWORD)nIndex; } } SendMessage(hComboHrs,CB_SETCURSEL,dwCurrentIndex,(LPARAM)0); return TRUE; } BOOL FillDaysCombo(HINSTANCE hInstance, HWND hwnd, DWORD dwSchedInstallDay, UINT uMinResId, UINT uMaxResId) { HWND hComboDays = GetDlgItem(hwnd,IDC_CMB_DAYS); DWORD dwCurrentIndex = 0; for (UINT i = uMinResId, j = 0; i <= uMaxResId; i ++, j++) { WCHAR szDay[40]; LoadStringW(hInstance,i,szDay,ARRAYSIZE(szDay)); LRESULT nIndex = SendMessage(hComboDays,CB_ADDSTRING,0,(LPARAM)szDay); SendMessage(hComboDays,CB_SETITEMDATA,nIndex,j); if( dwSchedInstallDay == j ) { dwCurrentIndex = (DWORD) nIndex; } } SendMessage(hComboDays,CB_SETCURSEL,dwCurrentIndex,(LPARAM)0); return TRUE; }