windows-nt/Source/XPSP1/NT/shell/ext/url/assoc.c

722 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* assoc.c - Type association routines.
*/
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include <mluisupp.h>
#define _INTSHCUT_ /* for intshcut.h */
#include <intshcut.h>
#include <intshctp.h> /* ALL_???_FLAGS */
#include "assoc.h"
#include "extricon.h"
#include "openas.h"
#pragma warning(disable:4001) /* "single line comment" warning */
#include "filetype.h"
#include "resource.h"
#pragma warning(default:4001) /* "single line comment" warning */
#include "shlstock.h"
#include "shlvalid.h"
/* Global Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
PUBLIC_DATA const HKEY g_hkeyURLProtocols = HKEY_CLASSES_ROOT;
PUBLIC_DATA const HKEY g_hkeyMIMESettings = HKEY_CLASSES_ROOT;
PUBLIC_DATA CCHAR g_cszURLProtocol[] = "URL Protocol";
PUBLIC_DATA CCHAR g_cszContentType[] = "Content Type";
PUBLIC_DATA CCHAR g_cszExtension[] = "Extension";
#pragma data_seg()
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
PRIVATE_DATA CCHAR s_cszShellOpenCmdSubKeyFmt[] = "%s\\shell\\open\\command";
PRIVATE_DATA CCHAR s_cszAppOpenCmdFmt[] = "%s %%1";
PRIVATE_DATA CCHAR s_cszDefaultIconSubKeyFmt[] = "%s\\DefaultIcon";
PRIVATE_DATA CCHAR s_cszDefaultIcon[] = "url.dll,0";
#pragma data_seg()
/***************************** Private Functions *****************************/
/*
** RegisterAppAsURLProtocolHandler()
**
** Under HKEY_CLASSES_ROOT\url-protocol\shell\open\command, add default value =
** "c:\foo\bar.exe %1".
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL RegisterAppAsURLProtocolHandler(PCSTR pcszProtocol,
PCSTR pcszApp)
{
BOOL bResult = FALSE;
DWORD dwcbShellOpenCmdSubKeyLen;
PSTR pszShellOpenCmdSubKey;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszApp, CSTR));
/* (+ 1) for null terminator. */
dwcbShellOpenCmdSubKeyLen = sizeof(s_cszShellOpenCmdSubKeyFmt) + 1
+ lstrlen(pcszProtocol);
if (AllocateMemory(dwcbShellOpenCmdSubKeyLen, &pszShellOpenCmdSubKey))
{
DWORD dwcbAppOpenCmdLen;
PSTR pszAppOpenCmd;
/* FEATURE: We should quote pcszApp here only if it contains spaces. */
/* (+ 1) for null terminator. */
dwcbAppOpenCmdLen = sizeof(s_cszAppOpenCmdFmt) + 1 + lstrlen(pcszApp);
if (AllocateMemory(dwcbAppOpenCmdLen, &pszAppOpenCmd))
{
EVAL((DWORD)wsprintf(pszShellOpenCmdSubKey, s_cszShellOpenCmdSubKeyFmt,
pcszProtocol) < dwcbShellOpenCmdSubKeyLen);
EVAL((DWORD)wsprintf(pszAppOpenCmd, s_cszAppOpenCmdFmt, pcszApp)
< dwcbAppOpenCmdLen);
/* (+ 1) for null terminator. */
bResult = (SetRegKeyValue(g_hkeyURLProtocols, pszShellOpenCmdSubKey,
NULL, REG_SZ, (PCBYTE)pszAppOpenCmd,
lstrlen(pszAppOpenCmd) + 1)
== ERROR_SUCCESS);
FreeMemory(pszShellOpenCmdSubKey);
pszShellOpenCmdSubKey = NULL;
}
FreeMemory(pszAppOpenCmd);
pszAppOpenCmd = NULL;
}
return(bResult);
}
/*
** RegisterURLProtocolDescription()
**
** Under g_hkeyURLSettings\url-protocol, add default value =
** URL:Url-protocol Protocol.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL RegisterURLProtocolDescription(PCSTR pcszProtocol)
{
BOOL bResult = FALSE;
PSTR pszProtocolCopy;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
if (StringCopy(pcszProtocol, &pszProtocolCopy))
{
char szDescriptionFmt[MAX_PATH_LEN];
/*
* Convert first character of protocol to upper case for description
* string.
*/
*pszProtocolCopy = (CHAR)PtrToUlong(CharUpper((LPSTR)(DWORD_PTR)*pszProtocolCopy));
if (MLLoadStringA(IDS_URL_DESC_FORMAT,
szDescriptionFmt, sizeof(szDescriptionFmt)))
{
char szDescription[MAX_PATH_LEN];
if ((UINT)lstrlen(szDescriptionFmt) + (UINT)lstrlen(pszProtocolCopy)
< sizeof(szDescription))
{
EVAL(wsprintf(szDescription, szDescriptionFmt, pszProtocolCopy)
< sizeof(szDescription));
/* (+ 1) for null terminator. */
bResult = (SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol,
NULL, REG_SZ, (PCBYTE)szDescription,
lstrlen(szDescription) + 1)
== ERROR_SUCCESS);
}
}
FreeMemory(pszProtocolCopy);
pszProtocolCopy = NULL;
}
return(bResult);
}
/*
** RegisterURLProtocolFlags()
**
** Under g_hkeyURLSettings\url-protocol, add EditFlags = FTA_Show.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL RegisterURLProtocolFlags(PCSTR pcszProtocol)
{
DWORD dwEditFlags = FTA_Show;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
/* FEATURE: What about preserving any existing EditFlags here? */
/* (+ 1) for null terminator. */
return(SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol, g_cszEditFlags,
REG_BINARY, (PCBYTE)&dwEditFlags, sizeof(dwEditFlags))
== ERROR_SUCCESS);
}
/*
** RegisterURLProtocol()
**
** Under g_hkeyURLSettings\url-protocol, add URL Protocol = "".
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL RegisterURLProtocol(PCSTR pcszProtocol)
{
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
/* (+ 1) for null terminator. */
return(SetRegKeyValue(g_hkeyURLProtocols, pcszProtocol, g_cszURLProtocol,
REG_SZ, (PCBYTE)EMPTY_STRING,
lstrlen(EMPTY_STRING) + 1) == ERROR_SUCCESS);
}
/*
** RegisterURLProtocolDefaultIcon()
**
** Under g_hkeyURLSettings\url-protocol\DefaultIcon, add default value =
** app.exe,0.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL RegisterURLProtocolDefaultIcon(PCSTR pcszProtocol)
{
BOOL bResult = FALSE;
DWORD dwcbDefaultIconSubKeyLen;
PSTR pszDefaultIconSubKey;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
/* (+ 1) for null terminator. */
dwcbDefaultIconSubKeyLen = sizeof(s_cszDefaultIconSubKeyFmt) + 1
+ lstrlen(pcszProtocol);
if (AllocateMemory(dwcbDefaultIconSubKeyLen, &pszDefaultIconSubKey))
{
EVAL((DWORD)wsprintf(pszDefaultIconSubKey, s_cszDefaultIconSubKeyFmt,
pcszProtocol) < dwcbDefaultIconSubKeyLen);
bResult = (SetRegKeyValue(g_hkeyURLProtocols, pszDefaultIconSubKey,
NULL, REG_SZ, (PCBYTE)s_cszDefaultIcon,
sizeof(s_cszDefaultIcon))
== ERROR_SUCCESS);
FreeMemory(pszDefaultIconSubKey);
pszDefaultIconSubKey = NULL;
}
return(bResult);
}
PRIVATE_CODE BOOL AllowedToRegisterMIMEType(PCSTR pcszMIMEContentType)
{
BOOL bResult;
#pragma data_seg(DATA_SEG_READ_ONLY)
bResult = (lstrcmpi(pcszMIMEContentType, "application/octet-stream") != 0 &&
lstrcmpi(pcszMIMEContentType, "application/octet-string") != 0);
#pragma data_seg()
if (bResult)
TRACE_OUT(("AllowedToRegisterMIMEType(): MIME type %s may be registered.",
pcszMIMEContentType));
else
WARNING_OUT(("AllowedToRegisterMIMEType(): MIME type %s may not be registered.",
pcszMIMEContentType));
return(bResult);
}
/****************************** Public Functions *****************************/
/*
** RegisterMIMETypeForExtension()
**
** Under HKEY_CLASSES_ROOT\.ext, add Content Type = mime/type.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE BOOL RegisterMIMETypeForExtension(PCSTR pcszExtension,
PCSTR pcszMIMEContentType)
{
ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
ASSERT(IsValidExtension(pcszExtension));
/* (+ 1) for null terminator. */
return(SetRegKeyValue(HKEY_CLASSES_ROOT, pcszExtension, g_cszContentType, REG_SZ,
(PCBYTE)pcszMIMEContentType,
lstrlen(pcszMIMEContentType) + 1) == ERROR_SUCCESS);
}
/*
** UnregisterMIMETypeForExtension()
**
** Deletes Content Type under HKEY_CLASSES_ROOT\.ext.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE BOOL UnregisterMIMETypeForExtension(PCSTR pcszExtension)
{
ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));
ASSERT(IsValidExtension(pcszExtension));
return(NO_ERROR == SHDeleteValue(HKEY_CLASSES_ROOT, pcszExtension, g_cszContentType));
}
/*
** RegisterExtensionForMIMEType()
**
** Under g_hkeyMIMESettings\MIME\Database\Content Type\mime/type, add
** Content Type = mime/type and Extension = .ext.
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE BOOL RegisterExtensionForMIMEType(PCSTR pcszExtension,
PCSTR pcszMIMEContentType)
{
BOOL bResult;
char szMIMEContentTypeSubKey[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszExtension, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
ASSERT(IsValidExtension(pcszExtension));
bResult = GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
sizeof(szMIMEContentTypeSubKey));
if (bResult)
/* (+ 1) for null terminator. */
bResult = (SetRegKeyValue(g_hkeyMIMESettings, szMIMEContentTypeSubKey,
g_cszExtension, REG_SZ, (PCBYTE)pcszExtension,
lstrlen(pcszExtension) + 1) == ERROR_SUCCESS);
if (bResult)
TRACE_OUT(("RegisterExtensionForMIMEType(): Registered extension %s as default extension for MIME type %s.",
pcszExtension,
pcszMIMEContentType));
else
WARNING_OUT(("RegisterExtensionForMIMEType(): Failed to register extension %s as default extension for MIME type %s.",
pcszExtension,
pcszMIMEContentType));
return(bResult);
}
/*
** UnregisterExtensionForMIMEType()
**
** Deletes Extension under
** g_hkeyMIMESettings\MIME\Database\Content Type\mime/type. If no other values
** or sub keys are left, deletes
** g_hkeyMIMESettings\MIME\Database\Content Type\mime/type.
**
** Arguments:
**
** Returns:
**
** Side Effects: May also delete MIME key.
*/
PUBLIC_CODE BOOL UnregisterExtensionForMIMEType(PCSTR pcszMIMEContentType)
{
BOOL bResult;
char szMIMEContentTypeSubKey[MAX_PATH_LEN];
ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
bResult = (GetMIMETypeSubKey(pcszMIMEContentType, szMIMEContentTypeSubKey,
sizeof(szMIMEContentTypeSubKey)) &&
SHDeleteValue(g_hkeyMIMESettings, szMIMEContentTypeSubKey,
g_cszExtension) == ERROR_SUCCESS &&
SHDeleteOrphanKey(g_hkeyMIMESettings, szMIMEContentTypeSubKey) == ERROR_SUCCESS);
if (bResult)
TRACE_OUT(("UnregisterExtensionForMIMEType(): Unregistered default extension for MIME type %s.",
pcszMIMEContentType));
else
WARNING_OUT(("UnregisterExtensionForMIMEType(): Failed to unregister default extension for MIME type %s.",
pcszMIMEContentType));
return(bResult);
}
PUBLIC_CODE BOOL RegisterMIMEAssociation(PCSTR pcszFile,
PCSTR pcszMIMEContentType)
{
BOOL bResult;
PCSTR pcszExtension;
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
pcszExtension = ExtractExtension(pcszFile);
/*
* Don't allow association of flag unknown MIME types
* application/octet-stream and application/octet-string.
*/
if (EVAL(*pcszExtension) &&
AllowedToRegisterMIMEType(pcszMIMEContentType))
bResult = (RegisterMIMETypeForExtension(pcszExtension, pcszMIMEContentType) &&
RegisterExtensionForMIMEType(pcszExtension, pcszMIMEContentType));
else
bResult = FALSE;
return(bResult);
}
PUBLIC_CODE BOOL RegisterURLAssociation(PCSTR pcszProtocol, PCSTR pcszApp)
{
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszApp, CSTR));
return(RegisterAppAsURLProtocolHandler(pcszProtocol, pcszApp) &&
RegisterURLProtocolDescription(pcszProtocol) &&
RegisterURLProtocol(pcszProtocol) &&
RegisterURLProtocolFlags(pcszProtocol) &&
RegisterURLProtocolDefaultIcon(pcszProtocol));
}
PUBLIC_CODE HRESULT MyMIMEAssociationDialog(HWND hwndParent, DWORD dwInFlags,
PCSTR pcszFile,
PCSTR pcszMIMEContentType,
PSTR pszAppBuf, UINT ucAppBufLen)
{
HRESULT hr;
OPENASINFO oainfo;
ASSERT(IS_VALID_HANDLE(hwndParent, WND));
ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS));
ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR));
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));
/* Use default file name if not supplied by caller. */
if (ucAppBufLen > 0)
*pszAppBuf = '\0';
oainfo.pcszFile = pcszFile;
oainfo.pcszClass = pcszMIMEContentType;
oainfo.dwInFlags = 0;
if (IS_FLAG_SET(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC))
SET_FLAG(oainfo.dwInFlags, (OPENASINFO_FL_ALLOW_REGISTRATION |
OPENASINFO_FL_REGISTER_EXT));
hr = MyOpenAsDialog(hwndParent, &oainfo);
if (hr == S_OK &&
IS_FLAG_SET(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC))
hr = RegisterMIMEAssociation(pcszFile, pcszMIMEContentType) ? S_OK
: E_OUTOFMEMORY;
if (SUCCEEDED(hr))
lstrcpyn(pszAppBuf, oainfo.szApp, ucAppBufLen);
ASSERT(! ucAppBufLen ||
(IS_VALID_STRING_PTR(pszAppBuf, STR) &&
EVAL((UINT)lstrlen(pszAppBuf) < ucAppBufLen)));
ASSERT(SUCCEEDED(hr) ||
(! ucAppBufLen ||
EVAL(! *pszAppBuf)));
return(hr);
}
PUBLIC_CODE HRESULT MyURLAssociationDialog(HWND hwndParent, DWORD dwInFlags,
PCSTR pcszFile, PCSTR pcszURL,
PSTR pszAppBuf, UINT ucAppBufLen)
{
HRESULT hr;
PSTR pszProtocol;
ASSERT(IS_VALID_HANDLE(hwndParent, WND));
ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS));
ASSERT(IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) ||
IS_VALID_STRING_PTR(pcszFile, CSTR));
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));
/* Use URL protocol as class name. */
if (ucAppBufLen > 0)
*pszAppBuf = '\0';
hr = CopyURLProtocol(pcszURL, &pszProtocol);
if (hr == S_OK)
{
char szInternetShortcut[MAX_PATH_LEN];
OPENASINFO oainfo;
/* Use default file name if not supplied by caller. */
if (IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) &&
EVAL(MLLoadStringA(IDS_INTERNET_SHORTCUT,
szInternetShortcut, sizeof(szInternetShortcut))))
pcszFile = szInternetShortcut;
oainfo.pcszFile = pcszFile;
oainfo.pcszClass = pszProtocol;
oainfo.dwInFlags = 0;
if (IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC))
SET_FLAG(oainfo.dwInFlags, OPENASINFO_FL_ALLOW_REGISTRATION);
hr = MyOpenAsDialog(hwndParent, &oainfo);
if (hr == S_OK &&
IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC))
hr = RegisterURLAssociation(pszProtocol, oainfo.szApp) ? S_OK
: E_OUTOFMEMORY;
if (SUCCEEDED(hr))
lstrcpyn(pszAppBuf, oainfo.szApp, ucAppBufLen);
FreeMemory(pszProtocol);
pszProtocol = NULL;
}
ASSERT(! ucAppBufLen ||
(IS_VALID_STRING_PTR(pszAppBuf, STR) &&
EVAL((UINT)lstrlen(pszAppBuf) < ucAppBufLen)));
ASSERT(SUCCEEDED(hr) ||
(! ucAppBufLen ||
EVAL(! *pszAppBuf)));
return(hr);
}
#ifdef DEBUG
PUBLIC_CODE BOOL IsValidPCOPENASINFO(PCOPENASINFO pcoainfo)
{
return(IS_VALID_READ_PTR(pcoainfo, COPENASINFO) &&
IS_VALID_STRING_PTR(pcoainfo->pcszFile, CSTR) &&
(! pcoainfo->pcszClass ||
IS_VALID_STRING_PTR(pcoainfo->pcszClass, CSTR)) &&
FLAGS_ARE_VALID(pcoainfo->dwInFlags, ALL_OPENASINFO_FLAGS) &&
(! *pcoainfo->szApp ||
IS_VALID_STRING_PTR(pcoainfo->szApp, STR)));
}
#endif /* DEBUG */
/***************************** Exported Functions ****************************/
INTSHCUTAPI HRESULT WINAPI MIMEAssociationDialogA(HWND hwndParent,
DWORD dwInFlags,
PCSTR pcszFile,
PCSTR pcszMIMEContentType,
PSTR pszAppBuf,
UINT ucAppBufLen)
{
HRESULT hr;
DebugEntry(MIMEAssociationDialogA);
#ifdef EXPV
/* Verify parameters. */
if (IS_VALID_HANDLE(hwndParent, WND) &&
IS_VALID_STRING_PTR(pcszFile, CSTR) &&
IS_VALID_STRING_PTR(pcszMIMEContentType, CSTR) &&
IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen))
{
if (FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS))
#endif
{
hr = MyMIMEAssociationDialog(hwndParent, dwInFlags, pcszFile,
pcszMIMEContentType, pszAppBuf,
ucAppBufLen);
}
#ifdef EXPV
else
hr = E_FLAGS;
}
else
hr = E_POINTER;
#endif
DebugExitHRESULT(MIMEAssociationDialogA, hr);
return(hr);
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
INTSHCUTAPI HRESULT WINAPI MIMEAssociationDialogW(HWND hwndParent,
DWORD dwInFlags,
PCWSTR pcszFile,
PCWSTR pcszMIMEContentType,
PWSTR pszAppBuf,
UINT ucAppBufLen)
{
HRESULT hr;
DebugEntry(MIMEAssociationDialogW);
SetLastError(ERROR_NOT_SUPPORTED);
hr = E_NOTIMPL;
DebugExitHRESULT(MIMEAssociationDialogW, hr);
return(hr);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
INTSHCUTAPI HRESULT WINAPI URLAssociationDialogA(HWND hwndParent,
DWORD dwInFlags,
PCSTR pcszFile, PCSTR pcszURL,
PSTR pszAppBuf,
UINT ucAppBufLen)
{
HRESULT hr;
DebugEntry(URLAssociationDialogA);
#ifdef EXPV
/* Verify parameters. */
if (IS_VALID_HANDLE(hwndParent, WND) &&
(IS_FLAG_SET(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) ||
IS_VALID_STRING_PTR(pcszFile, CSTR)) &&
IS_VALID_STRING_PTR(pcszURL, CSTR) &&
IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen))
{
if (FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS))
#endif
{
hr = MyURLAssociationDialog(hwndParent, dwInFlags, pcszFile, pcszURL,
pszAppBuf, ucAppBufLen);
}
#ifdef EXPV
else
hr = E_FLAGS;
}
else
hr = E_POINTER;
#endif
DebugExitHRESULT(URLAssociationDialogA, hr);
return(hr);
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
INTSHCUTAPI HRESULT WINAPI URLAssociationDialogW(HWND hwndParent,
DWORD dwInFlags,
PCWSTR pcszFile,
PCWSTR pcszURL,
PWSTR pszAppBuf,
UINT ucAppBufLen)
{
HRESULT hr;
DebugEntry(URLAssociationDialogW);
SetLastError(ERROR_NOT_SUPPORTED);
hr = E_NOTIMPL;
DebugExitHRESULT(URLAssociationDialogW, hr);
return(hr);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */