153 lines
5.2 KiB
C++
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;
|
|
}
|