|
|
/*
Copyright (c) Microsoft Corporation */ #include "stdinc.h"
#include "dbt.h"
#include "devguid.h"
#include "dialogs.h"
#include "cassemblyrecoveryinfo.h"
#include "protectionui.h"
#include "recover.h"
#include "sxsexceptionhandling.h"
//
// FAKERY
//
extern HINSTANCE g_hInstance; extern HANDLE g_hSxsLoginEvent; HDESK g_hDesktop = NULL;
BOOL SxspSpinUntilValidDesktop() { FN_PROLOG_WIN32
//
// NTRAID#NTBUG9-219455-2000/12/13-MGrier Postponed to Blackcomb; the
// current code does the same thing that WFP is doing; it's just that
// we should really have them pass us the desktop.
//
// We should be relying on what WFP has already
// found to be the 'proper' input desktop. Doing so, however requires a
// change to the interface between SXS and SFC to pass along a pointer to
// the WFP desktop handle. Not a bad thing, just .. not implemented yet.
//
while (g_hDesktop == NULL) { DWORD dwResult = ::WaitForSingleObject(g_hSxsLoginEvent, INFINITE);
if (dwResult == WAIT_OBJECT_0) IFW32NULL_ORIGINATE_AND_EXIT(g_hDesktop = ::OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED)); else if (dwResult == WAIT_FAILED) ORIGINATE_WIN32_FAILURE_AND_EXIT(WaitForSingleObject, ::FusionpGetLastWin32Error()); }
FN_EPILOG }
CSXSMediaPromptDialog::CSXSMediaPromptDialog() : m_hOurWnd((HWND)INVALID_HANDLE_VALUE), m_pvDeviceChange(NULL), m_uiAutoRunMsg(0), m_DeviceChangeMask(0), m_DeviceChangeFlags(0), m_fIsCDROM(false), m_CodebaseInfo(NULL) { }
CSXSMediaPromptDialog::~CSXSMediaPromptDialog() { }
BOOL CSXSMediaPromptDialog::Initialize( const CCodebaseInformation* CodebaseInfo ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess);
PARAMETER_CHECK(CodebaseInfo != NULL);
SxsWFPResolveCodebase CodebaseType;
IFW32FALSE_EXIT(CodebaseInfo->Win32GetType(CodebaseType));
PARAMETER_CHECK( (CodebaseType == CODEBASE_RESOLVED_URLHEAD_FILE) || (CodebaseType == CODEBASE_RESOLVED_URLHEAD_WINSOURCE) || (CodebaseType == CODEBASE_RESOLVED_URLHEAD_CDROM));
m_CodebaseInfo = CodebaseInfo; switch (CodebaseType) { case CODEBASE_RESOLVED_URLHEAD_CDROM: m_fIsCDROM = true; break;
case CODEBASE_RESOLVED_URLHEAD_WINSOURCE: { CFusionRegKey hkSetupInfo; DWORD dwWasFromCDRom;
IFREGFAILED_ORIGINATE_AND_EXIT( ::RegOpenKeyExW( HKEY_LOCAL_MACHINE, WINSXS_INSTALL_SOURCE_BASEDIR, 0, KEY_READ | FUSIONP_KEY_WOW64_64KEY, &hkSetupInfo));
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - If the key isn't there, it's ok to assume not
// from a CDROM but if it was out of resources etc. this should propagate an error.
if (!::FusionpRegQueryDwordValueEx( 0, hkSetupInfo, WINSXS_INSTALL_SOURCE_IS_CDROM, &dwWasFromCDRom)) { dwWasFromCDRom = 0; }
m_fIsCDROM = (dwWasFromCDRom != 0); break; }
case CODEBASE_RESOLVED_URLHEAD_FILE: { CSmallStringBuffer buffVolumePathName;
IFW32FALSE_EXIT( ::SxspGetVolumePathName( 0, CodebaseInfo->GetCodebase(), buffVolumePathName));
if (::GetDriveTypeW(buffVolumePathName) == DRIVE_CDROM) { m_fIsCDROM = true; }
break; } }
FN_EPILOG }
BOOL CSXSMediaPromptDialog::DisplayMessage( HWND hDlg, UINT uContentText, UINT uDialogFlags, int &riResult ) { FN_PROLOG_WIN32
const SIZE_T BufferSize = (MAX_PATH * 2);
CTinyStringBuffer wcTitle; CTinyStringBuffer wcContent; int iResult = 0;
if (wcContent.Win32ResizeBuffer(BufferSize + 1, eDoNotPreserveBufferContents)) { CStringBufferAccessor Accessor(&wcContent); IFW32ZERO_ORIGINATE_AND_EXIT(::LoadStringW(g_hInstance, uContentText, Accessor, BufferSize)); } if (wcTitle.Win32ResizeBuffer(BufferSize, eDoNotPreserveBufferContents)) { CStringBufferAccessor Accessor(&wcTitle); IFW32ZERO_ORIGINATE_AND_EXIT(::LoadStringW(g_hInstance, IDS_TITLE, Accessor, BufferSize)); } IFW32ZERO_ORIGINATE_AND_EXIT(iResult = ::MessageBoxW(hDlg, wcContent, wcTitle, uDialogFlags));
riResult = iResult;
FN_EPILOG }
BOOL CSXSMediaPromptDialog::ShowSelf( CSXSMediaPromptDialog::DialogResults &rResult ) { FN_PROLOG_WIN32
INT_PTR i;
IFW32FALSE_EXIT(::SxspSpinUntilValidDesktop()); IFW32FALSE_ORIGINATE_AND_EXIT(::SetThreadDesktop(g_hDesktop));
i = ::DialogBoxParamW( g_hInstance, MAKEINTRESOURCEW( m_fIsCDROM ? IDD_SFC_CD_PROMPT : IDD_SFC_NETWORK_PROMPT), NULL, &CSXSMediaPromptDialog::OurDialogProc, (LPARAM)this);
if (i == -1) ORIGINATE_WIN32_FAILURE_AND_EXIT(DialogBoxParamW, ::FusionpGetLastWin32Error());
rResult = static_cast<DialogResults>(i);
FN_EPILOG }
BOOL SxspFindInstallWindowsSourcePath( OUT CBaseStringBuffer &rbuffTempStringBuffer ) { FN_PROLOG_WIN32
CFusionRegKey rhkInstallSource; rbuffTempStringBuffer.Clear();
IFREGFAILED_ORIGINATE_AND_EXIT( ::RegOpenKeyExW( HKEY_LOCAL_MACHINE, WINSXS_INSTALL_SOURCE_BASEDIR, 0, KEY_READ | FUSIONP_KEY_WOW64_64KEY, &rhkInstallSource));
IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkInstallSource, WINSXS_INSTALL_SOURCEPATH_REGKEY, rbuffTempStringBuffer));
//
// Now let's be really cheesy and find the fourth slash (\\foo\bar\), and
// clip everything after that.
//
PCWSTR cursor = rbuffTempStringBuffer; ULONG ulSlashCount = 0; while ( *cursor && ulSlashCount < 4 ) { // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Should handle both slashes. I think we have
// a macro for this.
if (*cursor == L'\\') ulSlashCount++;
cursor++; }
//
// If we got 3 or less, then it's \\foo\bar or \\foo, which should be
// illegal. Otherwise, clip everything off past this point.
//
if (ulSlashCount > 3) { rbuffTempStringBuffer.Left(cursor - rbuffTempStringBuffer); IFW32FALSE_EXIT(rbuffTempStringBuffer.Win32RemoveTrailingPathSeparators()); }
FN_EPILOG }
INT_PTR CALLBACK CSXSMediaPromptDialog::OurDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { FN_TRACE(); INT_PTR iResult = 0; int iMessageBoxResult = 0;
#define WM_TRYAGAIN (WM_USER + 1)
static CSXSMediaPromptDialog *pThis = NULL;
switch (uMsg) { case WM_INITDIALOG: { pThis = reinterpret_cast<CSXSMediaPromptDialog *>(lParam);
FLASHWINFO winfo;
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Shouldn't these be INTERNAL_ERROR_CHECKs?
ASSERT(pThis != NULL); ASSERT(pThis->m_hOurWnd == INVALID_HANDLE_VALUE); pThis->m_hOurWnd = hDlg;
//
// Center the window, bring it forward
//
{ RECT rcWindow; LONG x, y, w, h;
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::GetWindowRect(hDlg, &rcWindow); // error check?
w = rcWindow.right - rcWindow.left + 1; h = rcWindow.bottom - rcWindow.top + 1; x = (::GetSystemMetrics(SM_CXSCREEN) - w) / 2; // error check?
y = (::GetSystemMetrics(SM_CYSCREEN) - h) / 2; // error check?
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::MoveWindow(hDlg, x, y, w, h, FALSE); // error check?
winfo.cbSize = sizeof(winfo); winfo.hwnd = hDlg; winfo.dwFlags = FLASHW_ALL; winfo.uCount = 3; winfo.dwTimeout = 0; // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::SetForegroundWindow(hDlg); // error check?
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::FlashWindowEx(&winfo); // error check?
}
//
// Create the device-change notification
//
if (pThis->m_pvDeviceChange == NULL) { DEV_BROADCAST_DEVICEINTERFACE_W FilterData = { 0 };
FilterData.dbcc_size = sizeof(FilterData); FilterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; FilterData.dbcc_classguid = GUID_DEVCLASS_CDROM;
IFW32NULL_ORIGINATE_AND_EXIT( pThis->m_pvDeviceChange = ::RegisterDeviceNotificationW( hDlg, &FilterData, DEVICE_NOTIFY_WINDOW_HANDLE)); }
//
// Turn off autorun
//
IFW32ZERO_ORIGINATE_AND_EXIT(pThis->m_uiAutoRunMsg = ::RegisterWindowMessageW(L"QueryCancelAutoPlay"));
//
// Fidget with the text in the popup dialog now
//
{ CSmallStringBuffer sbFormatter; CSmallStringBuffer buffFormattedText; CStringBufferAccessor acc;
//
// It is ok if these memory allocations fail, the ui will degrade.
// As well, that's a reason to leave the buffers "small" and not "tiny".
// ?
//
sbFormatter.Win32ResizeBuffer(512, eDoNotPreserveBufferContents); buffFormattedText.Win32ResizeBuffer(512, eDoNotPreserveBufferContents);
//
// Set the "Insert your .... now"
//
sbFormatter.Clear(); acc.Attach(&sbFormatter); // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::GetDlgItemTextW( // error check?
hDlg, IDC_MEDIA_NAME, acc, static_cast<DWORD>(sbFormatter.GetBufferCch())); acc.Detach();
if (pThis->m_CodebaseInfo->GetPromptText().Cch() != 0) { IFW32FALSE_EXIT(buffFormattedText.Win32Format( sbFormatter, static_cast<PCWSTR>(pThis->m_CodebaseInfo->GetPromptText()))); // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::SetDlgItemTextW(hDlg, IDC_MEDIA_NAME, static_cast<PCWSTR>(buffFormattedText)); // error check?
} else { #if DBG
::FusionpDbgPrintEx( FUSION_DBG_LEVEL_WFP, "SXS: %s - setting IDC_MEDIA_NAME to empty\n", __FUNCTION__); #endif
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::SetDlgItemTextW(hDlg, IDC_MEDIA_NAME, L""); // error check?
}
//
// Now, depending on what kind of box this is..
//
if (!pThis->m_fIsCDROM) { CSmallStringBuffer buffTempStringBuffer; SxsWFPResolveCodebase CodebaseType; sbFormatter.Clear(); acc.Attach(&sbFormatter);
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::GetDlgItemTextW( // error check?
hDlg, IDC_NET_NAME, acc, static_cast<DWORD>(sbFormatter.GetBufferCch()));
acc.Detach();
IFW32FALSE_EXIT(pThis->m_CodebaseInfo->Win32GetType(CodebaseType));
//
// If this is the Windows install media, display something
// pleasant to the user - \\server\share only!
//
if (CodebaseType == CODEBASE_RESOLVED_URLHEAD_WINSOURCE) { IFW32FALSE_EXIT(::SxspFindInstallWindowsSourcePath(buffTempStringBuffer)); } else {
IFW32FALSE_EXIT(buffTempStringBuffer.Win32Assign(pThis->m_CodebaseInfo->GetCodebase())); }
if (buffTempStringBuffer.Cch() != 0) { IFW32FALSE_EXIT(buffFormattedText.Win32Format(sbFormatter, static_cast<PCWSTR>(buffTempStringBuffer))); IFW32FALSE_EXIT(::SetDlgItemTextW(hDlg, IDC_NET_NAME, buffFormattedText)); } else { #if DBG
::FusionpDbgPrintEx( FUSION_DBG_LEVEL_WFP, "SXS: %s - setting IDC_NET_NAME to empty\n", __FUNCTION__); #endif
IFW32FALSE_EXIT(::SetDlgItemTextW(hDlg, IDC_NET_NAME, L"")); } } else { //
// TODO (jonwis) : This is a CD-rom based install, so we should do
// something sane about prompting for the windows CD.
//
}
//
// Now get the prompt from the resources.. we only have one, really.
//
sbFormatter.Clear(); acc.Attach(&sbFormatter);
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::LoadStringW( // error check?
g_hInstance, IDS_RESTORE_TEXT, acc.GetBufferPtr(), acc.GetBufferCchAsDWORD());
acc.Detach();
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::SetDlgItemTextW(hDlg, IDC_PROMPT_TEXT, sbFormatter); // error check?
} } break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_RETRY: pThis->m_DeviceChangeMask = static_cast<DWORD>(-1); pThis->m_DeviceChangeFlags = DBTF_MEDIA; IFW32FALSE_ORIGINATE_AND_EXIT(::PostMessageW(hDlg, WM_TRYAGAIN, 0, 0)); break;
case IDC_INFO: IFW32FALSE_EXIT( pThis->DisplayMessage( NULL, pThis->m_fIsCDROM ? IDS_MORE_INFORMATION_CD : IDS_MORE_INFORMATION_NET, MB_ICONINFORMATION | MB_SERVICE_NOTIFICATION | MB_OK, iMessageBoxResult)); break;
case IDCANCEL: IFW32FALSE_EXIT( pThis->DisplayMessage( hDlg, IDS_CANCEL_CONFIRM, MB_APPLMODAL | MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING, iMessageBoxResult));
if (iMessageBoxResult == IDYES) { // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::UnregisterDeviceNotification(pThis->m_pvDeviceChange); // error check?
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::EndDialog(hDlg, CSXSMediaPromptDialog::DialogCancelled); // error check?
}
break; }
break; // WM_COMMAND
case WM_DEVICECHANGE:
if (wParam == DBT_DEVICEARRIVAL) { DEV_BROADCAST_VOLUME *dbv = reinterpret_cast<DEV_BROADCAST_VOLUME*>(lParam); ASSERT(dbv != NULL);
if (dbv->dbcv_devicetype == DBT_DEVTYP_VOLUME) { pThis->m_DeviceChangeMask = dbv->dbcv_unitmask; pThis->m_DeviceChangeFlags = dbv->dbcv_flags; // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::PostMessageW(hDlg, WM_TRYAGAIN, 0, 0); // error check?
} }
break;
case WM_TRYAGAIN: // NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::UnregisterDeviceNotification(pThis->m_pvDeviceChange); // error check?
// NTRAID#NTBUG9 - 591839 - 2002/04/01 - mgrier - Missing error check
::EndDialog(hDlg, CSXSMediaPromptDialog::DialogMediaFound); // error check?
break; }
Exit:
return iResult; }
|