Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1123 lines
31 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: cpaction.cpp
//
// This module implements the various 'action' objects used by the
// Control Panel's 'category' view. Each 'link' in the UI has an
// associated 'action'. The action objects are defined in cpnamespc.cpp.
// All 'action' objects are designed so that object construction is
// very cheap and that minimal processing is performed until the action
// is invoked.
//
//--------------------------------------------------------------------------
#include "shellprv.h"
#include <idhidden.h>
#include "cpviewp.h"
#include "cpaction.h"
#include "cpguids.h"
#include "cpuiele.h"
#include "cputil.h"
//// from shell\sdspatch\sdfolder.cpp
VARIANT_BOOL GetBarricadeStatus(LPCTSTR pszValueName);
//
// Disable warning. ShellExecute uses SEH.
// "nonstandard extension used: 'Execute' uses SEH and 'se' has destructor".
//
#pragma warning( push )
#pragma warning( disable:4509 )
using namespace CPL;
//
// Helper to append a bare file name to the system directory.
//
HRESULT
AppendToSysDir(
LPCWSTR pszToAppend, // Append this
LPWSTR pszPath, // [out] Contains concatenated result
size_t cchPath
)
{
HRESULT hr = E_FAIL;
WCHAR szTemp[MAX_PATH];
if (0 != GetSystemDirectory(szTemp, ARRAYSIZE(szTemp)))
{
if (PathAppend(szTemp, pszToAppend))
{
hr = StringCchCopy(pszPath, cchPath, szTemp);
}
else
{
hr = E_FAIL;
}
}
else
{
hr = ResultFromLastError();
}
return THR(hr);
}
HRESULT
CRestrictApplet::IsRestricted(
ICplNamespace *pns
) const
{
UNREFERENCED_PARAMETER(pns);
DBG_ENTER(FTF_CPANEL, "RestrictApplet");
HRESULT hr = S_FALSE;
if (!IsAppletEnabled(m_pszFile, m_pszApplet))
{
hr = S_OK;
}
DBG_EXIT_HRES(FTF_CPANEL, "RestrictApplet", hr);
return hr;
}
//--------------------------------------------------------------------------
// CAction implementation
//--------------------------------------------------------------------------
CAction::CAction(
const CPL::IRestrict *pRestrict // optional. default = NULL
) : m_pRestrict(pRestrict)
{
}
//
// Returns:
// S_FALSE - Not restricted.
// S_OK - Restricted.
// Failure - Cannot determine.
//
HRESULT
CAction::IsRestricted(
ICplNamespace *pns
) const
{
HRESULT hr = S_FALSE; // Assume not restricted.
if (NULL != m_pRestrict)
{
hr = m_pRestrict->IsRestricted(pns);
}
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenUserMgrApplet implementation
//--------------------------------------------------------------------------
COpenUserMgrApplet::COpenUserMgrApplet(
const CPL::IRestrict *pRestrict // optional. default = NULL
): CAction(pRestrict)
{
}
HRESULT
COpenUserMgrApplet::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenUserMgrApplet::Execute");
HRESULT hr = E_FAIL;
if (IsOsServer())
{
CShellExecuteSysDir action(L"lusrmgr.msc");
hr = action.Execute(hwndParent, punkSite);
}
else
{
COpenCplAppletSysDir action(L"nusrmgr.cpl");
hr = action.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenUserMgrApplet::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenCplApplet implementation
//--------------------------------------------------------------------------
COpenCplApplet::COpenCplApplet(
LPCWSTR pszApplet,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_pszApplet(pszApplet)
{
ASSERT(NULL != pszApplet);
}
HRESULT
COpenCplApplet::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenCplApplet::Execute");
ASSERT(NULL != m_pszApplet);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
//
// Build a path consisting of the system directory, the
// "%SystemDir%\shell32,Control_RunDLL" string and the
// applet name. i.e.:
//
// "c:\windows\system32\shell32,Control_RundLL desk.cpl"
//
WCHAR szArgs[MAX_PATH * 2];
HRESULT hr = AppendToSysDir(L"shell32.dll,Control_RunDLL ", szArgs, ARRAYSIZE(szArgs));
if (SUCCEEDED(hr))
{
hr = StringCchCat(szArgs, ARRAYSIZE(szArgs), m_pszApplet);
if (SUCCEEDED(hr))
{
//
// Build a path to rundll32.exe.
// i.e.:
// "c:\windows\system32\rundll32.exe"
//
WCHAR szRunDll32[MAX_PATH];
hr = AppendToSysDir(L"rundll32.exe", szRunDll32, ARRAYSIZE(szRunDll32));
if (SUCCEEDED(hr))
{
TraceMsg(TF_CPANEL, "Executing: \"%s %s\"", szRunDll32, szArgs);
SHELLEXECUTEINFOW sei = {
sizeof(sei), // cbSize;
0, // fMask
hwndParent, // hwnd
NULL, // lpVerb
szRunDll32, // lpFile
szArgs, // lpParameters
NULL, // lpDirectory
SW_SHOWNORMAL, // nShow
0, // hInstApp
NULL, // lpIDList
NULL, // lpClass
NULL, // hkeyClass
0, // dwHotKey
NULL, // hIcon
NULL // hProcess
};
if (!ShellExecuteExW(&sei))
{
hr = ResultFromLastError();
}
}
}
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenCplApplet::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenCplAppletSysDir implementation
//
// Minor extension of COpenCplApplet that assumes the applet is in
// %SystemRoot%\System32 directory.
//
//--------------------------------------------------------------------------
COpenCplAppletSysDir::COpenCplAppletSysDir(
LPCWSTR pszApplet,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : COpenCplApplet(pszApplet, pRestrict)
{
ASSERT(NULL != pszApplet);
}
HRESULT
COpenCplAppletSysDir::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenCplAppletSysDir::Execute");
ASSERT(NULL != m_pszApplet);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
//
// Build a path consisting of the system directory and the
// applet name. i.e.:
//
// "c:\windows\system32\desk.cpl"
//
WCHAR szAppletPath[MAX_PATH];
HRESULT hr = AppendToSysDir(m_pszApplet, szAppletPath, ARRAYSIZE(szAppletPath));
if (SUCCEEDED(hr))
{
COpenCplApplet oca(szAppletPath);
hr = oca.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenCplAppletSysDir::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenDeskCpl implementation
//--------------------------------------------------------------------------
COpenDeskCpl::COpenDeskCpl(
eDESKCPLTAB eCplTab,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_eCplTab(eCplTab)
{
}
HRESULT
COpenDeskCpl::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenDeskCpl::Execute");
TraceMsg(TF_CPANEL, "Desk CPL tab ID = %d", m_eCplTab);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
HRESULT hr = E_FAIL;
WCHAR szTab[MAX_PATH];
const int iTab = CPL::DeskCPL_GetTabIndex(m_eCplTab, szTab, ARRAYSIZE(szTab));
if (CPLTAB_ABSENT != iTab)
{
WCHAR szArgs[MAX_PATH];
hr = StringCchPrintfW(szArgs, ARRAYSIZE(szArgs), L"desk.cpl ,@%ls", szTab);
if (SUCCEEDED(hr))
{
COpenCplAppletSysDir oca(szArgs);
hr = oca.Execute(hwndParent, punkSite);
}
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenDeskCpl::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CNavigateURL implementation
//--------------------------------------------------------------------------
CNavigateURL::CNavigateURL(
LPCWSTR pszURL,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_pszURL(pszURL)
{
ASSERT(NULL != pszURL);
}
HRESULT
CNavigateURL::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CNavigateURL::Execute");
ASSERT(NULL != m_pszURL);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(hwndParent);
TraceMsg(TF_CPANEL, "URL = \"%s\"", m_pszURL);
IWebBrowser2 *pwb;
HRESULT hr = IUnknown_QueryService(punkSite, SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pwb);
if (SUCCEEDED(hr))
{
LPTSTR pszExpanded;
hr = CPL::ExpandEnvironmentVars(m_pszURL, &pszExpanded);
if (SUCCEEDED(hr))
{
VARIANT varURL;
hr = InitVariantFromStr(&varURL, pszExpanded);
if (SUCCEEDED(hr))
{
VARIANT varEmpty;
VariantInit(&varEmpty);
VARIANT varFlags;
varFlags.vt = VT_UINT;
varFlags.uintVal = 0;
hr = pwb->Navigate2(&varURL, &varFlags, &varEmpty, &varEmpty, &varEmpty);
VariantClear(&varURL);
}
LocalFree(pszExpanded);
}
pwb->Release();
}
DBG_EXIT_HRES(FTF_CPANEL, "CNavigateURL::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenTroubleshooter implementation
//--------------------------------------------------------------------------
COpenTroubleshooter::COpenTroubleshooter(
LPCWSTR pszTs,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_pszTs(pszTs)
{
ASSERT(NULL != pszTs);
}
HRESULT
COpenTroubleshooter::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenTroubleshooter::Execute");
ASSERT(NULL != m_pszTs);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
WCHAR szPath[MAX_PATH];
HRESULT hr = StringCchPrintfW(szPath, ARRAYSIZE(szPath), L"hcp://help/tshoot/%s", m_pszTs);
if (SUCCEEDED(hr))
{
CNavigateURL actionURL(szPath);
hr = actionURL.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenTroubleshooter::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CShellExecute implementation
//--------------------------------------------------------------------------
CShellExecute::CShellExecute(
LPCWSTR pszExe,
LPCWSTR pszArgs, // optional. default = NULL.
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_pszExe(pszExe),
m_pszArgs(pszArgs)
{
ASSERT(NULL != pszExe);
}
HRESULT
CShellExecute::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CShellExecute::Execute");
ASSERT(NULL != m_pszExe);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
TraceMsg(TF_CPANEL, "ShellExecute: \"%s %s\"", m_pszExe, m_pszArgs ? m_pszArgs : L"<no args>");
SHELLEXECUTEINFOW sei = {
sizeof(sei), // cbSize;
SEE_MASK_DOENVSUBST, // fMask
hwndParent, // hwnd
L"open", // lpVerb
m_pszExe, // lpFile
m_pszArgs, // lpParameters
NULL, // lpDirectory
SW_SHOWNORMAL, // nShow
0, // hInstApp
NULL, // lpIDList
NULL, // lpClass
NULL, // hkeyClass
0, // dwHotKey
NULL, // hIcon
NULL // hProcess
};
HRESULT hr = S_OK;
if (!ShellExecuteExW(&sei))
{
hr = ResultFromLastError();
}
DBG_EXIT_HRES(FTF_CPANEL, "CShellExecute::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CShellExecuteSysDir implementation
// Simply wraps CShellExecute assuming that the EXE exists in the
// SYSTEM32 directory.
//--------------------------------------------------------------------------
CShellExecuteSysDir::CShellExecuteSysDir(
LPCWSTR pszExe,
LPCWSTR pszArgs, // optional. default = NULL.
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CShellExecute(pszExe, pszArgs, pRestrict)
{
ASSERT(NULL != pszExe);
}
HRESULT
CShellExecuteSysDir::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CShellExecuteSysDir::Execute");
ASSERT(NULL != m_pszExe);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
TraceMsg(TF_CPANEL, "ShellExecuteSysDir: \"%s %s\"", m_pszExe, m_pszArgs ? m_pszArgs : L"<no args>");
//
// Build a path consisting of the system directory and the
// EXE name. i.e.:
//
// "c:\windows\system32\myapp.exe"
//
WCHAR szExePath[MAX_PATH];
HRESULT hr = AppendToSysDir(m_pszExe, szExePath, ARRAYSIZE(szExePath));
if (SUCCEEDED(hr))
{
CShellExecute se(szExePath, m_pszArgs);
hr = se.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "CShellExecuteSysDir::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CRundll32 implementation
// This is a simple wrapper around CShellExecute that saves an instance
// definition from having to type L"%SystemRoot%\\system32\\rundll32.exe".
//--------------------------------------------------------------------------
CRunDll32::CRunDll32(
LPCWSTR pszArgs,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_pszArgs(pszArgs)
{
ASSERT(NULL != pszArgs);
}
HRESULT
CRunDll32::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CRunDll32::Execute");
ASSERT(NULL != m_pszArgs);
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
TraceMsg(TF_CPANEL, "CRunDll32: \"%s\"", m_pszArgs);
WCHAR szPath[MAX_PATH];
HRESULT hr = AppendToSysDir(L"rundll32.exe", szPath, ARRAYSIZE(szPath));
if (SUCCEEDED(hr))
{
CShellExecute se(szPath, m_pszArgs);
hr = se.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "CRunDll32::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CExecDiskUtil implementation
//--------------------------------------------------------------------------
CExecDiskUtil::CExecDiskUtil(
eDISKUTILS eUtil,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_eUtil(eUtil)
{
ASSERT(eDISKUTIL_NUMUTILS > m_eUtil);
}
HRESULT
CExecDiskUtil::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CExecDiskUtil::Execute");
TCHAR szValue[MAX_PATH];
DWORD dwType;
DWORD cbValue = sizeof(szValue);
//
// These strings must remain in sync with the eDISKUTILS enumeration.
//
static LPCTSTR rgpszRegNames[] = {
TEXT("MyComputer\\backuppath"), // eDISKUTIL_BACKUP
TEXT("MyComputer\\defragpath"), // eDISKUTIL_DEFRAG
TEXT("MyComputer\\cleanuppath"), // eDISKUTIL_CLEANUP
};
HRESULT hr = SKGetValue(SHELLKEY_HKLM_EXPLORER,
rgpszRegNames[int(m_eUtil)],
NULL,
&dwType,
szValue,
&cbValue);
if (SUCCEEDED(hr))
{
LPTSTR pszExpanded = NULL;
//
// Expand environment strings.
// According to the code in shell32\drvx.cpp, some apps
// use embedded env vars even if the value type is REG_SZ.
//
hr = CPL::ExpandEnvironmentVars(szValue, &pszExpanded);
if (SUCCEEDED(hr))
{
//
// The drive utility command strings were designed to be
// invoked from the drives property page. They therefore
// accept a drive letter. Since control panel launches
// the utilities for no particular drive, we need to remove
// the "%c:" format specifier.
//
hr = _RemoveDriveLetterFmtSpec(pszExpanded);
if (SUCCEEDED(hr))
{
TCHAR szArgs[MAX_PATH] = {0};
PathRemoveBlanks(pszExpanded);
hr = PathSeperateArgs(pszExpanded, szArgs, ARRAYSIZE(szArgs), NULL);
if (SUCCEEDED(hr))
{
//
// Note that it's valid to use a NULL restriction here.
// If there's a restriction on the CExecDiskUtil object
// we won't get this far (i.e. Execute isn't called).
//
CShellExecute exec(pszExpanded, szArgs);
hr = exec.Execute(hwndParent, punkSite);
}
}
LocalFree(pszExpanded);
}
}
DBG_EXIT_HRES(FTF_CPANEL, "CExecDiskUtil::Execute", hr);
return THR(hr);
}
//
// The command line strings for the backup, defrag and disk cleanup utilities
// can contain a format specifier for the drive letter. That's because
// they're designed to be opened from a particular volume's "Tools" property
// page. Control Panel launches these from outside the context of any particular
// volume. Therefore, the drive letter is not available and the the format
// specifier is unused. This function removes that format specifier if it exists.
//
// i.e.: "c:\windows\system32\ntbackup.exe" -> "c:\windows\system32\ntbackpu.exe"
// "c:\windows\system32\cleanmgr.exe /D %c:" -> "c:\windows\system32\cleanmgr.exe"
// "c:\windows\system32\defrg.msc %c:" -> "c:\windows\system32\defrg.msc"
//
HRESULT
CExecDiskUtil::_RemoveDriveLetterFmtSpec( // [static]
LPTSTR pszCmdLine
)
{
LPCTSTR pszRead = pszCmdLine;
LPTSTR pszWrite = pszCmdLine;
while(*pszRead)
{
if (TEXT('%') == *pszRead && TEXT('c') == *(pszRead + 1))
{
//
// Skip over the "%c" or "%c:" fmt specifier.
//
pszRead += 2;
if (TEXT(':') == *pszRead)
{
pszRead++;
}
}
if (*pszRead)
{
*pszWrite++ = *pszRead++;
}
}
*pszWrite = *pszRead; // pick up null terminator.
return S_OK;
}
//--------------------------------------------------------------------------
// COpenCplCategory implementation
//--------------------------------------------------------------------------
COpenCplCategory::COpenCplCategory(
eCPCAT eCategory,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_eCategory(eCategory)
{
}
HRESULT
COpenCplCategory::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenCplCategory::Execute");
TraceMsg(TF_CPANEL, "Category ID = %d", m_eCategory);
ASSERT(NULL != punkSite);
UNREFERENCED_PARAMETER(hwndParent);
IShellBrowser *psb;
HRESULT hr = CPL::ShellBrowserFromSite(punkSite, &psb);
if (SUCCEEDED(hr))
{
LPITEMIDLIST pidlFolder;
hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlFolder);
if (SUCCEEDED(hr))
{
WCHAR szCategory[10];
hr = StringCchPrintfW(szCategory, ARRAYSIZE(szCategory), L"%d", m_eCategory);
if (SUCCEEDED(hr))
{
LPITEMIDLIST pidlTemp = ILAppendHiddenStringW(pidlFolder, IDLHID_NAVIGATEMARKER, szCategory);
if (NULL == pidlTemp)
{
hr = E_OUTOFMEMORY;
}
else
{
pidlFolder = pidlTemp;
pidlTemp = NULL;
hr = CPL::BrowseIDListInPlace(pidlFolder, psb);
}
ILFree(pidlFolder);
}
}
psb->Release();
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenCplCategory2 implementation
//--------------------------------------------------------------------------
COpenCplCategory2::COpenCplCategory2(
eCPCAT eCategory,
const IAction *pDefAction,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_eCategory(eCategory),
m_pDefAction(pDefAction)
{
}
HRESULT
COpenCplCategory2::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "COpenCplCategory2::Execute");
TraceMsg(TF_CPANEL, "Category ID = %d", m_eCategory);
ASSERT(NULL != punkSite);
bool bOpenCategory = false;
HRESULT hr = _ExecuteActionOnSingleCplApplet(hwndParent, punkSite, &bOpenCategory);
if (SUCCEEDED(hr))
{
if (bOpenCategory)
{
//
// Category has more than one CPL.
// Open the category page.
//
COpenCplCategory action(m_eCategory);
hr = action.Execute(hwndParent, punkSite);
}
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory2::Execute", hr);
return THR(hr);
}
HRESULT
COpenCplCategory2::_ExecuteActionOnSingleCplApplet(
HWND hwndParent,
IUnknown *punkSite,
bool *pbOpenCategory // optional. Can be NULL
) const
{
DBG_ENTER(FTF_CPANEL, "COpenCplCategory2::_ExecuteActionOnSingleCplApplet");
bool bOpenCategory = true;
ICplView *pview;
HRESULT hr = CPL::ControlPanelViewFromSite(punkSite, &pview);
if (SUCCEEDED(hr))
{
IServiceProvider *psp;
hr = pview->QueryInterface(IID_IServiceProvider, (void **)&psp);
if (SUCCEEDED(hr))
{
ICplNamespace *pns;
hr = psp->QueryService(SID_SControlPanelView, IID_ICplNamespace, (void **)&pns);
if (SUCCEEDED(hr))
{
ICplCategory *pCategory;
hr = pns->GetCategory(m_eCategory, &pCategory);
if (SUCCEEDED(hr))
{
IEnumUICommand *penum;
hr = pCategory->EnumCplApplets(&penum);
if (SUCCEEDED(hr))
{
//
// See if the category has more than one CPL applet
// assigned to it.
//
ULONG cApplets = 0;
IUICommand *rgpuic[2] = {0};
if (SUCCEEDED(hr = penum->Next(ARRAYSIZE(rgpuic), rgpuic, &cApplets)))
{
for (int i = 0; i < ARRAYSIZE(rgpuic); i++)
{
ATOMICRELEASE(rgpuic[i]);
}
if (2 > cApplets)
{
//
// There's zero or one CPLs registered for this category.
// Simply execute the default action. If there's one
// we assume it's the "default" applet (i.e. ARP or
// User Accounts).
//
hr = m_pDefAction->IsRestricted(pns);
if (SUCCEEDED(hr))
{
if (S_FALSE == hr)
{
bOpenCategory = false;
hr = m_pDefAction->Execute(hwndParent, punkSite);
}
else
{
//
// Default action is restricted.
// Open the category page. Note that the
// category page may be displayed as a 'barrier'
// if no tasks or CPL applets are available.
//
ASSERT(bOpenCategory);
}
}
}
}
penum->Release();
}
pCategory->Release();
}
pns->Release();
}
psp->Release();
}
pview->Release();
}
if (NULL != pbOpenCategory)
{
*pbOpenCategory = bOpenCategory;
}
DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory2::_ExecuteActionOnSingleCplApplet", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// COpenCplView implementation
//--------------------------------------------------------------------------
COpenCplView::COpenCplView(
eCPVIEWTYPE eViewType,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_eViewType(eViewType)
{
}
HRESULT
COpenCplView::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
UNREFERENCED_PARAMETER(hwndParent);
ASSERT(NULL != punkSite);
HRESULT hr = _SetFolderBarricadeStatus();
if (SUCCEEDED(hr))
{
IShellBrowser *psb;
hr = CPL::ShellBrowserFromSite(punkSite, &psb);
if (SUCCEEDED(hr))
{
LPITEMIDLIST pidlFolder;
hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlFolder);
if (SUCCEEDED(hr))
{
hr = CPL::BrowseIDListInPlace(pidlFolder, psb);
ILFree(pidlFolder);
}
psb->Release();
}
}
return THR(hr);
}
HRESULT
COpenCplView::_SetFolderBarricadeStatus(
void
) const
{
VARIANT_BOOL vtb = VARIANT_FALSE;
if (eCPVIEWTYPE_CATEGORY == m_eViewType)
{
vtb = VARIANT_TRUE;
}
else
{
ASSERT(eCPVIEWTYPE_CLASSIC == m_eViewType);
}
HRESULT hr = CPL::SetControlPanelBarricadeStatus(vtb);
return THR(hr);
}
//--------------------------------------------------------------------------
// CAddPrinter implementation
//--------------------------------------------------------------------------
CAddPrinter::CAddPrinter(
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict)
{
}
HRESULT
CAddPrinter::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
DBG_ENTER(FTF_CPANEL, "CAddPrinter::Execute");
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
HRESULT hr = E_FAIL;
if (SHInvokePrinterCommandW(hwndParent,
PRINTACTION_OPEN,
L"WinUtils_NewObject",
NULL,
FALSE))
{
//
// Navigate to the printers folder after invoking the add-printer wizard.
// This gives the user visual feedback when a printer is added. We navigate
// even if the user cancels the wizard because we cannot determine if the
// wizard was cancelled. We've determined this is acceptable.
//
CNavigateURL prnfldr(L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}");
hr = prnfldr.Execute(hwndParent, punkSite);
}
DBG_EXIT_HRES(FTF_CPANEL, "CAddPrinter::Execute", hr);
return THR(hr);
}
//--------------------------------------------------------------------------
// CTrayCommand implementation
//--------------------------------------------------------------------------
CTrayCommand::CTrayCommand(
UINT idm,
const CPL::IRestrict *pRestrict // optional. default = NULL
) : CAction(pRestrict),
m_idm(idm)
{
}
HRESULT
CTrayCommand::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
UNREFERENCED_PARAMETER(hwndParent);
UNREFERENCED_PARAMETER(punkSite);
// APPHACK! 221008 DesktopX creates their own window with class
// name "Shell_TrayWnd", so if we're not careful we will end
// posting the messages to the wrong window. They create their
// window with the title "CTrayServer"; ours has a null title.
// Use the null title to find the correct window.
HWND hwndTray = FindWindowA(WNDCLASS_TRAYNOTIFY, "");
if (hwndTray)
{
PostMessage(hwndTray, WM_COMMAND, m_idm, 0);
}
return S_OK;
}
//--------------------------------------------------------------------------
// CActionNYI implementation
//--------------------------------------------------------------------------
CActionNYI::CActionNYI(
LPCWSTR pszText
) : m_pszText(pszText)
{
}
HRESULT
CActionNYI::Execute(
HWND hwndParent,
IUnknown *punkSite
) const
{
ASSERT(NULL == hwndParent || IsWindow(hwndParent));
UNREFERENCED_PARAMETER(punkSite);
HRESULT hr = E_OUTOFMEMORY;
if (NULL != m_pszText)
{
MessageBoxW(hwndParent, m_pszText, L"Action Not Yet Implemented", MB_OK);
hr = S_OK;
}
return THR(hr);
}
#pragma warning( pop )