|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: cputil.cpp
//
//--------------------------------------------------------------------------
#include "shellprv.h"
#include "cpviewp.h"
#include "cputil.h"
//
// Loads a string based upon the description.
// Example: shell32,42
//
// lpStrDesc - contains the string description
//
HRESULT CPL::LoadStringFromResource( LPCWSTR pszStrDesc, LPWSTR *ppszOut ) { ASSERT(NULL != pszStrDesc); ASSERT(NULL != ppszOut); ASSERT(!IsBadWritePtr(ppszOut, sizeof(*ppszOut)));
*ppszOut = NULL; WCHAR szFile[MAX_PATH]; HRESULT hr = StringCchCopyW(szFile, ARRAYSIZE(szFile), pszStrDesc); // the below writes this buffer
if (SUCCEEDED(hr)) { int iStrID = PathParseIconLocationW(szFile); if (iStrID < 0) { iStrID = -iStrID; // support ",-id" syntax
}
HMODULE hLib = LoadLibraryExW(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE); if (hLib) { WCHAR szTemp[INFOTIPSIZE]; // INFOTIPSIZE is the largest string type we're expected to load
if (0 < LoadStringW(hLib, (UINT)iStrID, szTemp, ARRAYSIZE(szTemp))) { hr = SHStrDup(szTemp, ppszOut); } else { hr = ResultFromLastError(); } FreeLibrary(hLib); } else { hr = ResultFromLastError(); } }
return THR(hr); }
//
// Shell icon functions deal in terms of "small" and "large" icons.
// This function determines which should be used for a
// given eCPIMGSIZE value.
//
bool CPL::ShouldUseSmallIconForDesiredSize( eCPIMGSIZE eSize ) { UINT cx; UINT cy; ImageDimensionsFromDesiredSize(eSize, &cx, &cy);
if (int(cx) <= GetSystemMetrics(SM_CXSMICON)) { return true; } return false; }
//
// This function returns a eCPIMGSIZE value to pixel dimensions.
// This indirection lets us specify image sizes in abstract terms
// then convert to physical pixel dimensions when required. If
// you want to change the size of images used for a particular
// Control Panel UI item type, this is where you change it.
//
void CPL::ImageDimensionsFromDesiredSize( eCPIMGSIZE eSize, UINT *pcx, UINT *pcy ) { ASSERT(NULL != pcx); ASSERT(!IsBadWritePtr(pcx, sizeof(*pcx))); ASSERT(NULL != pcy); ASSERT(!IsBadWritePtr(pcy, sizeof(*pcy))); *pcx = *pcy = 0;
//
// This table converts eCPIMGSIZE values into actual
// image size values. A couple of things to note:
//
// 1. If you want to change the image size associated with
// an eIMGSIZE value, simply change these numbers.
//
// 2. If actual image size is dependent upon some system
// configuration parameter, do the interpretation of
// that parameter here making the size a function
// of that parameter.
//
static const SIZE rgSize[] = { { 16, 16 }, // eCPIMGSIZE_WEBVIEW
{ 16, 16 }, // eCPIMGSIZE_TASK
{ 48, 48 }, // eCPIMGSIZE_CATEGORY
{ 32, 32 }, // eCPIMGSIZE_BANNER
{ 32, 32 } // eCPIMGSIZE_APPLET
};
ASSERT(int(eSize) >= 0 && int(eSize) < ARRAYSIZE(rgSize)); *pcx = rgSize[eSize].cx; *pcy = rgSize[eSize].cy; }
HRESULT CPL::LoadIconFromResourceID( LPCWSTR pszModule, int idIcon, eCPIMGSIZE eSize, HICON *phIcon ) { ASSERT(NULL != pszModule); ASSERT(NULL != phIcon); ASSERT(!IsBadWritePtr(phIcon, sizeof(*phIcon))); ASSERT(0 < idIcon);
HRESULT hr = E_FAIL; HICON hIcon = NULL; HMODULE hModule = LoadLibraryExW(pszModule, NULL, LOAD_LIBRARY_AS_DATAFILE); if (hModule) { UINT cxIcon; UINT cyIcon;
ImageDimensionsFromDesiredSize(eSize, &cxIcon, &cyIcon);
hIcon = (HICON)LoadImage(hModule, MAKEINTRESOURCE(idIcon), IMAGE_ICON, cxIcon, cyIcon, 0);
if (NULL != hIcon) { hr = S_OK; } else { hr = ResultFromLastError(); } FreeLibrary(hModule); } else { hr = ResultFromLastError(); }
*phIcon = hIcon; return THR(hr); }
HRESULT CPL::LoadIconFromResourceIndex( LPCWSTR pszModule, int iIcon, eCPIMGSIZE eSize, HICON *phIcon ) { ASSERT(NULL != pszModule); ASSERT(NULL != phIcon); ASSERT(!IsBadWritePtr(phIcon, sizeof(*phIcon)));
if (-1 == iIcon) { //
// Special case. -1 is an invalid icon index/id.
//
iIcon = 0; }
HICON hIcon = NULL; HRESULT hr = E_FAIL; if (CPL::ShouldUseSmallIconForDesiredSize(eSize)) { if (0 < ExtractIconExW(pszModule, iIcon, NULL, &hIcon, 1)) { hr = S_OK; } else { TraceMsg(TF_ERROR, "ExtractIconEx failed for small icon (index %d) in module \"%s\"", iIcon, pszModule); } } else { if (0 < ExtractIconExW(pszModule, iIcon, &hIcon, NULL, 1)) { hr = S_OK; } else { TraceMsg(TF_ERROR, "ExtractIconEx failed for large icon (index %d) in module \"%s\"", iIcon, pszModule); } } *phIcon = hIcon; return THR(hr); }
HRESULT CPL::LoadIconFromResource( LPCWSTR pszResource, eCPIMGSIZE eSize, HICON *phIcon ) { ASSERT(NULL != pszResource); ASSERT(NULL != phIcon); ASSERT(!IsBadWritePtr(phIcon, sizeof(*phIcon)));
*phIcon = NULL;
//
// PathParseIconLocation modifies it's input string.
//
WCHAR szResource[MAX_PATH]; HRESULT hr = StringCchCopyW(szResource, ARRAYSIZE(szResource), pszResource); if (SUCCEEDED(hr)) { int idIcon = PathParseIconLocationW(szResource); if (-1 == idIcon) { //
// Special case. -1 is an invalid icon ID.
//
idIcon = 0; }
if (0 > idIcon) { hr = CPL::LoadIconFromResourceID(szResource, -idIcon, eSize, phIcon); } else { hr = CPL::LoadIconFromResourceIndex(szResource, idIcon, eSize, phIcon); } } return THR(hr); }
HRESULT CPL::ExtractIconFromPidl( IShellFolder *psf, LPCITEMIDLIST pidl, eCPIMGSIZE eSize, HICON *phIcon ) { ASSERT(NULL != psf); ASSERT(NULL != pidl); ASSERT(NULL != phIcon); ASSERT(!IsBadWritePtr(phIcon, sizeof(*phIcon)));
*phIcon = NULL;
IExtractIcon *pei; HRESULT hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IExtractIcon, NULL, (void **)&pei); if (SUCCEEDED(hr)) { TCHAR szFile[MAX_PATH]; INT iIcon; UINT uFlags = 0; hr = pei->GetIconLocation(GIL_FORSHELL, szFile, ARRAYSIZE(szFile), &iIcon, &uFlags); if (SUCCEEDED(hr)) { if (0 == (GIL_NOTFILENAME & uFlags)) { hr = CPL::LoadIconFromResourceIndex(szFile, iIcon, eSize, phIcon); } else { HICON hIconLarge = NULL; HICON hIconSmall = NULL;
const int cxIcon = GetSystemMetrics(SM_CXICON); const int cxSmIcon = GetSystemMetrics(SM_CXSMICON); hr = pei->Extract(szFile, iIcon, &hIconLarge, &hIconSmall, MAKELONG(cxIcon, cxSmIcon)); if (SUCCEEDED(hr)) { if (CPL::ShouldUseSmallIconForDesiredSize(eSize)) { *phIcon = hIconSmall; hIconSmall = NULL; } else { *phIcon = hIconLarge; hIconLarge = NULL; } } //
// Destroy any icons not being returned.
//
if (NULL != hIconSmall) { DestroyIcon(hIconSmall); } if (NULL != hIconLarge) { DestroyIcon(hIconLarge); } } } pei->Release(); } ASSERT(FAILED(hr) || NULL != *phIcon); if (NULL == *phIcon) { //
// If by-chance a NULL icon handle is retrieved, we don't
// want to return a success code.
//
hr = E_FAIL; } return THR(hr); }
// Checks the given restriction. Returns TRUE (restricted) if the
// specified key/value exists and is non-zero, false otherwise
BOOL DeskCPL_CheckRestriction( HKEY hKey, LPCWSTR lpszValueName ) { ASSERT(NULL != lpszValueName);
DWORD dwData; DWORD dwSize = sizeof(dwData); if ((ERROR_SUCCESS == RegQueryValueExW(hKey, lpszValueName, NULL, NULL, (BYTE *)&dwData, &dwSize)) && dwData) { return TRUE; } return FALSE; }
//
// Function returns the actual tab index given the default tab index.
// The actual tab index will be different than the default value if there are
// various system policies in effect which disable some tabs
//
//
// To add further restrictions, modify the aTabMap to include the default tab
// index and the corresponding policy. Also, you should keep the eDESKCPLTAB enum
// in sync with the aTabMap array.
//
//
int CPL::DeskCPL_GetTabIndex( CPL::eDESKCPLTAB iTab, OPTIONAL LPWSTR pszCanonicalName, OPTIONAL DWORD cchSize ) { HKEY hKey; int iTabActual = CPL::CPLTAB_ABSENT;
if (iTab >= 0 && iTab < CPL::CPLTAB_DESK_MAX) { //
// While adding more tabs, make sure that it is entered in the right position in the
// the array below. So, for example, if the default tab index of the new tab is 2, it
// should be the aTabMap[2] entry (Currently CPLTAB_DESK_APPEARANCE is
// the one with tab index = 2). You will have to modify eDESKCPLTAB accordingly too.
//
struct { int nIndex; // the canonical name of the tab (don't use indexes because they change with policies or revs)
LPCWSTR pszCanoncialTabName; // the canonical name of the tab (don't use indexes because they change with policies or revs)
LPCWSTR pszRestriction; // corresponding restriction
} aTabMap[CPL::CPLTAB_DESK_MAX] = { { 0, SZ_DISPLAYCPL_OPENTO_DESKTOP, REGSTR_VAL_DISPCPL_NOBACKGROUNDPAGE }, // CPLTAB_DESK_BACKGROUND == 0
{ 1, SZ_DISPLAYCPL_OPENTO_SCREENSAVER, REGSTR_VAL_DISPCPL_NOSCRSAVPAGE }, // CPLTAB_DESK_SCREENSAVER == 1
{ 2, SZ_DISPLAYCPL_OPENTO_APPEARANCE, REGSTR_VAL_DISPCPL_NOAPPEARANCEPAGE }, // CPLTAB_DESK_APPEARANCE == 2
{ 3, SZ_DISPLAYCPL_OPENTO_SETTINGS, REGSTR_VAL_DISPCPL_NOSETTINGSPAGE } // CPLTAB_DESK_SETTINGS == 3
};
#ifdef DEBUG
//
// Verify proper initialization of the nIndex member of aTabMap[]
//
for (int k=0; k < ARRAYSIZE(aTabMap); k++) { ASSERT(aTabMap[k].nIndex == k); } #endif
iTabActual = aTabMap[iTab].nIndex;
//
// Note, if no policy is configured, the RegOpenKey call below will fail,
// in that case we return the default tab value, as entered in the
// map above.
//
if ((ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, REGSTR_PATH_POLICIES L"\\" REGSTR_KEY_SYSTEM, 0, KEY_QUERY_VALUE, &hKey))) { //
// check all tabs to see if there is restriction
//
if (DeskCPL_CheckRestriction(hKey, aTabMap[iTab].pszRestriction)) { // this tab does not exist, mark it as such
iTabActual = CPL::CPLTAB_ABSENT; }
RegCloseKey(hKey); }
if (pszCanonicalName && (iTab >= 0) && (iTab < ARRAYSIZE(aTabMap))) { StringCchCopyW(pszCanonicalName, cchSize, aTabMap[iTab].pszCanoncialTabName); } } return iTabActual; }
bool CPL::DeskCPL_IsTabPresent( eDESKCPLTAB iTab ) { return CPLTAB_ABSENT != DeskCPL_GetTabIndex(iTab, NULL, 0); }
//////////////////////////////////////////////////////////////
//
// Policy checking routines
//
//////////////////////////////////////////////////////////////
#define REGSTR_POLICIES_RESTRICTCPL REGSTR_PATH_POLICIES TEXT("\\Explorer\\RestrictCpl")
#define REGSTR_POLICIES_DISALLOWCPL REGSTR_PATH_POLICIES TEXT("\\Explorer\\DisallowCpl")
//
// Returns true if the specified app is listed under the specified key
//
// pszFileName can be a string resource ID in shell32 for things
// like "Fonts", "Printers and Faxes" etc.
//
// i.e. IsNameListedUnderKey(MAKEINTRESOURCE(IDS_MY_APPLET_TITLE), hkey);
//
// In this case, if the resource string cannot be loaded, the function
// returns 'false'.
//
bool IsNameListedUnderKey( LPCWSTR pszFileName, LPCWSTR pszKey ) { bool bResult = FALSE; HKEY hkey; TCHAR szName[MAX_PATH];
if (IS_INTRESOURCE(pszFileName)) { //
// The name is localized so we specify it as a string resource ID.
// Load it from shell32.dll.
//
if (0 < LoadString(HINST_THISDLL, PtrToUint(pszFileName), szName, ARRAYSIZE(szName))) { pszFileName = szName; } else { //
// If the load fails spit out a debug squirty and return false.
//
TW32(GetLastError()); return false; } } if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, pszKey, 0, KEY_QUERY_VALUE, &hkey)) { int iValue = 0; WCHAR szValue[MAX_PATH]; WCHAR szData[MAX_PATH]; DWORD dwType, cbData, cchValue;
while (cbData = sizeof(szData), cchValue = ARRAYSIZE(szValue), ERROR_SUCCESS == RegEnumValue(hkey, iValue, szValue, &cchValue, NULL, &dwType, (LPBYTE) szData, &cbData)) { if (0 == lstrcmpiW(szData, pszFileName)) { bResult = true; break; } iValue++; } RegCloseKey(hkey); } return bResult; }
//
// Method cloned from shell32\ctrlfldr.cpp (DoesCplPolicyAllow)
//
// pszName can be a string resource ID in shell32 for things
// like "Fonts", "Printers and Faxes" etc.
//
// i.e. IsAppletEnabled(NULL, MAKEINTRESOURCE(IDS_MY_APPLET_TITLE));
//
bool CPL::IsAppletEnabled( LPCWSTR pszFileName, LPCWSTR pszName ) { bool bEnabled = true; //
// It's illegal (and meaningless) for both to be NULL.
// Trap both with an assert and runtime check. I don't want any
// code to erroneously think an applet is enabled when it's not.
//
ASSERT(NULL != pszName || NULL != pszFileName); if (NULL == pszName && NULL == pszFileName) { bEnabled = false; } else { if (SHRestricted(REST_RESTRICTCPL) && ((NULL == pszName || !IsNameListedUnderKey(pszName, REGSTR_POLICIES_RESTRICTCPL)) && (NULL == pszFileName || !IsNameListedUnderKey(pszFileName, REGSTR_POLICIES_RESTRICTCPL)))) { bEnabled = false; } if (bEnabled) { if (SHRestricted(REST_DISALLOWCPL) && ((NULL == pszName || IsNameListedUnderKey(pszName, REGSTR_POLICIES_DISALLOWCPL)) || (NULL == pszFileName || IsNameListedUnderKey(pszFileName, REGSTR_POLICIES_DISALLOWCPL)))) { bEnabled = false; } } } return bEnabled; }
HRESULT CPL::ControlPanelViewFromSite( IUnknown *punkSite, ICplView **ppview ) { ASSERT(NULL != punkSite); ASSERT(NULL != ppview); ASSERT(!IsBadWritePtr(ppview, sizeof(*ppview)));
*ppview = NULL;
HRESULT hr = IUnknown_QueryService(punkSite, SID_SControlPanelView, IID_ICplView, (void **)ppview); return THR(hr); }
HRESULT CPL::ShellBrowserFromSite( IUnknown *punkSite, IShellBrowser **ppsb ) { ASSERT(NULL != punkSite); ASSERT(NULL != ppsb); ASSERT(!IsBadWritePtr(ppsb, sizeof(*ppsb)));
*ppsb = NULL;
HRESULT hr = IUnknown_QueryService(punkSite, SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, ppsb)); return THR(hr); }
HRESULT CPL::BrowseIDListInPlace( LPCITEMIDLIST pidl, IShellBrowser *psb ) { ASSERT(NULL != pidl); ASSERT(NULL != psb); const UINT uFlags = SBSP_SAMEBROWSER | SBSP_OPENMODE | SBSP_ABSOLUTE; HRESULT hr = psb->BrowseObject(pidl, uFlags); return THR(hr); }
//
// System Restore is allowed only for admins/owners.
// Also must check policy.
//
bool CPL::IsSystemRestoreRestricted( void ) { bool bRestricted = false;
//
// First check policy.
//
DWORD dwType; DWORD dwValue; DWORD cbValue = sizeof(dwValue);
DWORD dwResult = SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Policies\\Microsoft\\Windows NT\\SystemRestore", L"DisableSR", &dwType, &dwValue, &cbValue);
if (ERROR_SUCCESS == dwResult && REG_DWORD == dwType) { if (1 == dwValue) { //
// Sytem Restore is disabled by policy.
//
bRestricted = true; } }
if (!bRestricted) { //
// Not restricted by policy. Check for admin/owner.
//
if (!CPL::IsUserAdmin()) { //
// User is not an admin.
//
bRestricted = true; } } return bRestricted; }
#ifdef DEBUG
HRESULT ReadTestConfigurationFlag( LPCWSTR pszValue, BOOL *pbFlag ) { HRESULT hr = S_OK; DWORD dwValue = 0; DWORD cbValue = sizeof(dwValue); DWORD dwType;
DWORD dwResult = SHGetValueW(HKEY_CURRENT_USER, REGSTR_PATH_CONTROLPANEL, pszValue, &dwType, &dwValue, &cbValue);
if (ERROR_SUCCESS != dwResult) { hr = HRESULT_FROM_WIN32(dwResult); } else if (REG_DWORD != dwType) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } if (SUCCEEDED(hr) && NULL != pbFlag) { if (0 == dwValue) { *pbFlag = FALSE; } else { *pbFlag = TRUE; } } return hr; }
enum eSKU { eSKU_SERVER, eSKU_PROFESSIONAL, eSKU_PERSONAL, eSKU_NUMSKUS };
HRESULT ReadTestConfigurationSku( eSKU *peSku ) { HRESULT hr = S_OK; WCHAR szValue[MAX_PATH]; DWORD cbValue = sizeof(szValue); DWORD dwType;
DWORD dwResult = SHGetValueW(HKEY_CURRENT_USER, REGSTR_PATH_CONTROLPANEL, L"SKU", &dwType, szValue, &cbValue);
if (ERROR_SUCCESS != dwResult) { hr = HRESULT_FROM_WIN32(dwResult); } else if (REG_SZ != dwType) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } if (SUCCEEDED(hr) && NULL != peSku) { static const struct { LPCWSTR pszValue; eSKU sku;
} rgMap[] = { { L"personal", eSKU_PERSONAL }, { L"professional", eSKU_PROFESSIONAL }, { L"pro", eSKU_PROFESSIONAL }, { L"server", eSKU_SERVER } };
hr = E_FAIL; for (int i = 0; i < ARRAYSIZE(rgMap); i++) { if (0 == lstrcmpiW(rgMap[i].pszValue, szValue)) { *peSku = rgMap[i].sku; hr = S_OK; break; } } } return hr; }
#endif
BOOL CPL::IsOsServer( void ) { BOOL bServer = IsOS(OS_ANYSERVER);
#ifdef DEBUG
eSKU sku; if (SUCCEEDED(ReadTestConfigurationSku(&sku))) { bServer = (eSKU_SERVER == sku); } #endif
return bServer; }
BOOL CPL::IsOsPersonal( void ) { BOOL bPersonal = IsOS(OS_PERSONAL);
#ifdef DEBUG
eSKU sku; if (SUCCEEDED(ReadTestConfigurationSku(&sku))) { bPersonal = (eSKU_PERSONAL == sku); } #endif
return bPersonal; }
BOOL CPL::IsOsProfessional( void ) { BOOL bProfessional = IsOS(OS_PROFESSIONAL);
#ifdef DEBUG
eSKU sku; if (SUCCEEDED(ReadTestConfigurationSku(&sku))) { bProfessional = (eSKU_PROFESSIONAL == sku); } #endif
return bProfessional; }
BOOL CPL::IsConnectedToDomain( void ) { BOOL bDomain = IsOS(OS_DOMAINMEMBER);
#ifdef DEBUG
ReadTestConfigurationFlag(L"Domain", &bDomain); #endif
return bDomain; }
BOOL CPL::IsUserAdmin( void ) { BOOL bAdmin = ::IsUserAnAdmin();
#ifdef DEBUG
ReadTestConfigurationFlag(L"Admin", &bAdmin); #endif
return bAdmin; }
HRESULT CPL::GetUserAccountType( eACCOUNTTYPE *pType ) { ASSERT(NULL != pType); ASSERT(!IsBadWritePtr(pType, sizeof(*pType)));
HRESULT hr = E_FAIL; eACCOUNTTYPE acctype = eACCOUNTTYPE_UNKNOWN;
static const struct { DWORD rid; // Account relative ID.
eACCOUNTTYPE eType; // Type code to return.
} rgMap[] = { { DOMAIN_ALIAS_RID_ADMINS, eACCOUNTTYPE_OWNER }, { DOMAIN_ALIAS_RID_POWER_USERS, eACCOUNTTYPE_STANDARD }, { DOMAIN_ALIAS_RID_USERS, eACCOUNTTYPE_LIMITED }, { DOMAIN_ALIAS_RID_GUESTS, eACCOUNTTYPE_GUEST } };
for (int i = 0; i < ARRAYSIZE(rgMap); i++) { if (SHTestTokenMembership(NULL, rgMap[i].rid)) { acctype = rgMap[i].eType; hr = S_OK; break; } } ASSERT(eACCOUNTTYPE_UNKNOWN != acctype); *pType = acctype; return THR(hr); }
//
// Create a URL to pass to HSS help.
// The URL created references the Control_Panel help topic.
//
HRESULT CPL::BuildHssHelpURL( LPCWSTR pszSelect, // Optional. NULL == base CP help.
LPWSTR pszURL, UINT cchURL ) { ASSERT(NULL != pszURL); ASSERT(!IsBadWritePtr(pszURL, cchURL * sizeof(*pszURL))); ASSERT(NULL == pszSelect || !IsBadStringPtr(pszSelect, UINT(-1)));
//
// HSS has specific help content for 'limited' users.
// Default to a non-limited user.
//
bool bLimitedUser = false; CPL::eACCOUNTTYPE accType; if (SUCCEEDED(CPL::GetUserAccountType(&accType))) { bLimitedUser = (eACCOUNTTYPE_LIMITED == accType); } HRESULT hr = S_OK; WCHAR szSelect[160]; szSelect[0] = L'\0'; if (NULL != pszSelect) { hr = StringCchPrintfW(szSelect, ARRAYSIZE(szSelect), L"&select=Unmapped/Control_Panel/%s", pszSelect); } if (SUCCEEDED(hr)) { //
// The URL can take one of 4 forms depending upon the category and account type.
//
// User Account CP View Help Content Displayed
// ---------------- ---------------- -----------------------
// Non-limited Category choice General CP help
// Non-limited Category Category-specific help
// Limited Category choice General CP help
// Limited Category Category-specific help
//
hr = StringCchPrintfW(pszURL, cchURL, L"hcp://services/subsite?node=Unmapped/%sControl_Panel&topic=MS-ITS%%3A%%25HELP_LOCATION%%25%%5Chs.chm%%3A%%3A/hs_control_panel.htm%s", bLimitedUser ? L"L/" : L"", szSelect); }
return hr; }
HRESULT CPL::GetControlPanelFolder( IShellFolder **ppsf ) { ASSERT(NULL != ppsf); ASSERT(!IsBadWritePtr(ppsf, sizeof(*ppsf)));
*ppsf = NULL; LPITEMIDLIST pidlCpanel; HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlCpanel); if (SUCCEEDED(hr)) { IShellFolder *psfDesktop; hr = SHGetDesktopFolder(&psfDesktop); if (SUCCEEDED(hr)) { hr = psfDesktop->BindToObject(pidlCpanel, NULL, IID_IShellFolder, (void **)ppsf); ATOMICRELEASE(psfDesktop); } ILFree(pidlCpanel); } return THR(hr); }
//
// On successful return, caller is responsible for freeing
// returned buffer using LocalFree.
//
HRESULT CPL::ExpandEnvironmentVars( LPCTSTR psz, LPTSTR *ppszOut ) { ASSERT(NULL != psz); ASSERT(NULL != ppszOut); ASSERT(!IsBadWritePtr(ppszOut, sizeof(*ppszOut)));
HRESULT hr = E_FAIL; *ppszOut = NULL;
TCHAR szDummy[1]; DWORD dwResult = ExpandEnvironmentStrings(psz, szDummy, 0); if (0 < dwResult) { const DWORD cchRequired = dwResult; *ppszOut = (LPTSTR)LocalAlloc(LPTR, cchRequired * sizeof(TCHAR)); if (NULL != *ppszOut) { dwResult = ExpandEnvironmentStrings(psz, *ppszOut, cchRequired); if (0 < dwResult) { ASSERT(dwResult <= cchRequired); hr = S_OK; } else { LocalFree(*ppszOut); *ppszOut = NULL; } } else { hr = E_OUTOFMEMORY; } } if (0 == dwResult) { hr = ResultFromLastError(); } return THR(hr); }
//// from sdfolder.cpp
VARIANT_BOOL GetBarricadeStatus(LPCTSTR pszValueName);
#define REGSTR_POLICIES_EXPLORER TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer")
bool CPL::CategoryViewIsActive( bool *pbBarricadeFixedByPolicy ) { DBG_ENTER(FTF_CPANEL, "CPL::CategoryViewIsActive"); bool bActive = false; bool bBarricadeFixedByPolicy = false;
//
// We don't provide category view when running WOW64.
//
if (!IsOS(OS_WOW6432)) { SHELLSTATE ss; const DWORD dwMask = SSF_WEBVIEW | SSF_WIN95CLASSIC; SHGetSetSettings(&ss, dwMask, FALSE);
//
// WebView? Barricade status View type
// ----------- ---------------- ------------------------------
// Off On Classic view
// Off Off Classic view
// On On Category view (aka 'simple')
// On Off Classic view
//
// Note that these two shellstate settings encompass and are set
// by the shell restrictions REST_CLASSICSHELL and REST_NOWEBVIEW.
// Therefore, there is no reason to explicitely check those two restrictions.
//
if (ss.fWebView && !ss.fWin95Classic) { if (VARIANT_TRUE == CPL::GetBarricadeStatus(&bBarricadeFixedByPolicy)) { bActive = true; } } } if (NULL != pbBarricadeFixedByPolicy) { *pbBarricadeFixedByPolicy = bBarricadeFixedByPolicy; } TraceMsg(TF_CPANEL, "Category view is %s.", bActive ? TEXT("ACTIVE") : TEXT("INACTIVE")); DBG_EXIT(FTF_CPANEL, "CPL::CategoryViewIsActive"); return bActive; }
//
// Control Panel uses the 'barricade status' to determine which view
// 'classic' or 'category' to display. Yes, this is overloading the
// meaning of 'barricade' as used in the shell. However, since the
// Control Panel does not use a barricade in it's usual sense, this
// is a reasonable application of the feature.
//
VARIANT_BOOL CPL::GetBarricadeStatus( bool *pbFixedByPolicy // Optional. May be NULL.
) { DBG_ENTER(FTF_CPANEL, "CPL::GetBarricadeStatus");
VARIANT_BOOL vtb; DWORD dwType; DWORD dwData; DWORD cbData = sizeof(dwData); bool bFixedByPolicy = false; bool bSetBarricade = false; //
// First handle any OOBE issues.
//
if (CPL::IsFirstRunForThisUser()) { TraceMsg(TF_CPANEL, "First time this user has opened Control Panel"); //
// Determine the default view to display out-of-box.
//
// Server gets 'classic'.
// Non-servers get 'category'.
//
if (IsOS(OS_ANYSERVER)) { //
// Default is 'classic'.
//
vtb = VARIANT_FALSE; TraceMsg(TF_CPANEL, "Running on server. Default to 'classic' view Control Panel."); } else { //
// Default is 'category'.
//
vtb = VARIANT_TRUE; TraceMsg(TF_CPANEL, "Running on non-server. Default to 'category' view Control Panel."); } bSetBarricade = true; }
//
// Apply any 'force view type' policy. This will override
// the default out-of-box setting obtained above.
//
if (ERROR_SUCCESS == SHRegGetUSValue(REGSTR_POLICIES_EXPLORER, TEXT("ForceClassicControlPanel"), &dwType, &dwData, &cbData, FALSE, NULL, 0)) { //
// policy exists
//
bFixedByPolicy = true; if (0 == dwData) { //
// force the simple (category) view, ie, show barricade
//
vtb = VARIANT_TRUE; TraceMsg(TF_CPANEL, "Policy forcing use of 'category' view Control Panel."); } else { //
// force the classic (icon) view, ie, no barricade
//
vtb = VARIANT_FALSE; TraceMsg(TF_CPANEL, "Policy forcing use of 'classic' view Control Panel."); } bSetBarricade = true; }
if (bSetBarricade) { THR(CPL::SetControlPanelBarricadeStatus(vtb)); }
vtb = ::GetBarricadeStatus(TEXT("shell:ControlPanelFolder")); if (NULL != pbFixedByPolicy) { *pbFixedByPolicy = bFixedByPolicy; }
TraceMsg(TF_CPANEL, "Barricade is %s", VARIANT_TRUE == vtb ? TEXT("ON") : TEXT("OFF")); DBG_EXIT(FTF_CPANEL, "CPL::GetBarricadeStatus"); return vtb; }
//
// Checks for the existance of the "HKCU\Control Panel\Opened" reg value.
// If this value does not exist or it contains a number less than what
// is expected, we assume the control panel has not been opened by this
// user. The 'expected' value is then written at this location in the
// registry to indicate to subsequent calls that the user has indeed
// already opened Control Panel. If future versions of the OS need
// to again trigger this "first run" behavior following upgrades,
// simply increment this expected value in the code below.
//
bool CPL::IsFirstRunForThisUser( void ) { bool bFirstRun = true; // Assume first run.
HKEY hkey; DWORD dwResult = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_CONTROLPANEL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkey);
if (ERROR_SUCCESS == dwResult) { DWORD dwType; DWORD dwData; DWORD cbData = sizeof(dwData);
const TCHAR szValueName[] = TEXT("Opened"); //
// Increment this value if you want to re-trigger
// this 'first run' state on future versions.
//
const DWORD dwTestValue = 1;
dwResult = RegQueryValueEx(hkey, szValueName, NULL, &dwType, (LPBYTE)&dwData, &cbData);
if (ERROR_SUCCESS == dwResult) { if (REG_DWORD == dwType && dwData >= dwTestValue) { bFirstRun = false; } } else if (ERROR_FILE_NOT_FOUND != dwResult) { TraceMsg(TF_ERROR, "Error %d reading Control Panel 'first run' value from registry", dwResult); }
if (bFirstRun) { //
// Write our value so we know user has opened
// Control Panel.
//
dwResult = RegSetValueEx(hkey, szValueName, 0, REG_DWORD, (CONST BYTE *)&dwTestValue, sizeof(dwTestValue));
if (ERROR_SUCCESS != dwResult) { TraceMsg(TF_ERROR, "Error %d writing Control Panel 'first run' value to registry", dwResult); } }
RegCloseKey(hkey); } else { TraceMsg(TF_ERROR, "Error %d opening 'HKCU\\Control Panel' reg key", dwResult); } return bFirstRun; }
//
// Use a private version of SetBarricadeStatus so that we don't
// clear the global barricade status whenever we turn on 'category' view
// (i.e. enable our barricade).
//
#define REGSTR_WEBVIEW_BARRICADEDFOLDERS (REGSTR_PATH_EXPLORER TEXT("\\WebView\\BarricadedFolders"))
HRESULT CPL::SetControlPanelBarricadeStatus( VARIANT_BOOL vtb ) { HRESULT hr = E_FAIL; DWORD dwBarricade = (VARIANT_FALSE == vtb) ? 0 : 1; if (SHRegSetUSValue(REGSTR_WEBVIEW_BARRICADEDFOLDERS, TEXT("shell:ControlPanelFolder"), REG_DWORD, (void *)&dwBarricade, sizeof(dwBarricade), SHREGSET_FORCE_HKCU) == ERROR_SUCCESS) { hr = S_OK; } return THR(hr); }
|