#include "priv.h" #include "resource.h" #include #include struct SUParams { LPSOFTDISTINFO psdi; BITBOOL bRemind : 1; BITBOOL bDetails : 1; LONG cyNoDetails; LONG cxDlg; LONG cyDlg; }; INT_PTR CALLBACK SoftwareUpdateDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); SHDOCAPI_(DWORD) SoftwareUpdateMessageBox( HWND hWnd, LPCWSTR szDistUnit, DWORD dwFlags, LPSOFTDISTINFO psdi ) { HRESULT hr; int iRet = IDIGNORE; SOFTDISTINFO sdi; SUParams suparams; DWORD dwAdStateNew = SOFTDIST_ADSTATE_NONE; if ( psdi == NULL ) { // use a local sdi.cbSize = sizeof(SOFTDISTINFO); sdi.dwReserved = 0; psdi = &sdi; } suparams.psdi = psdi; suparams.bRemind = TRUE; suparams.bDetails = FALSE; hr = GetSoftwareUpdateInfo( szDistUnit, psdi ); // we need an HREF to work properly. The title and abstract are negotiable. if ( SUCCEEDED(hr) && psdi->szHREF != NULL ) { // see if this is an update the user already knows about. // If it is, then skip the dialog. if ( (psdi->dwUpdateVersionMS >= psdi->dwInstalledVersionMS || (psdi->dwUpdateVersionMS == psdi->dwInstalledVersionMS && psdi->dwUpdateVersionLS >= psdi->dwInstalledVersionLS)) && (psdi->dwUpdateVersionMS >= psdi->dwAdvertisedVersionMS || (psdi->dwUpdateVersionMS == psdi->dwAdvertisedVersionMS && psdi->dwUpdateVersionLS >= psdi->dwAdvertisedVersionLS)) ) { DWORD idDlg; if ( hr == S_OK ) // new version { // we have a pending update, either on the net, or downloaded if ( psdi->dwFlags & SOFTDIST_FLAG_USAGE_PRECACHE ) { dwAdStateNew = SOFTDIST_ADSTATE_DOWNLOADED; // Show same dialog for downloaded/available states // because users get confused. See IE5 RAID entry 14488 idDlg = IDD_SUAVAILABLE; } else { dwAdStateNew = SOFTDIST_ADSTATE_AVAILABLE; idDlg = IDD_SUAVAILABLE; } } else if ( psdi->dwUpdateVersionMS == psdi->dwInstalledVersionMS && psdi->dwUpdateVersionLS == psdi->dwInstalledVersionLS ) { // if installed version matches advertised, then we autoinstalled already dwAdStateNew = SOFTDIST_ADSTATE_INSTALLED; idDlg = IDD_SUINSTALLED; } else { idDlg = 0; } // only show the dialog if we've haven't been in this ad state before for // this update version if ( dwAdStateNew > psdi->dwAdState && idDlg != 0) { // Sundown: coercion is OK since SoftwareUpdateDlgProc returns true/false iRet = (int) DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(idDlg), hWnd, SoftwareUpdateDlgProc, (LPARAM)&suparams); } } // if update is a newer version than advertised // If the user doesn't want a reminder and didn't cancel, mark the DU. if ( !suparams.bRemind && (iRet == IDNO || iRet == IDYES) ) { SetSoftwareUpdateAdvertisementState( szDistUnit, dwAdStateNew, psdi->dwUpdateVersionMS, psdi->dwUpdateVersionLS ); } // if we're finished with this ad state for this version } // if we got the update info else iRet = IDABORT; if ( FAILED(hr) || psdi == &sdi ) { if ( psdi->szTitle != NULL ) { CoTaskMemFree( psdi->szTitle ); psdi->szTitle = NULL; } if ( psdi->szAbstract != NULL ) { CoTaskMemFree( psdi->szAbstract ); psdi->szAbstract = NULL; }; if ( psdi->szHREF != NULL ) { CoTaskMemFree( psdi->szHREF ); psdi->szHREF = NULL; } } return iRet; } INT_PTR CALLBACK SoftwareUpdateDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL fRet = 0; SUParams *psuparam = (SUParams*)GetWindowLongPtr(hDlg, DWLP_USER);; HRESULT hr = S_OK; HWND hwndDetails; switch (msg) { case WM_INITDIALOG: int cchDetails; TCHAR *pszTitle; TCHAR *pszAbstract; TCHAR *pszDetails; TCHAR szFmt[MAX_PATH]; SetWindowLongPtr(hDlg, DWLP_USER, lParam); psuparam = (SUParams*)lParam; if (SHRestricted( REST_NOFORGETSOFTWAREUPDATE)) EnableWindow(GetDlgItem(hDlg, IDC_REMIND), FALSE); // Prepare the details from the SOFTDISTINFO MLLoadString(IDS_SUDETAILSFMT, szFmt, ARRAYSIZE(szFmt) ); cchDetails = lstrlen( szFmt ); if ( psuparam->psdi->szTitle != NULL ) { pszTitle = psuparam->psdi->szTitle; } else { pszTitle = NULL; } if ( psuparam->psdi->szAbstract != NULL ) { pszAbstract = psuparam->psdi->szAbstract; } else { pszAbstract = NULL; } pszDetails = new TCHAR[cchDetails]; if ( pszDetails != NULL ) { StringCchPrintf( pszDetails, cchDetails, szFmt, ((pszTitle!=NULL)?pszTitle:TEXT("")), ((pszAbstract!=NULL)?pszAbstract:TEXT("")) ); // set the details text SetDlgItemText( hDlg, IDC_DETAILSTEXT, pszDetails ); // initialize the reminder check box CheckDlgButton( hDlg, IDC_REMIND, ((psuparam->bRemind)?BST_CHECKED:BST_UNCHECKED) ); // Hide or show the details RECT rectDlg; RECT rectDetails; GetWindowRect( hDlg, &rectDlg ); psuparam->cyDlg = rectDlg.bottom - rectDlg.top; psuparam->cxDlg = rectDlg.right - rectDlg.left; hwndDetails = GetDlgItem( hDlg, IDC_DETAILSTEXT ); GetWindowRect( hwndDetails, &rectDetails ); psuparam->cyNoDetails = rectDetails.top - rectDlg.top; SetWindowPos( hwndDetails, NULL, 0,0,0,0, SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE ); SetWindowPos( hDlg, NULL, 0,0,psuparam->cxDlg,psuparam->cyNoDetails, SWP_NOMOVE | SWP_NOZORDER ); } else EndDialog( hDlg, IDABORT ); if ( pszDetails != NULL ) delete pszDetails; fRet = TRUE; break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDYES: EndDialog(hDlg, IDYES ); fRet = TRUE; break; case IDNO: EndDialog(hDlg, IDNO ); fRet = TRUE; break; case IDC_REMIND: psuparam->bRemind = IsDlgButtonChecked( hDlg, IDC_REMIND ) == BST_CHECKED; fRet = TRUE; break; case IDC_DETAILS: { TCHAR szDetails[40]; // toggle the details hwndDetails = GetDlgItem( hDlg, IDC_DETAILSTEXT ); psuparam->bDetails = !psuparam->bDetails; if ( psuparam->bDetails ) { // show the details // switch button to close text MLLoadString(IDS_SUDETAILSCLOSE, szDetails, ARRAYSIZE(szDetails) ); SetDlgItemText( hDlg, IDC_DETAILS, szDetails ); SetWindowPos( hDlg, NULL, 0,0,psuparam->cxDlg, psuparam->cyDlg, SWP_NOMOVE | SWP_NOZORDER ); SetWindowPos( hwndDetails, NULL, 0,0,0,0, SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE ); } else { MLLoadString(IDS_SUDETAILSOPEN, szDetails, ARRAYSIZE(szDetails) ); SetDlgItemText( hDlg, IDC_DETAILS, szDetails ); SetWindowPos( hwndDetails, NULL, 0,0,0,0, SWP_NOMOVE | SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE ); SetWindowPos( hDlg, NULL, 0,0,psuparam->cxDlg,psuparam->cyNoDetails, SWP_NOMOVE | SWP_NOZORDER ); } } fRet = TRUE; break; } break; case WM_CLOSE: EndDialog(hDlg, IDNO); fRet = TRUE; break; case WM_DESTROY: fRet = TRUE; break; default: fRet = FALSE; } return fRet; }