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

153 lines
5.2 KiB
C++

#include "stock.h"
#pragma hdrstop
//
// Return root hkey and default client name. The caller is expected to
// retrieve the command from hkey\default\shell\open\command.
//
STDAPI_(HKEY) _GetClientKeyAndDefaultW(LPCWSTR pwszClientType, LPWSTR pwszDefault, DWORD cchDefault)
{
HKEY hkClient = NULL;
ASSERT(cchDefault); // This had better be a nonempty buffer
// Borrow pwszDefault as a scratch buffer
wnsprintfW(pwszDefault, cchDefault, L"SOFTWARE\\Clients\\%s", pwszClientType);
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszDefault, 0, KEY_READ, &hkClient))
{
DWORD dwSize = cchDefault * sizeof(*pwszDefault);
pwszDefault[0] = 0; // in case of failure
RegQueryValueExW(hkClient, NULL, NULL, NULL, (LPBYTE)pwszDefault, &dwSize);
// If no default client, then fail
if (!pwszDefault[0])
{
RegCloseKey(hkClient);
hkClient = NULL;
}
} else if (StrCmpIW(pwszClientType, L"webbrowser") == 0)
{
// In theory, we could use
// RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkClient)
// but that just returns HKEY_CLASSES_ROOT back anyway.
hkClient = HKEY_CLASSES_ROOT;
StrCpyNW(pwszDefault, L"http", cchDefault);
}
return hkClient;
}
// Gets the path to open the default Mail, News, etc Client.
STDAPI SHGetDefaultClientOpenCommandW(LPCWSTR pwszClientType,
LPWSTR pwszClientCommand, DWORD dwCch,
OPTIONAL LPWSTR pwszClientParams, DWORD dwCchParams)
{
HRESULT hr = E_INVALIDARG;
HKEY hkClient;
WCHAR wszDefault[MAX_PATH];
ASSERT(pwszClientCommand && dwCch);
ASSERT(pwszClientParams == NULL || dwCchParams);
hkClient = _GetClientKeyAndDefaultW(pwszClientType, wszDefault, ARRAYSIZE(wszDefault));
if (hkClient)
{
// For the webbrowser client, do not pass any command line arguments
// at all. This suppresses the "-nohome" flag that IE likes to throw
// in there. Also, if we end up being forced to use the Protocol key,
// then strip the args there, too.
BOOL fStripArgs = hkClient == HKEY_CLASSES_ROOT;
BOOL iRetry = 0;
int cchDefault = lstrlenW(wszDefault);
again:
StrCatBuffW(wszDefault, L"\\shell\\open\\command", ARRAYSIZE(wszDefault));
// convert characters to bytes
DWORD cb = dwCch * (sizeof(WCHAR)/sizeof(BYTE));
// the default value of this key is the actual command to run the app
DWORD dwError;
dwError = SHGetValueW(hkClient, wszDefault, NULL, NULL, (LPBYTE) pwszClientCommand, &cb);
if (dwError == ERROR_FILE_NOT_FOUND && iRetry == 0 &&
StrCmpICW(pwszClientType, L"mail") == 0)
{
// Sigh, Netscape doesn't register a shell\open\command; we have to
// look in Protocols\mailto\shell\open\command instead.
wszDefault[cchDefault] = L'\0';
StrCatBuffW(wszDefault, L"\\Protocols\\mailto", ARRAYSIZE(wszDefault));
fStripArgs = TRUE;
iRetry++;
goto again;
}
if (dwError == ERROR_SUCCESS)
{
// Sigh. Netscape forgets to quote its EXE name.
PathProcessCommand(pwszClientCommand, pwszClientCommand, dwCch,
PPCF_ADDQUOTES | PPCF_NODIRECTORIES | PPCF_LONGESTPOSSIBLE);
if (pwszClientParams)
{
if (fStripArgs)
{
pwszClientParams[0] = 0;
}
else
{
StrCpyNW(pwszClientParams, PathGetArgsW(pwszClientCommand), dwCchParams);
}
}
PathRemoveArgsW(pwszClientCommand);
PathUnquoteSpaces(pwszClientCommand);
// Bonus hack for Netscape! To read email you have to pass the
// "-mail" command line option even though there is no indication
// anywhere that this is the case.
if (iRetry > 0 && pwszClientParams &&
StrCmpIW(PathFindFileName(pwszClientCommand), L"netscape.exe") == 0)
{
StrCpyNW(pwszClientParams, L"-mail", dwCchParams);
}
hr = S_OK;
}
else
{
hr = HRESULT_FROM_WIN32(dwError);
}
// Do not RegCloseKey(HKEY_CLASSES_ROOT) or the world will end!
if (hkClient != HKEY_CLASSES_ROOT)
RegCloseKey(hkClient);
}
return hr;
}
// Gets the friendly name for the default Mail, News, etc Client.
// Note that this doesn't work for Webbrowser.
STDAPI SHGetDefaultClientNameW(LPCWSTR pwszClientType,
LPWSTR pwszBuf, DWORD dwCch)
{
HRESULT hr = E_INVALIDARG;
HKEY hkClient;
WCHAR wszDefault[MAX_PATH];
ASSERT(pwszBuf && dwCch);
hkClient = _GetClientKeyAndDefaultW(pwszClientType, wszDefault, ARRAYSIZE(wszDefault));
if (hkClient && hkClient != HKEY_CLASSES_ROOT)
{
LONG cbValue = dwCch * sizeof(TCHAR);
if (RegQueryValueW(hkClient, wszDefault, pwszBuf, &cbValue) == ERROR_SUCCESS &&
pwszBuf[0])
{
hr = S_OK;
}
RegCloseKey(hkClient);
}
return hr;
}