236 lines
6.1 KiB
C++
236 lines
6.1 KiB
C++
//
|
|
// native.cpp in shell\lib
|
|
//
|
|
// common Utility functions that need to be compiled for
|
|
// both UNICODE and ANSI
|
|
//
|
|
#include "stock.h"
|
|
#pragma hdrstop
|
|
|
|
#include "shellp.h"
|
|
#include <regstr.h>
|
|
|
|
// get the name and flags of an absolute IDlist
|
|
// in:
|
|
// dwFlags SHGDN_ flags as hints to the name space GetDisplayNameOf() function
|
|
//
|
|
// in/out:
|
|
// *pdwAttribs (optional) return flags
|
|
|
|
STDAPI SHGetNameAndFlags(LPCITEMIDLIST pidl, DWORD dwFlags, LPTSTR pszName, UINT cchName, DWORD *pdwAttribs)
|
|
{
|
|
if (pszName)
|
|
{
|
|
*pszName = 0;
|
|
}
|
|
|
|
HRESULT hrInit = SHCoInitialize();
|
|
|
|
IShellFolder *psf;
|
|
LPCITEMIDLIST pidlLast;
|
|
HRESULT hr = SHBindToIDListParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pszName)
|
|
hr = DisplayNameOf(psf, pidlLast, dwFlags, pszName, cchName);
|
|
|
|
if (SUCCEEDED(hr) && pdwAttribs)
|
|
{
|
|
RIP(*pdwAttribs); // this is an in-out param
|
|
*pdwAttribs = SHGetAttributes(psf, pidlLast, *pdwAttribs);
|
|
}
|
|
|
|
psf->Release();
|
|
}
|
|
|
|
SHCoUninitialize(hrInit);
|
|
return hr;
|
|
}
|
|
|
|
STDAPI_(DWORD) GetUrlScheme(LPCTSTR pszUrl)
|
|
{
|
|
if (pszUrl)
|
|
{
|
|
PARSEDURL pu;
|
|
pu.cbSize = sizeof(pu);
|
|
if (SUCCEEDED(ParseURL(pszUrl, &pu)))
|
|
return pu.nScheme;
|
|
}
|
|
return URL_SCHEME_INVALID;
|
|
}
|
|
|
|
//
|
|
// returns
|
|
//
|
|
// TRUE if the key is present and nonzero.
|
|
// FALSE if the key is present and zero.
|
|
// -1 if the key is not present.
|
|
//
|
|
|
|
BOOL GetExplorerUserSetting(HKEY hkeyRoot, LPCTSTR pszSubKey, LPCTSTR pszValue)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szPathExplorer[MAX_PATH];
|
|
DWORD cbSize = ARRAYSIZE(szPath);
|
|
DWORD dwType;
|
|
|
|
PathCombine(szPathExplorer, REGSTR_PATH_EXPLORER, pszSubKey);
|
|
if (ERROR_SUCCESS == SHGetValue(hkeyRoot, szPathExplorer, pszValue,
|
|
&dwType, szPath, &cbSize))
|
|
{
|
|
// Zero in the DWORD case or NULL in the string case
|
|
// indicates that this item is not available.
|
|
if (dwType == REG_DWORD)
|
|
return *((DWORD*)szPath) != 0;
|
|
else
|
|
return (TCHAR)szPath[0] != 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// This function allows a feature to be controlled by both a user setting
|
|
// or a policy restriction. The policy restriction is first checked.
|
|
//
|
|
// If the value is 1, then the action is restricted.
|
|
// If the value is 2, then the action is allowed.
|
|
// If the value is absent or 0, then we look at the user setting.
|
|
//
|
|
// If the user setting is present, then ROUS_KEYALLOWS and ROUS_KEYRESTRICTS
|
|
// controls the return value. ROUS_KEYALLOWS means that a nonzero user
|
|
// setting allows the action. ROUS_KEYRESTRICTS means that a nonzero user
|
|
// setting restricts the action.
|
|
//
|
|
// If the user setting is absent, then ROUS_DEFAULTALLOW and
|
|
// ROUS_DESFAULTRESTRICT controls the default return value.
|
|
//
|
|
STDAPI_(BOOL) IsRestrictedOrUserSetting(HKEY hkeyRoot, RESTRICTIONS rest, LPCTSTR pszSubKey, LPCTSTR pszValue, UINT flags)
|
|
{
|
|
// See if the system policy restriction trumps
|
|
|
|
DWORD dwRest = SHRestricted(rest);
|
|
|
|
if (dwRest == 1)
|
|
return TRUE;
|
|
|
|
if (dwRest == 2)
|
|
return FALSE;
|
|
|
|
//
|
|
// Restriction not in place or defers to user setting.
|
|
//
|
|
BOOL fValidKey = GetExplorerUserSetting(hkeyRoot, pszSubKey, pszValue);
|
|
|
|
switch (fValidKey)
|
|
{
|
|
case 0: // Key is present and zero
|
|
if (flags & ROUS_KEYRESTRICTS)
|
|
return FALSE; // restriction not present
|
|
else
|
|
return TRUE; // ROUS_KEYALLOWS, value is 0 -> restricted
|
|
|
|
case 1: // Key is present and nonzero
|
|
|
|
if (flags & ROUS_KEYRESTRICTS)
|
|
return TRUE; // restriction present -> restricted
|
|
else
|
|
return FALSE; // ROUS_KEYALLOWS, value is 1 -> not restricted
|
|
|
|
default:
|
|
ASSERT(0); // _GetExplorerUserSetting returns exactly 0, 1 or -1.
|
|
// Fall through
|
|
|
|
case -1: // Key is not present
|
|
return (flags & ROUS_DEFAULTRESTRICT);
|
|
}
|
|
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
//
|
|
// Repair font attributes that don't work on certain languages.
|
|
//
|
|
STDAPI_(void) SHAdjustLOGFONT(IN OUT LOGFONT *plf)
|
|
{
|
|
ASSERT(plf);
|
|
|
|
//
|
|
// FE fonts don't look good in bold since the glyphs are intricate
|
|
// and converting them to bold turns them into a black blob.
|
|
//
|
|
if (plf->lfCharSet == SHIFTJIS_CHARSET||
|
|
plf->lfCharSet == HANGEUL_CHARSET ||
|
|
plf->lfCharSet == GB2312_CHARSET ||
|
|
plf->lfCharSet == CHINESEBIG5_CHARSET)
|
|
{
|
|
if (plf->lfWeight > FW_NORMAL)
|
|
plf->lfWeight = FW_NORMAL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Some of our registry keys were used prior to MUI, so for compat
|
|
// reasons, apps have to put non-MUI strings there; otherwise,
|
|
// downlevel clients will display at-signs which is kinda ugly.
|
|
//
|
|
// So the solution for these keys is to store the non-MUI string
|
|
// in the legacy location, but put the MUI version in the
|
|
// "LocalizedString" value.
|
|
//
|
|
STDAPI SHLoadLegacyRegUIString(HKEY hk, LPCTSTR pszSubkey, LPTSTR pszOutBuf, UINT cchOutBuf)
|
|
{
|
|
HKEY hkClose = NULL;
|
|
|
|
ASSERT(cchOutBuf);
|
|
pszOutBuf[0] = TEXT('\0');
|
|
|
|
if (pszSubkey && *pszSubkey)
|
|
{
|
|
DWORD dwError = RegOpenKeyEx(hk, pszSubkey, 0, KEY_QUERY_VALUE, &hkClose);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
hk = hkClose;
|
|
}
|
|
|
|
HRESULT hr = SHLoadRegUIString(hk, TEXT("LocalizedString"), pszOutBuf, cchOutBuf);
|
|
if (FAILED(hr) || pszOutBuf[0] == TEXT('\0'))
|
|
{
|
|
hr = SHLoadRegUIString(hk, TEXT(""), pszOutBuf, cchOutBuf);
|
|
}
|
|
|
|
if (hkClose)
|
|
{
|
|
RegCloseKey(hkClose);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDAPI_(TCHAR) SHFindMnemonic(LPCTSTR psz)
|
|
{
|
|
ASSERT(psz);
|
|
TCHAR tchDefault = *psz; // Default is first character
|
|
LPCTSTR pszAmp;
|
|
|
|
while ((pszAmp = StrChr(psz, TEXT('&'))) != NULL)
|
|
{
|
|
switch (pszAmp[1])
|
|
{
|
|
case TEXT('&'): // Skip over &&
|
|
psz = pszAmp + 2;
|
|
continue;
|
|
|
|
case TEXT('\0'): // Ignore trailing ampersand
|
|
return tchDefault;
|
|
|
|
default:
|
|
return pszAmp[1];
|
|
}
|
|
}
|
|
return tchDefault;
|
|
}
|