804 lines
22 KiB
C++
804 lines
22 KiB
C++
|
/*
|
||
|
* url.cpp - IUniformResourceLocator implementation for InternetShortcut class.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/* Headers
|
||
|
**********/
|
||
|
|
||
|
#include "project.hpp"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "assoc.h"
|
||
|
#include "resource.h"
|
||
|
#define DECL_CRTFREE
|
||
|
#include <crtfree.h>
|
||
|
|
||
|
|
||
|
/* Module Constants
|
||
|
*******************/
|
||
|
|
||
|
#pragma data_seg(DATA_SEG_READ_ONLY)
|
||
|
|
||
|
PRIVATE_DATA const char s_cszURLSeparator[] = ":";
|
||
|
|
||
|
PRIVATE_DATA const char s_cchURLSuffixSlash = '/';
|
||
|
|
||
|
PRIVATE_DATA const char s_cszURLPrefixesKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes";
|
||
|
PRIVATE_DATA const char s_cszDefaultURLPrefixKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\DefaultPrefix";
|
||
|
|
||
|
#pragma data_seg()
|
||
|
|
||
|
|
||
|
/***************************** Private Functions *****************************/
|
||
|
|
||
|
|
||
|
PRIVATE_CODE PCSTR SkipLeadingSlashes(PCSTR pcszURL)
|
||
|
{
|
||
|
PCSTR pcszURLStart;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
|
||
|
|
||
|
// Skip two leading slashes.
|
||
|
|
||
|
if (pcszURL[0] == s_cchURLSuffixSlash &&
|
||
|
pcszURL[1] == s_cchURLSuffixSlash)
|
||
|
{
|
||
|
pcszURLStart = CharNext(pcszURL);
|
||
|
pcszURLStart = CharNext(pcszURLStart);
|
||
|
}
|
||
|
else
|
||
|
pcszURLStart = pcszURL;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR) &&
|
||
|
EVAL(IsStringContained(pcszURL, pcszURLStart)));
|
||
|
|
||
|
return(pcszURLStart);
|
||
|
}
|
||
|
|
||
|
|
||
|
PRIVATE_CODE HRESULT ApplyURLPrefix(PCSTR pcszURL, PSTR *ppszTranslatedURL)
|
||
|
{
|
||
|
HRESULT hr = S_FALSE;
|
||
|
HKEY hkeyPrefixes;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
|
||
|
|
||
|
*ppszTranslatedURL = NULL;
|
||
|
|
||
|
if (RegOpenKey(g_hkeyURLSettings, s_cszURLPrefixesKey, &hkeyPrefixes)
|
||
|
== ERROR_SUCCESS)
|
||
|
{
|
||
|
PCSTR pcszURLStart;
|
||
|
DWORD dwiValue;
|
||
|
char rgchValueName[MAX_PATH_LEN];
|
||
|
DWORD dwcbValueNameLen;
|
||
|
DWORD dwType;
|
||
|
char rgchPrefix[MAX_PATH_LEN];
|
||
|
DWORD dwcbPrefixLen;
|
||
|
|
||
|
pcszURLStart = SkipLeadingSlashes(pcszURL);
|
||
|
|
||
|
dwcbValueNameLen = sizeof(rgchValueName);
|
||
|
dwcbPrefixLen = sizeof(rgchPrefix);
|
||
|
|
||
|
for (dwiValue = 0;
|
||
|
RegEnumValue(hkeyPrefixes, dwiValue, rgchValueName,
|
||
|
&dwcbValueNameLen, NULL, &dwType, (PBYTE)rgchPrefix,
|
||
|
&dwcbPrefixLen) == ERROR_SUCCESS;
|
||
|
dwiValue++)
|
||
|
{
|
||
|
if (! lstrnicmp(pcszURLStart, rgchValueName, dwcbValueNameLen))
|
||
|
{
|
||
|
DWORD cbUrl = lstrlen(pcszURLStart);
|
||
|
|
||
|
// If the url==prefix, then we're calling the executable.
|
||
|
|
||
|
if (cbUrl >= dwcbPrefixLen)
|
||
|
{
|
||
|
// dwcbPrefixLen includes null terminator.
|
||
|
|
||
|
*ppszTranslatedURL = new(char[dwcbPrefixLen + cbUrl]);
|
||
|
|
||
|
if (*ppszTranslatedURL)
|
||
|
{
|
||
|
lstrcpy(*ppszTranslatedURL, rgchPrefix);
|
||
|
lstrcat(*ppszTranslatedURL, pcszURLStart);
|
||
|
// (+ 1) for null terminator.
|
||
|
ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbPrefixLen + lstrlen(pcszURLStart));
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwcbValueNameLen = sizeof(rgchValueName);
|
||
|
dwcbPrefixLen = sizeof(rgchPrefix);
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkeyPrefixes);
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case S_OK:
|
||
|
TRACE_OUT(("ApplyURLPrefix(): Prefix %s prepended to prefix %s of %s to yield URL %s.",
|
||
|
rgchValueName,
|
||
|
rgchPrefix,
|
||
|
pcszURL,
|
||
|
*ppszTranslatedURL));
|
||
|
break;
|
||
|
|
||
|
case S_FALSE:
|
||
|
TRACE_OUT(("ApplyURLPrefix(): No matching prefix found for URL %s.",
|
||
|
pcszURL));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(hr == E_OUTOFMEMORY);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
TRACE_OUT(("ApplyURLPrefix(): No URL prefixes registered."));
|
||
|
|
||
|
ASSERT((hr == S_OK &&
|
||
|
IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
|
||
|
((hr == S_FALSE ||
|
||
|
hr == E_OUTOFMEMORY) &&
|
||
|
! *ppszTranslatedURL));
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
PRIVATE_CODE HRESULT ApplyDefaultURLPrefix(PCSTR pcszURL,
|
||
|
PSTR *ppszTranslatedURL)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
char rgchDefaultURLPrefix[MAX_PATH_LEN];
|
||
|
DWORD dwcbDefaultURLPrefixLen;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
|
||
|
|
||
|
*ppszTranslatedURL = NULL;
|
||
|
|
||
|
dwcbDefaultURLPrefixLen = sizeof(rgchDefaultURLPrefix);
|
||
|
|
||
|
if (GetDefaultRegKeyValue(g_hkeyURLSettings, s_cszDefaultURLPrefixKey,
|
||
|
rgchDefaultURLPrefix, &dwcbDefaultURLPrefixLen)
|
||
|
== ERROR_SUCCESS)
|
||
|
{
|
||
|
// (+ 1) for null terminator.
|
||
|
|
||
|
*ppszTranslatedURL = new(char[dwcbDefaultURLPrefixLen +
|
||
|
lstrlen(pcszURL) + 1]);
|
||
|
|
||
|
if (*ppszTranslatedURL)
|
||
|
{
|
||
|
PCSTR pcszURLStart;
|
||
|
|
||
|
pcszURLStart = SkipLeadingSlashes(pcszURL);
|
||
|
|
||
|
lstrcpy(*ppszTranslatedURL, rgchDefaultURLPrefix);
|
||
|
lstrcat(*ppszTranslatedURL, pcszURLStart);
|
||
|
// (+ 1) for null terminator.
|
||
|
ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbDefaultURLPrefixLen + lstrlen(pcszURLStart));
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case S_OK:
|
||
|
TRACE_OUT(("ApplyDefaultURLPrefix(): Default prefix %s prepended to %s to yield URL %s.",
|
||
|
rgchDefaultURLPrefix,
|
||
|
pcszURL,
|
||
|
*ppszTranslatedURL));
|
||
|
break;
|
||
|
|
||
|
case S_FALSE:
|
||
|
TRACE_OUT(("ApplyDefaultURLPrefix(): No default URL prefix registered."));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(hr == E_OUTOFMEMORY);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ASSERT((hr == S_OK &&
|
||
|
IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
|
||
|
((hr == S_FALSE ||
|
||
|
hr == E_OUTOFMEMORY) &&
|
||
|
! *ppszTranslatedURL));
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
PRIVATE_CODE HRESULT MyTranslateURL(PCSTR pcszURL, DWORD dwFlags,
|
||
|
PSTR *ppszTranslatedURL)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
PARSEDURL pu;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
|
||
|
ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_TRANSLATEURL_FLAGS));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
|
||
|
|
||
|
// Check URL syntax.
|
||
|
|
||
|
pu.cbSize = sizeof(pu);
|
||
|
if (ParseURL(pcszURL, &pu) == S_OK)
|
||
|
{
|
||
|
*ppszTranslatedURL = NULL;
|
||
|
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_GUESS_PROTOCOL))
|
||
|
hr = ApplyURLPrefix(pcszURL, ppszTranslatedURL);
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
if (hr == S_FALSE &&
|
||
|
IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL))
|
||
|
hr = ApplyDefaultURLPrefix(pcszURL, ppszTranslatedURL);
|
||
|
}
|
||
|
|
||
|
ASSERT((hr == S_OK &&
|
||
|
IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
|
||
|
((hr == S_FALSE ||
|
||
|
hr == E_OUTOFMEMORY) &&
|
||
|
! *ppszTranslatedURL));
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
|
||
|
PRIVATE_CODE IsValidPCURLINVOKECOMMANDINFO(PCURLINVOKECOMMANDINFO pcurlici)
|
||
|
{
|
||
|
return(IS_VALID_READ_PTR(pcurlici, CURLINVOKECOMMANDINFO) &&
|
||
|
EVAL(pcurlici->dwcbSize >= sizeof(*pcurlici)) &&
|
||
|
FLAGS_ARE_VALID(pcurlici->dwFlags, ALL_IURL_INVOKECOMMAND_FLAGS) &&
|
||
|
(IS_FLAG_CLEAR(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI) ||
|
||
|
IS_VALID_HANDLE(pcurlici->hwndParent, WND)) &&
|
||
|
(IS_FLAG_SET(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB) ||
|
||
|
IS_VALID_STRING_PTR(pcurlici->pcszVerb, CSTR)));
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/********************************** Methods **********************************/
|
||
|
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE InternetShortcut::RegisterProtocolHandler(
|
||
|
HWND hwndParent,
|
||
|
PSTR pszAppBuf,
|
||
|
UINT ucAppBufLen)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DWORD dwFlags = 0;
|
||
|
|
||
|
DebugEntry(InternetShortcut::RegisterProtocolHandler);
|
||
|
|
||
|
ASSERT(! hwndParent ||
|
||
|
IS_VALID_HANDLE(hwndParent, WND));
|
||
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
|
||
|
|
||
|
SET_FLAG(dwFlags, URLASSOCDLG_FL_REGISTER_ASSOC);
|
||
|
|
||
|
if (! m_pszFile)
|
||
|
SET_FLAG(dwFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME);
|
||
|
|
||
|
hr = URLAssociationDialog(hwndParent, dwFlags, m_pszFile, m_pszURL,
|
||
|
pszAppBuf, ucAppBufLen);
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case S_FALSE:
|
||
|
TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): One time execution of %s via %s requested.",
|
||
|
m_pszURL,
|
||
|
pszAppBuf));
|
||
|
break;
|
||
|
|
||
|
case S_OK:
|
||
|
TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): Protocol handler registered for %s.",
|
||
|
m_pszURL));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(FAILED(hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ASSERT(! ucAppBufLen ||
|
||
|
(IS_VALID_STRING_PTR(pszAppBuf, STR) &&
|
||
|
(UINT)lstrlen(pszAppBuf) < ucAppBufLen));
|
||
|
|
||
|
DebugExitHRESULT(InternetShortcut::RegisterProtocolHandler, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE InternetShortcut::SetURL(PCSTR pcszURL,
|
||
|
DWORD dwInFlags)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
BOOL bChanged;
|
||
|
PSTR pszNewURL = NULL;
|
||
|
|
||
|
DebugEntry(InternetShortcut::SetURL);
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT(! pcszURL ||
|
||
|
IS_VALID_STRING_PTR(pcszURL, CSTR));
|
||
|
ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_IURL_SETURL_FLAGS));
|
||
|
|
||
|
bChanged = ! ((! pcszURL && ! m_pszURL) ||
|
||
|
(pcszURL && m_pszURL &&
|
||
|
! lstrcmp(pcszURL, m_pszURL)));
|
||
|
|
||
|
if (bChanged && pcszURL)
|
||
|
{
|
||
|
DWORD dwTranslateURLFlags;
|
||
|
PSTR pszTranslatedURL;
|
||
|
|
||
|
dwTranslateURLFlags = 0;
|
||
|
|
||
|
if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_GUESS_PROTOCOL))
|
||
|
SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_GUESS_PROTOCOL);
|
||
|
|
||
|
if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_USE_DEFAULT_PROTOCOL))
|
||
|
SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL);
|
||
|
|
||
|
hr = TranslateURL(pcszURL, dwTranslateURLFlags, &pszTranslatedURL);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
PCSTR pcszURLToUse;
|
||
|
|
||
|
// Still different?
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
bChanged = (lstrcmp(pszTranslatedURL, m_pszURL) != 0);
|
||
|
|
||
|
pcszURLToUse = pszTranslatedURL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(hr == S_FALSE);
|
||
|
|
||
|
pcszURLToUse = pcszURL;
|
||
|
}
|
||
|
|
||
|
if (bChanged)
|
||
|
{
|
||
|
PARSEDURL pu;
|
||
|
|
||
|
// Validate URL syntax.
|
||
|
|
||
|
pu.cbSize = sizeof(pu);
|
||
|
hr = ParseURL(pcszURLToUse, &pu);
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
pszNewURL = new(char[lstrlen(pcszURLToUse) + 1]);
|
||
|
|
||
|
if (pszNewURL)
|
||
|
lstrcpy(pszNewURL, pcszURLToUse);
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
if (pszTranslatedURL)
|
||
|
{
|
||
|
LocalFree(pszTranslatedURL);
|
||
|
pszTranslatedURL = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = S_OK;
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
if (bChanged)
|
||
|
{
|
||
|
if (m_pszURL)
|
||
|
delete m_pszURL;
|
||
|
|
||
|
m_pszURL = pszNewURL;
|
||
|
|
||
|
Dirty(TRUE);
|
||
|
|
||
|
TRACE_OUT(("InternetShortcut::SetURL(): Set URL to %s.",
|
||
|
CHECK_STRING(m_pszURL)));
|
||
|
}
|
||
|
else
|
||
|
TRACE_OUT(("InternetShortcut::SetURL(): URL already %s.",
|
||
|
CHECK_STRING(m_pszURL)));
|
||
|
}
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT(hr == S_OK ||
|
||
|
hr == E_OUTOFMEMORY ||
|
||
|
hr == URL_E_INVALID_SYNTAX);
|
||
|
|
||
|
DebugExitHRESULT(InternetShortcut::SetURL, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE InternetShortcut::GetURL(PSTR *ppszURL)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
DebugEntry(InternetShortcut::GetURL);
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT(IS_VALID_WRITE_PTR(ppszURL, PSTR));
|
||
|
|
||
|
*ppszURL = NULL;
|
||
|
|
||
|
if (m_pszURL)
|
||
|
{
|
||
|
// (+ 1) for null terminator.
|
||
|
*ppszURL = (PSTR)SHAlloc(lstrlen(m_pszURL) + 1);
|
||
|
|
||
|
if (*ppszURL)
|
||
|
{
|
||
|
lstrcpy(*ppszURL, m_pszURL);
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
TRACE_OUT(("InternetShortcut::GetURL(): Got URL %s.",
|
||
|
*ppszURL));
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
// No URL.
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT((hr == S_OK &&
|
||
|
IS_VALID_STRING_PTR(*ppszURL, STR)) ||
|
||
|
((hr == S_FALSE ||
|
||
|
hr == E_OUTOFMEMORY) &&
|
||
|
! *ppszURL));
|
||
|
|
||
|
DebugExitHRESULT(InternetShortcut::GetURL, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE InternetShortcut::InvokeCommand(
|
||
|
PURLINVOKECOMMANDINFO purlici)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
char szOneShotApp[MAX_PATH_LEN];
|
||
|
BOOL bExecFailedWhine = FALSE;
|
||
|
|
||
|
DebugEntry(InternetShortcut::InvokeCommand);
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(purlici, CURLINVOKECOMMANDINFO));
|
||
|
|
||
|
if (purlici && EVAL(sizeof(*purlici) == purlici->dwcbSize))
|
||
|
{
|
||
|
if (m_pszURL)
|
||
|
{
|
||
|
PSTR pszProtocol;
|
||
|
|
||
|
hr = CopyURLProtocol(m_pszURL, &pszProtocol);
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
hr = IsProtocolRegistered(pszProtocol);
|
||
|
|
||
|
if (hr == URL_E_UNREGISTERED_PROTOCOL &&
|
||
|
IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
|
||
|
{
|
||
|
TRACE_OUT(("InternetShortcut::InvokeCommand(): Unregistered URL protocol %s. Invoking URL protocol handler association dialog.",
|
||
|
pszProtocol));
|
||
|
|
||
|
hr = RegisterProtocolHandler(purlici->hwndParent, szOneShotApp,
|
||
|
sizeof(szOneShotApp));
|
||
|
}
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case S_OK:
|
||
|
{
|
||
|
SHELLEXECUTEINFO sei;
|
||
|
char szDefaultVerb[MAX_PATH_LEN];
|
||
|
|
||
|
// Execute URL via registered protocol handler.
|
||
|
|
||
|
ZeroMemory(&sei, sizeof(sei));
|
||
|
|
||
|
sei.fMask = (SEE_MASK_CLASSNAME | SEE_MASK_NO_HOOKS);
|
||
|
|
||
|
if (IS_FLAG_CLEAR(purlici->dwFlags,
|
||
|
IURL_INVOKECOMMAND_FL_ALLOW_UI))
|
||
|
SET_FLAG(sei.fMask, SEE_MASK_FLAG_NO_UI);
|
||
|
|
||
|
if (IS_FLAG_CLEAR(purlici->dwFlags,
|
||
|
IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB))
|
||
|
sei.lpVerb = purlici->pcszVerb;
|
||
|
else
|
||
|
{
|
||
|
if (GetClassDefaultVerb(pszProtocol, szDefaultVerb,
|
||
|
sizeof(szDefaultVerb)))
|
||
|
sei.lpVerb = szDefaultVerb;
|
||
|
else
|
||
|
ASSERT(! sei.lpVerb);
|
||
|
}
|
||
|
|
||
|
sei.cbSize = sizeof(sei);
|
||
|
sei.hwnd = purlici->hwndParent;
|
||
|
sei.lpFile = m_pszURL;
|
||
|
sei.lpDirectory = m_pszWorkingDirectory;
|
||
|
sei.nShow = m_nShowCmd;
|
||
|
sei.lpClass = pszProtocol;
|
||
|
|
||
|
TRACE_OUT(("InternetShortcut::InvokeCommand(): Invoking %s verb on URL %s.",
|
||
|
sei.lpVerb ? sei.lpVerb : "open",
|
||
|
sei.lpFile));
|
||
|
|
||
|
hr = ShellExecuteEx(&sei) ? S_OK : IS_E_EXEC_FAILED;
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
TRACE_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler succeeded for %s.",
|
||
|
m_pszURL));
|
||
|
else
|
||
|
WARNING_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler failed for %s.",
|
||
|
m_pszURL));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case S_FALSE:
|
||
|
hr = MyExecute(szOneShotApp, m_pszURL, 0);
|
||
|
switch (hr)
|
||
|
{
|
||
|
case E_FAIL:
|
||
|
bExecFailedWhine = TRUE;
|
||
|
hr = IS_E_EXEC_FAILED;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(FAILED(hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
delete pszProtocol;
|
||
|
pszProtocol = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
// No URL. Not an error.
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
if (FAILED(hr) &&
|
||
|
IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
|
||
|
{
|
||
|
int nResult;
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case IS_E_EXEC_FAILED:
|
||
|
if (bExecFailedWhine)
|
||
|
{
|
||
|
ASSERT(IS_VALID_STRING_PTR(szOneShotApp, STR));
|
||
|
|
||
|
if (MyMsgBox(purlici->hwndParent,
|
||
|
MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
|
||
|
MAKEINTRESOURCE(IDS_EXEC_FAILED),
|
||
|
(MB_OK | MB_ICONEXCLAMATION), &nResult,
|
||
|
szOneShotApp)) {
|
||
|
ASSERT(nResult == IDOK);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case URL_E_INVALID_SYNTAX:
|
||
|
ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
|
||
|
|
||
|
if (MyMsgBox(purlici->hwndParent,
|
||
|
MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
|
||
|
MAKEINTRESOURCE(IDS_EXEC_INVALID_SYNTAX),
|
||
|
(MB_OK | MB_ICONEXCLAMATION), &nResult, m_pszURL)) {
|
||
|
ASSERT(nResult == IDOK);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case URL_E_UNREGISTERED_PROTOCOL:
|
||
|
{
|
||
|
PSTR pszProtocol;
|
||
|
|
||
|
ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
|
||
|
|
||
|
if (CopyURLProtocol(m_pszURL, &pszProtocol) == S_OK)
|
||
|
{
|
||
|
if (MyMsgBox(purlici->hwndParent,
|
||
|
MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
|
||
|
MAKEINTRESOURCE(IDS_EXEC_UNREGISTERED_PROTOCOL),
|
||
|
(MB_OK | MB_ICONEXCLAMATION), &nResult,
|
||
|
pszProtocol)) {
|
||
|
ASSERT(nResult == IDOK);
|
||
|
}
|
||
|
|
||
|
delete pszProtocol;
|
||
|
pszProtocol = NULL;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case E_OUTOFMEMORY:
|
||
|
if (MyMsgBox(purlici->hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
|
||
|
MAKEINTRESOURCE(IDS_EXEC_OUT_OF_MEMORY),
|
||
|
(MB_OK | MB_ICONEXCLAMATION), &nResult)) {
|
||
|
ASSERT(nResult == IDOK);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(hr == E_ABORT);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
|
||
|
ASSERT(hr == S_OK ||
|
||
|
hr == E_ABORT ||
|
||
|
hr == E_OUTOFMEMORY ||
|
||
|
hr == E_INVALIDARG ||
|
||
|
hr == URL_E_INVALID_SYNTAX ||
|
||
|
hr == URL_E_UNREGISTERED_PROTOCOL ||
|
||
|
hr == IS_E_EXEC_FAILED);
|
||
|
|
||
|
DebugExitHRESULT(InternetShortcut::InvokeCommand, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************** Exported Functions ****************************/
|
||
|
|
||
|
|
||
|
INTSHCUTAPI HRESULT WINAPI TranslateURLA(PCSTR pcszURL, DWORD dwInFlags,
|
||
|
PSTR *ppszTranslatedURL)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
DebugEntry(TranslateURLA);
|
||
|
|
||
|
*ppszTranslatedURL = NULL;
|
||
|
|
||
|
#ifdef EXPV
|
||
|
/* Verify parameters. */
|
||
|
|
||
|
if (IS_VALID_STRING_PTR(pcszURL, CSTR) &&
|
||
|
IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR))
|
||
|
{
|
||
|
if (FLAGS_ARE_VALID(dwInFlags, ALL_TRANSLATEURL_FLAGS))
|
||
|
#endif
|
||
|
{
|
||
|
PSTR pszTempTranslatedURL;
|
||
|
|
||
|
hr = MyTranslateURL(pcszURL, dwInFlags, &pszTempTranslatedURL);
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
// (+ 1) for null terminator.
|
||
|
*ppszTranslatedURL = (PSTR)LocalAlloc(
|
||
|
LMEM_FIXED,
|
||
|
lstrlen(pszTempTranslatedURL) + 1);
|
||
|
|
||
|
if (*ppszTranslatedURL)
|
||
|
{
|
||
|
lstrcpy(*ppszTranslatedURL, pszTempTranslatedURL);
|
||
|
ASSERT(lstrlen(*ppszTranslatedURL) == lstrlen(pszTempTranslatedURL));
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
|
||
|
delete pszTempTranslatedURL;
|
||
|
pszTempTranslatedURL = NULL;
|
||
|
}
|
||
|
}
|
||
|
#ifdef EXPV
|
||
|
else
|
||
|
hr = E_FLAGS;
|
||
|
}
|
||
|
else
|
||
|
hr = E_POINTER;
|
||
|
#endif
|
||
|
|
||
|
switch (hr)
|
||
|
{
|
||
|
case S_FALSE:
|
||
|
TRACE_OUT(("TranslateURLA(): URL %s does not require translation.",
|
||
|
pcszURL));
|
||
|
break;
|
||
|
|
||
|
case S_OK:
|
||
|
TRACE_OUT(("TranslateURLA(): URL %s translated to URL %s.",
|
||
|
pcszURL,
|
||
|
*ppszTranslatedURL));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(hr == E_OUTOFMEMORY ||
|
||
|
hr == E_POINTER);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ASSERT((hr == S_OK &&
|
||
|
IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
|
||
|
((hr == S_FALSE ||
|
||
|
hr == E_OUTOFMEMORY ||
|
||
|
hr == E_POINTER ||
|
||
|
hr == E_FLAGS) &&
|
||
|
! *ppszTranslatedURL));
|
||
|
|
||
|
DebugExitHRESULT(TranslateURLA, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
|
||
|
|
||
|
INTSHCUTAPI HRESULT WINAPI TranslateURLW(PCWSTR pcszURL, DWORD dwInFlags,
|
||
|
PWSTR UNALIGNED *ppszTranslatedURL)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
DebugEntry(TranslateURLW);
|
||
|
|
||
|
SetLastError(ERROR_NOT_SUPPORTED);
|
||
|
hr = E_NOTIMPL;
|
||
|
|
||
|
DebugExitHRESULT(TranslateURLW, hr);
|
||
|
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
|
||
|
|