windows-nt/Source/XPSP1/NT/shell/shell32/apdlg.cpp
2020-09-26 16:20:57 +08:00

817 lines
19 KiB
C++

#include "shellprv.h"
#include "ids.h"
#include "apdlg.h"
#include "hwcmmn.h"
#include "mtpt.h"
static const DWORD s_rgdwHelpIDsArray[] =
{
IDC_AP_TOPTEXT, IDH_SELECT_CONTENT_TYPE,
IDC_AP_LIST, IDH_SELECT_CONTENT_TYPE,
IDC_AP_DEFAULTHANDLER, IDH_SELECT_ACTION,
IDC_AP_LIST_ACTIONS, IDH_SELECT_ACTION,
IDC_AP_PROMPTEACHTIME, IDH_PROMPT_ME_EACH_TIME,
IDC_AP_NOACTION, IDH_TAKE_NO_ACTION,
0, 0
};
static const DWORD g_rgdwContentTypes[] =
{
CT_AUTOPLAYMUSIC ,
CT_AUTOPLAYPIX ,
CT_AUTOPLAYMOVIE ,
CT_AUTOPLAYMIXEDCONTENT ,
CT_CDAUDIO ,
CT_DVDMOVIE ,
CT_BLANKCDR , // could also have been: CT_BLANKCDRW
};
#define COL_ACTION 0
#define COL_PROVIDER 1
const UINT c_auTileColumns[] = {COL_ACTION, COL_PROVIDER};
const UINT c_auTileSubItems[] = {COL_PROVIDER};
HRESULT CAutoPlayDlg::_InitListViewActions()
{
HWND hwndList = GetDlgItem(_hwnd, IDC_AP_LIST_ACTIONS);
HRESULT hr = _uilListViewActions.Init(hwndList);
if (SUCCEEDED(hr))
{
hr = _uilListViewActions.InitTileInfo(c_auTileSubItems, ARRAYSIZE(c_auTileSubItems));
if (SUCCEEDED(hr))
{
RECT rc = {0};
LVTILEVIEWINFO lvtvi = {0};
HIMAGELIST himagelist;
ListView_SetView(hwndList, LV_VIEW_TILE);
for (int i = 0; i < ARRAYSIZE(c_auTileColumns); ++i)
{
LVCOLUMN lvcolumn = {0};
lvcolumn.mask = LVCF_SUBITEM;
lvcolumn.iSubItem = c_auTileColumns[i];
ListView_InsertColumn(hwndList, i, &lvcolumn);
}
GetClientRect(hwndList, &rc);
lvtvi.cbSize = sizeof(lvtvi);
lvtvi.dwMask = LVTVIM_TILESIZE | LVTVIM_COLUMNS;
lvtvi.dwFlags = LVTVIF_FIXEDWIDTH;
// Leave room for the scroll bar when setting tile sizes or listview gets screwed up.
lvtvi.sizeTile.cx = ((rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL));
lvtvi.cLines = ARRAYSIZE(c_auTileSubItems);
ListView_SetTileViewInfo(hwndList, &lvtvi);
Shell_GetImageLists(&himagelist, NULL);
if (himagelist)
{
ListView_SetImageList(hwndList, himagelist, LVSIL_NORMAL);
hr = S_OK;
}
}
}
return hr;
}
HRESULT CAutoPlayDlg::_FillListViewActions(CContentTypeData* pdata)
{
HRESULT hr = _uilListViewActions.ResetContent();
if (SUCCEEDED(hr))
{
int c = pdata->GetHandlerCount();
if (c)
{
for (int i = 0; SUCCEEDED(hr) && (i < c); ++i)
{
CHandlerData* phandlerdata = pdata->GetHandlerData(i);
if (phandlerdata)
{
CHandlerLVItem* puidata = new CHandlerLVItem();
if (puidata)
{
hr = puidata->InitData(phandlerdata);
if (SUCCEEDED(hr))
{
hr = _uilListViewActions.AddItem(puidata);
if (FAILED(hr))
{
delete puidata;
}
}
}
else
{
hr = E_OUTOFMEMORY;
}
phandlerdata->Release();
}
}
_fAtLeastOneAction = TRUE;
}
else
{
// disable the listview and its radio button
_fAtLeastOneAction = FALSE;
}
}
return hr;
}
HRESULT CAutoPlayDlg::_UpdateRestoreButton(BOOL fPromptEachTime)
{
BOOL fEnable;
if (fPromptEachTime)
{
fEnable = FALSE;
}
else
{
fEnable = TRUE;
}
EnableWindow(GetDlgItem(_hwnd, IDC_AP_RESTOREDEFAULTS), fEnable);
return fEnable;
}
HRESULT CAutoPlayDlg::_UpdateLowerPane()
{
CContentTypeData* pdata;
HRESULT hr = _uilListView.GetSelectedItemData(&pdata);
_fIgnoreListViewItemStateChanges = TRUE;
if (SUCCEEDED(hr))
{
BOOL fPromptEachTime = !lstrcmpi(pdata->_pszHandlerDefault, TEXT("MSPromptEachTime"));
if (!fPromptEachTime)
{
if (!(pdata->_dwHandlerDefaultFlags & HANDLERDEFAULT_USERCHOSENDEFAULT))
{
// There *NO* User Chosen Default
fPromptEachTime = TRUE;
}
else
{
// There is a User Chosen Default
if (pdata->_dwHandlerDefaultFlags &
HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED)
{
// But there's also more recent apps
fPromptEachTime = TRUE;
}
}
}
hr = _FillListViewActions(pdata);
if (SUCCEEDED(hr))
{
hr = _SelectListViewActionsItem(pdata->_pszHandlerDefault);
}
if (SUCCEEDED(hr))
{
hr = _SelectRadioButton(fPromptEachTime);
}
if (SUCCEEDED(hr))
{
hr = _UpdateRestoreButton(fPromptEachTime);
}
pdata->Release();
}
_fIgnoreListViewItemStateChanges = FALSE;
return hr;
}
HRESULT CAutoPlayDlg::_UpdateApplyButton()
{
if (_dlmanager.IsDirty())
{
PropSheet_Changed(GetParent(_hwnd), _hwnd);
}
else
{
PropSheet_UnChanged(GetParent(_hwnd), _hwnd);
}
return S_OK;
}
HRESULT _SetHandlerDefault(LPWSTR* ppszHandlerDefault, LPCWSTR pszHandler)
{
LPWSTR pszHandlerNew;
HRESULT hr = SHStrDup(pszHandler, &pszHandlerNew);
if (SUCCEEDED(hr))
{
if (*ppszHandlerDefault)
{
CoTaskMemFree(*ppszHandlerDefault);
}
*ppszHandlerDefault = pszHandlerNew;
}
return hr;
}
HRESULT CAutoPlayDlg::_SelectRadioButton(BOOL fPromptEachTime)
{
CContentTypeData* pdata;
HRESULT hr = _uilListView.GetSelectedItemData(&pdata);
if (SUCCEEDED(hr))
{
int iCtrl;
BOOL fEnableListView = FALSE;
if (fPromptEachTime)
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), TEXT("MSPromptEachTime"));
iCtrl = IDC_AP_PROMPTEACHTIME;
}
else
{
fEnableListView = TRUE;
CHandlerData* phandlerdata;
hr = _uilListViewActions.GetSelectedItemData(&phandlerdata);
if (SUCCEEDED(hr))
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), phandlerdata->_pszHandler);
phandlerdata->Release();
}
iCtrl = IDC_AP_DEFAULTHANDLER;
}
Button_SetCheck(GetDlgItem(_hwnd, IDC_AP_DEFAULTHANDLER), (IDC_AP_DEFAULTHANDLER == iCtrl));
Button_SetCheck(GetDlgItem(_hwnd, IDC_AP_PROMPTEACHTIME), (IDC_AP_PROMPTEACHTIME == iCtrl));
EnableWindow(GetDlgItem(_hwnd, IDC_AP_LIST_ACTIONS), fEnableListView);
pdata->Release();
hr = _UpdateApplyButton();
}
return hr;
}
HRESULT CAutoPlayDlg::_SelectListViewActionsItem(LPCWSTR pszHandlerDefault)
{
HRESULT hr = S_FALSE;
LVITEM lvitem = {0};
int iItemToSelect = 0;
HWND hwndList = GetDlgItem(_hwnd, IDC_AP_LIST_ACTIONS);
if (pszHandlerDefault)
{
int c = ListView_GetItemCount(hwndList);
if (c)
{
int i;
for (i = 0; i < c; ++i)
{
lvitem.mask = LVIF_PARAM;
lvitem.iItem = i;
if (ListView_GetItem(hwndList, &lvitem))
{
CHandlerLVItem* phandleruidata = (CHandlerLVItem*)lvitem.lParam;
if (phandleruidata)
{
CHandlerData* phandlerdata = phandleruidata->GetData();
if (phandlerdata)
{
if (!lstrcmp(phandlerdata->_pszHandler,
pszHandlerDefault))
{
break;
}
phandlerdata->Release();
}
}
}
}
if (i == c)
{
i = 0;
}
else
{
hr = S_OK;
}
iItemToSelect = i;
}
}
else
{
// Select first one
hr = S_OK;
}
lvitem.mask = LVIF_STATE;
lvitem.iItem = iItemToSelect;
lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
lvitem.state = LVIS_SELECTED | LVIS_FOCUSED;
ListView_SetItem(hwndList, &lvitem);
ListView_EnsureVisible(hwndList, lvitem.iItem, FALSE);
return hr;
}
void _SetCtrlTextFromResourceText(HWND hwndDlg, int iCtrl, int iResourceText)
{
// We use 256, even if we would use a bigger buffer, the ctrl where we'll
// put the text would probably not be able to take it anyway (would be
// truncated).
WCHAR sz[256];
if (LoadString(HINST_THISDLL, iResourceText, sz, ARRAYSIZE(sz)))
{
SetDlgItemText(hwndDlg, iCtrl, sz);
}
}
LRESULT CAutoPlayDlg::_OnApply()
{
if (_dlmanager.IsDirty())
{
// Should we get the return value, and if so, why?
_dlmanager.Commit();
}
return PSNRET_NOERROR;
}
// Listview Actions
HRESULT CAutoPlayDlg::_OnListViewActionsSelChange()
{
CHandlerData* phandlerdata;
HRESULT hr = _uilListViewActions.GetSelectedItemData(&phandlerdata);
if (SUCCEEDED(hr))
{
CContentTypeData* pdata;
hr = _uilListView.GetSelectedItemData(&pdata);
if (SUCCEEDED(hr))
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), phandlerdata->_pszHandler);
pdata->Release();
}
phandlerdata->Release();
}
if (SUCCEEDED(hr))
{
hr = _UpdateApplyButton();
}
return hr;
}
// Radio buttons
HRESULT CAutoPlayDlg::_OnRestoreDefault()
{
CContentTypeData* pdata;
HRESULT hr = _uilListView.GetSelectedItemData(&pdata);
if (SUCCEEDED(hr))
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), TEXT("MSPromptEachTime"));
_SelectRadioButton(TRUE);
hr = _UpdateApplyButton();
if (SUCCEEDED(hr))
{
_UpdateRestoreButton(TRUE);
}
pdata->Release();
SetFocus(GetNextDlgTabItem(_hwnd, GetDlgItem(_hwnd, IDC_AP_RESTOREDEFAULTS), FALSE /*next ctrl*/));
}
return hr;
}
HRESULT CAutoPlayDlg::_OnRadio(int iButton)
{
CContentTypeData* pdata;
HRESULT hr = _uilListView.GetSelectedItemData(&pdata);
if (SUCCEEDED(hr))
{
HWND hwndList = GetDlgItem(_hwnd, IDC_AP_LIST_ACTIONS);
if (IDC_AP_DEFAULTHANDLER == iButton)
{
CHandlerData* phandlerdata;
EnableWindow(hwndList, TRUE);
hr = _uilListViewActions.GetSelectedItemData(&phandlerdata);
if (SUCCEEDED(hr))
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), phandlerdata->_pszHandler);
phandlerdata->Release();
}
}
else
{
_SetHandlerDefault(&(pdata->_pszHandlerDefault), TEXT("MSPromptEachTime"));
EnableWindow(hwndList, FALSE);
}
hr = _UpdateApplyButton();
if (SUCCEEDED(hr))
{
_UpdateRestoreButton(!lstrcmpi(pdata->_pszHandlerDefault, TEXT("MSPromptEachTime")));
}
pdata->Release();
}
return hr;
}
LRESULT CAutoPlayDlg::OnInitDialog(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = _InitDataObjects();
_fIgnoreListViewItemStateChanges = TRUE;
if (SUCCEEDED(hr))
{
hr = _InitListView();
if (SUCCEEDED(hr))
{
hr = _FillListView();
if (SUCCEEDED(hr))
{
hr = _InitListViewActions();
if (SUCCEEDED(hr))
{
hr = _uilListView.SelectFirstItem();
if (SUCCEEDED(hr))
{
hr = _UpdateLowerPane();
}
}
}
}
}
_fIgnoreListViewItemStateChanges = FALSE;
return TRUE;
}
LRESULT CAutoPlayDlg::OnNotify(WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = FALSE;
LPNMHDR pNMHDR = (LPNMHDR)lParam;
UINT_PTR idFrom = pNMHDR->idFrom;
UINT uCode = pNMHDR->code;
switch (uCode)
{
case PSN_APPLY:
lRes = _OnApply();
CBaseDlg::OnNotify(wParam, lParam);
break;
default:
switch (idFrom)
{
case IDC_AP_LIST_ACTIONS:
if (!_fIgnoreListViewItemStateChanges)
{
NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
if (LVN_ITEMCHANGED == uCode)
{
// Is a new item being selected?
if ((pNMLV->uChanged & LVIF_STATE) &&
pNMLV->uNewState & LVIS_SELECTED)
{
_OnListViewActionsSelChange();
}
}
}
lRes = CBaseDlg::OnNotify(wParam, lParam);
break;
default:
lRes = CBaseDlg::OnNotify(wParam, lParam);
break;
}
break;
}
return lRes;
}
LRESULT CAutoPlayDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
int iCtl = LOWORD(wParam);
int iNot = HIWORD(wParam);
switch (iCtl)
{
case IDC_AP_DEFAULTHANDLER:
case IDC_AP_PROMPTEACHTIME:
if (BN_CLICKED == iNot)
{
_OnRadio(iCtl);
}
break;
case IDC_AP_LIST:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
_UpdateLowerPane();
}
break;
case IDC_AP_RESTOREDEFAULTS:
if (BN_CLICKED == iNot)
{
_OnRestoreDefault();
}
break;
}
return CBaseDlg::OnCommand(wParam, lParam);
}
LRESULT CAutoPlayDlg::OnDestroy(WPARAM wParam, LPARAM lParam)
{
_uilListView.ResetContent();
_uilListViewActions.ResetContent();
return CBaseDlg::OnDestroy(wParam, lParam);
}
LRESULT CAutoPlayDlg::OnHelp(WPARAM wParam, LPARAM lParam)
{
HWND hwndItem = (HWND)((LPHELPINFO)lParam)->hItemHandle;
BOOL ret = WinHelp(hwndItem, TEXT("filefold.hlp"), HELP_WM_HELP, (ULONG_PTR)(LPTSTR)s_rgdwHelpIDsArray);
if (!ret)
{
return CBaseDlg::OnHelp(wParam, lParam);
}
return ret;
}
LRESULT CAutoPlayDlg::OnContextMenu(WPARAM wParam, LPARAM lParam)
{
BOOL lRes=FALSE;
if (HTCLIENT == (int)SendMessage(_hwnd, WM_NCHITTEST, 0, lParam))
{
POINT pt;
HWND hwndItem = NULL;
int iCtrlID = 0;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
ScreenToClient(_hwnd, &pt);
hwndItem = ChildWindowFromPoint(_hwnd, pt);
iCtrlID = GetDlgCtrlID(hwndItem);
lRes = WinHelp((HWND)wParam, TEXT("filefold.hlp"), HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)s_rgdwHelpIDsArray);
if (!lRes)
{
return CBaseDlg::OnContextMenu(wParam, lParam);
}
}
else
{
lRes = FALSE;
}
return lRes;
}
CAutoPlayDlg::CAutoPlayDlg() : CBaseDlg((ULONG_PTR)s_rgdwHelpIDsArray)
{
ASSERT(ARRAYSIZE(_rgpContentTypeData) >= ARRAYSIZE(g_rgdwContentTypes));
}
HRESULT CAutoPlayDlg::Init(LPWSTR pszDrive, int iDriveType)
{
lstrcpyn(_szDrive, pszDrive, ARRAYSIZE(_szDrive));
_iDriveType = iDriveType;
return S_OK;
}
HRESULT CAutoPlayDlg::_InitDataObjects()
{
HRESULT hr = S_FALSE;
BOOL fIsCDDrive = FALSE;
DWORD dwDriveCapabilities = HWDDC_CDROM;
DWORD dwMediaCapabilities = HWDMC_CDROM;
CMountPoint* pmtpt = CMountPoint::GetMountPoint(_szDrive);
if (pmtpt)
{
fIsCDDrive = pmtpt->IsCDROM();
if (fIsCDDrive)
{
hr = pmtpt->GetCDInfo(&dwDriveCapabilities, &dwMediaCapabilities);
}
pmtpt->Release();
}
for (DWORD dw = 0; SUCCEEDED(hr) && (dw < ARRAYSIZE(g_rgdwContentTypes));
++dw)
{
BOOL fAddOption = TRUE;
if (fIsCDDrive)
{
if ((g_rgdwContentTypes[dw] & CT_DVDMOVIE) &&
!(dwDriveCapabilities & (HWDDC_DVDROM | HWDDC_DVDRECORDABLE | HWDDC_DVDREWRITABLE)))
{
fAddOption = FALSE;
}
else if ((g_rgdwContentTypes[dw] & CT_BLANKCDR) &&
!(dwDriveCapabilities & (HWDDC_CDRECORDABLE | HWDDC_CDREWRITABLE)))
{
fAddOption = FALSE;
}
}
else
{
if (g_rgdwContentTypes[dw] &
(CT_CDAUDIO | CT_DVDMOVIE | CT_BLANKCDR))
{
fAddOption = FALSE;
}
}
if (fAddOption)
{
_rgpContentTypeData[dw] = new CContentTypeData();
if (_rgpContentTypeData[dw])
{
hr = (_rgpContentTypeData[dw])->Init(_szDrive, g_rgdwContentTypes[dw]);
if (SUCCEEDED(hr))
{
hr = _dlmanager.AddDataObject(_rgpContentTypeData[dw]);
}
else
{
// Let's just skip this one, do not go out of the loop and
// abort the whole initialization.
hr = S_FALSE;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
return hr;
}
HRESULT CAutoPlayDlg::_InitListView()
{
HWND hwndList = GetDlgItem(_hwnd, IDC_AP_LIST);
HRESULT hr = _uilListView.Init(hwndList);
if (SUCCEEDED(hr))
{
Shell_GetImageLists(NULL, &_himagelist);
if (_himagelist)
{
SendMessage(hwndList, CBEM_SETIMAGELIST, 0, (LPARAM)_himagelist);
hr = S_OK;
}
}
return hr;
}
HRESULT CAutoPlayDlg::_FillListView()
{
HRESULT hr = S_FALSE;
for (DWORD dw = 0; SUCCEEDED(hr) && (dw < ARRAYSIZE(_rgpContentTypeData));
++dw)
{
if (_rgpContentTypeData[dw])
{
CContentTypeCBItem* pctlvitem = new CContentTypeCBItem();
if (pctlvitem)
{
hr = pctlvitem->InitData(_rgpContentTypeData[dw]);
if (SUCCEEDED(hr))
{
hr = _uilListView.AddItem(pctlvitem);
}
if (FAILED(hr))
{
delete pctlvitem;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
return hr;
}
CAutoPlayDlg::~CAutoPlayDlg()
{
for (DWORD dw = 0; dw < ARRAYSIZE(_rgpContentTypeData); ++dw)
{
if (_rgpContentTypeData[dw])
{
(_rgpContentTypeData[dw])->Release();
}
}
#ifdef AUTOPLAYDLG_LEAKPARANOIA
// If this is on, you cannot open two Autoplay dialogs (e.g.: Autoplay
// proppage and Autoplay prompt) at the same time and then close one.
// It will assert for sure when you close the first one.
ASSERT(!_DbgLocalAllocCount);
#endif
}