|
|
/*
* urlassoc.c - URL Type association routines. */
#include "priv.h"
#include "ishcut.h"
#include <filetype.h>
#include <shlwapip.h>
#include "assocurl.h"
#include "resource.h"
#include <intshctp.h>
#include <mluisupp.h>
#define c_szURLProtocol TEXT("URL Protocol")
#define c_szEditFlags TEXT("EditFlags")
#define c_szMIMETypeSubKeyFmt TEXT("MIME\\Database\\Content Type\\%s")
#define c_szShellOpenCmdSubKeyFmt TEXT("%s\\shell\\open\\command")
#define c_szAppOpenCmdFmt TEXT("%s %%1")
#define c_szDefaultIconSubKeyFmt TEXT("%s\\DefaultIcon")
#define c_szDefaultProtocolIcon TEXT("shdocvw.dll,-105")
/***************************** Private Functions *****************************/
extern "C" {
/*
** RegisterAppAsURLProtocolHandler() ** ** Under HKEY_CLASSES_ROOT\url-protocol\shell\open\command, add default value = ** "c:\foo\bar.exe %1". ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ BOOL RegisterAppAsURLProtocolHandler( LPCTSTR pcszProtocol, LPCTSTR pcszApp) { BOOL bResult = FALSE; DWORD cbShellOpen; LPTSTR pszShellOpen;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1)); ASSERT(IS_VALID_STRING_PTR(pcszApp, -1));
/* (+ 1) for null terminator. */ cbShellOpen = SIZEOF(c_szShellOpenCmdSubKeyFmt) + CbFromCch(1 + lstrlen(pcszProtocol));
pszShellOpen = (LPTSTR)LocalAlloc(LPTR, cbShellOpen);
if (pszShellOpen) { DWORD cbAppOpen; LPTSTR pszAppOpen;
/* FEATURE: We should quote pcszApp here only if it contains spaces. */
/* (+ 1) for null terminator. */ cbAppOpen = SIZEOF(c_szAppOpenCmdFmt) + CbFromCch(1 + lstrlen(pcszApp));
pszAppOpen = (LPTSTR)LocalAlloc(LPTR, cbAppOpen);
if (pszAppOpen) { wnsprintf(pszShellOpen, cbShellOpen / sizeof(TCHAR), c_szShellOpenCmdSubKeyFmt, pcszProtocol);
wnsprintf(pszAppOpen, cbAppOpen / sizeof(TCHAR), c_szAppOpenCmdFmt, pcszApp);
/* (+ 1) for null terminator. */ bResult = (NO_ERROR == SHSetValue(HKEY_CLASSES_ROOT, pszShellOpen, NULL, REG_SZ, pszAppOpen, CbFromCch(lstrlen(pszAppOpen) + 1)));
LocalFree(pszAppOpen); pszAppOpen = NULL; }
LocalFree(pszShellOpen); pszShellOpen = NULL; }
return(bResult); }
/*
** RegisterURLProtocolDescription() ** ** Under HKEY_CLASSES_ROOT\url-protocol, add default value = ** URL:Url-protocol Protocol. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ BOOL RegisterURLProtocolDescription( LPCTSTR pcszProtocol) { BOOL bResult = FALSE; LPTSTR pszProtocolCopy = NULL;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1));
if (Str_SetPtr(&pszProtocolCopy, pcszProtocol)) { TCHAR szDescriptionFmt[MAX_PATH];
/*
* Convert first character of protocol to upper case for description * string. */
*pszProtocolCopy = (TCHAR) (DWORD_PTR) CharUpper((LPTSTR)(DWORD_PTR)*pszProtocolCopy);
if (MLLoadString(IDS_URL_DESC_FORMAT, szDescriptionFmt, SIZECHARS(szDescriptionFmt))) { TCHAR szDescription[MAX_PATH];
if ((UINT)lstrlen(szDescriptionFmt) + (UINT)lstrlen(pszProtocolCopy) < SIZECHARS(szDescription)) { wnsprintf(szDescription, ARRAYSIZE(szDescription), szDescriptionFmt, pszProtocolCopy);
/* (+ 1) for null terminator. */ bResult = (NO_ERROR == SHSetValue(HKEY_CLASSES_ROOT, pcszProtocol, NULL, REG_SZ, szDescription, CbFromCch(lstrlen(szDescription) + 1))); } }
Str_SetPtr(&pszProtocolCopy, NULL); }
return(bResult); }
/*
** RegisterURLProtocolFlags() ** ** Under HKEY_CLASSES_ROOT\url-protocol, add EditFlags = FTA_Show. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ BOOL RegisterURLProtocolFlags( LPCTSTR pcszProtocol) { DWORD dwEditFlags = FTA_Show;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1));
/* FEATURE: What about preserving any existing EditFlags here? */
return NO_ERROR == SHSetValue(HKEY_CLASSES_ROOT, pcszProtocol, c_szEditFlags, REG_BINARY, &dwEditFlags, SIZEOF(dwEditFlags)); }
/*
** RegisterURLProtocol() ** ** Under HKEY_CLASSES_ROOT\url-protocol, add URL Protocol = "". ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ BOOL RegisterURLProtocol( LPCTSTR pcszProtocol) { ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1));
// REVIEW (scotth): what does this value mean??
/* (+ 1) for null terminator. */ return NO_ERROR == SHSetValue(HKEY_CLASSES_ROOT, pcszProtocol, c_szURLProtocol, REG_SZ, c_szNULL, CbFromCch(1)); }
/*
** RegisterURLProtocolDefaultIcon() ** ** Under HKEY_CLASSES_ROOT\url-protocol\DefaultIcon, add default value = ** app.exe,0. ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ BOOL RegisterURLProtocolDefaultIcon( LPCTSTR pcszProtocol) { BOOL bResult = FALSE; DWORD cbAlloc; LPTSTR pszT;
ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1));
/* (+ 1) for null terminator. */ cbAlloc = SIZEOF(c_szDefaultIconSubKeyFmt) + CbFromCch(1 + lstrlen(pcszProtocol));
pszT = (LPTSTR)LocalAlloc(LPTR, cbAlloc);
if (pszT) { wnsprintf(pszT, cbAlloc / sizeof(TCHAR), c_szDefaultIconSubKeyFmt, pcszProtocol);
bResult = (NO_ERROR == SHSetValue(HKEY_CLASSES_ROOT, pszT, NULL, REG_SZ, c_szDefaultProtocolIcon, SIZEOF(c_szDefaultProtocolIcon)));
LocalFree(pszT); pszT = NULL; }
return(bResult); }
BOOL AllowedToRegisterMIMEType( LPCTSTR pcszMIMEContentType) { BOOL bResult;
bResult = (0 != StrCmpI(pcszMIMEContentType, TEXT("application/octet-stream")) && 0 != StrCmpI(pcszMIMEContentType, TEXT("application/octet-string")));
return(bResult); }
BOOL RegisterMIMEAssociation( LPCTSTR pcszFile, LPCTSTR pcszMIMEContentType) { BOOL bResult; LPCTSTR pcszExtension;
ASSERT(IS_VALID_STRING_PTR(pcszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, -1));
pcszExtension = PathFindExtension(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); }
BOOL RegisterURLAssociation( LPCTSTR pcszProtocol, LPCTSTR pcszApp) { ASSERT(IS_VALID_STRING_PTR(pcszProtocol, -1)); ASSERT(IS_VALID_STRING_PTR(pcszApp, -1));
return(RegisterAppAsURLProtocolHandler(pcszProtocol, pcszApp) && RegisterURLProtocolDescription(pcszProtocol) && RegisterURLProtocol(pcszProtocol) && RegisterURLProtocolFlags(pcszProtocol) && RegisterURLProtocolDefaultIcon(pcszProtocol)); }
HRESULT MyMIMEAssociationDialog( HWND hwndParent, DWORD dwInFlags, LPCTSTR pcszFile, LPCTSTR pcszMIMEContentType, LPTSTR pszAppBuf, UINT cchAppBuf) { HRESULT hr; OPENASINFO oainfo;
ASSERT(IS_VALID_HANDLE(hwndParent, WND)); ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS)); ASSERT(IS_VALID_STRING_PTR(pcszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pcszMIMEContentType, -1)); ASSERT(IS_VALID_WRITE_BUFFER(pszAppBuf, TCHAR, cchAppBuf));
/* Use default file name if not supplied by caller. */
if (cchAppBuf > 0) *pszAppBuf = '\0';
oainfo.pcszFile = pcszFile; oainfo.pcszClass = pcszMIMEContentType; oainfo.dwInFlags = 0;
if (IsFlagSet(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC)) { SetFlag(oainfo.dwInFlags, (OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT)); }
#if 0 // FEATURE (scotth): fix this
hr = OpenAsDialog(hwndParent, &oainfo); #else
hr = E_FAIL; #endif
if (hr == S_OK && IsFlagSet(dwInFlags, MIMEASSOCDLG_FL_REGISTER_ASSOC)) { hr = RegisterMIMEAssociation(pcszFile, pcszMIMEContentType) ? S_OK : E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) StrCpyN(pszAppBuf, oainfo.szApp, cchAppBuf);
ASSERT(! cchAppBuf || (IS_VALID_STRING_PTR(pszAppBuf, -1) && EVAL((UINT)lstrlen(pszAppBuf) < cchAppBuf))); ASSERT(SUCCEEDED(hr) || (! cchAppBuf || EVAL(! *pszAppBuf)));
return(hr); }
HRESULT MyURLAssociationDialog( HWND hwndParent, DWORD dwInFlags, LPCTSTR pcszFile, LPCTSTR pcszURL, LPTSTR pszAppBuf, UINT cchAppBuf) { HRESULT hr; LPTSTR pszProtocol;
ASSERT(IS_VALID_HANDLE(hwndParent, WND)); ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS)); ASSERT(IsFlagSet(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) || IS_VALID_STRING_PTR(pcszFile, -1)); ASSERT(IS_VALID_STRING_PTR(pcszURL, -1)); ASSERT(IS_VALID_WRITE_BUFFER(pszAppBuf, TCHAR, cchAppBuf));
/* Use URL protocol as class name. */
if (cchAppBuf > 0) *pszAppBuf = '\0';
hr = CopyURLProtocol(pcszURL, &pszProtocol, NULL);
if (hr == S_OK) { TCHAR szInternetShortcut[MAX_PATH]; OPENASINFO oainfo;
/* Use default file name if not supplied by caller. */
if (IsFlagSet(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) && EVAL(MLLoadString(IDS_INTERNET_SHORTCUT, szInternetShortcut, SIZECHARS(szInternetShortcut)))) { pcszFile = szInternetShortcut; }
oainfo.pcszFile = pcszFile; oainfo.pcszClass = pszProtocol; oainfo.dwInFlags = 0;
if (IsFlagSet(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC)) SetFlag(oainfo.dwInFlags, OAIF_ALLOW_REGISTRATION);
#if 0 // FEATURE (scotth): fix this
hr = OpenAsDialog(hwndParent, &oainfo); #else
hr = E_FAIL; #endif
if (hr == S_OK && IsFlagSet(dwInFlags, URLASSOCDLG_FL_REGISTER_ASSOC)) { hr = RegisterURLAssociation(pszProtocol, oainfo.szApp) ? S_OK : E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) StrCpyN(pszAppBuf, oainfo.szApp, cchAppBuf);
LocalFree(pszProtocol); pszProtocol = NULL; }
ASSERT(! cchAppBuf || (IS_VALID_STRING_PTR(pszAppBuf, -1) && EVAL((UINT)lstrlen(pszAppBuf) < cchAppBuf))); ASSERT(SUCCEEDED(hr) || (! cchAppBuf || EVAL(! *pszAppBuf)));
return(hr); }
#ifdef DEBUG
BOOL IsValidPCOPENASINFO( POPENASINFO poainfo) { return(IS_VALID_READ_PTR(poainfo, OPENASINFO) && IS_VALID_STRING_PTR(poainfo->pcszFile, -1) && (! poainfo->pcszClass || IS_VALID_STRING_PTR(poainfo->pcszClass, -1)) && FLAGS_ARE_VALID(poainfo->dwInFlags, OAIF_ALL) && (! *poainfo->szApp || IS_VALID_STRING_PTR(poainfo->szApp, -1))); }
#endif /* DEBUG */
/***************************** Exported Functions ****************************/
/*----------------------------------------------------------
Purpose: Invoke the MIME-type association dialog.
Returns: standard hresult
Cond: This API must conform to MIMEAssociationDialog semantics as defined in intshcut.h. URL.DLL auto-forwards to this API in Nashville.
*/ STDAPI AssociateMIME( HWND hwndParent, DWORD dwInFlags, LPCTSTR pcszFile, LPCTSTR pcszMIMEContentType, LPTSTR pszAppBuf, UINT cchAppBuf) { HRESULT hr;
/* Verify parameters. */
#ifdef EXPV
if (IS_VALID_HANDLE(hwndParent, WND) && IS_VALID_STRING_PTR(pcszFile, -1) && IS_VALID_STRING_PTR(pcszMIMEContentType, -1) && IS_VALID_WRITE_BUFFER(pszAppBuf, TCHAR, cchAppBuf)) { if (FLAGS_ARE_VALID(dwInFlags, ALL_MIMEASSOCDLG_FLAGS)) { #endif
hr = MyMIMEAssociationDialog(hwndParent, dwInFlags, pcszFile, pcszMIMEContentType, pszAppBuf, cchAppBuf); #ifdef EXPV
} else hr = E_FLAGS; } else hr = E_POINTER; #endif
return(hr); }
STDAPI AssociateMIMEA( HWND hwndParent, DWORD dwInFlags, LPCSTR pcszFile, LPCSTR pcszMIMEContentType, LPSTR pszAppBuf, UINT cchAppBuf) { HRESULT hres; WCHAR wszFile[MAX_PATH]; WCHAR wszMIMEType[MAX_PATH]; LPWSTR pwszT;
MultiByteToWideChar(CP_ACP, 0, pcszFile, -1, wszFile, SIZECHARS(wszFile)); MultiByteToWideChar(CP_ACP, 0, pcszMIMEContentType, -1, wszMIMEType, SIZECHARS(wszMIMEType));
*pszAppBuf = '\0';
pwszT = (LPWSTR)LocalAlloc(LPTR, CbFromCch(cchAppBuf)); if (pwszT) { hres = AssociateMIME(hwndParent, dwInFlags, wszFile, wszMIMEType, pwszT, cchAppBuf);
if (SUCCEEDED(hres)) { WideCharToMultiByte(CP_ACP, 0, pwszT, -1, pszAppBuf, cchAppBuf, NULL, NULL); }
LocalFree(pwszT); pwszT = NULL; } else { hres = E_OUTOFMEMORY; }
return hres; }
/*----------------------------------------------------------
Purpose: Invoke the URL association dialog.
Returns: standard hresult
Cond: This API must conform to URLAssociationDialog semantics as defined in intshcut.h. URL.DLL auto-forwards to this API in Nashville.
*/ STDAPI AssociateURL( HWND hwndParent, DWORD dwInFlags, LPCTSTR pcszFile, LPCTSTR pcszURL, LPTSTR pszAppBuf, UINT cchAppBuf) { HRESULT hr;
/* Verify parameters. */
#ifdef EXPV
if (IS_VALID_HANDLE(hwndParent, WND) && (IsFlagSet(dwInFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME) || IS_VALID_STRING_PTR(pcszFile, -1)) && IS_VALID_STRING_PTR(pcszURL, -1) && IS_VALID_WRITE_BUFFER(pszAppBuf, TCHAR, cchAppBuf)) { if (FLAGS_ARE_VALID(dwInFlags, ALL_URLASSOCDLG_FLAGS)) { #endif
hr = MyURLAssociationDialog(hwndParent, dwInFlags, pcszFile, pcszURL, pszAppBuf, cchAppBuf); #ifdef EXPV
} else hr = E_FLAGS; } else hr = E_POINTER; #endif
return(hr); }
STDAPI AssociateURLA( HWND hwndParent, DWORD dwInFlags, LPCSTR pcszFile, LPCSTR pcszURL, LPSTR pszAppBuf, UINT cchAppBuf) { HRESULT hres; WCHAR wszFile[MAX_PATH]; WCHAR wszURL[INTERNET_MAX_URL_LENGTH]; LPWSTR pwszT;
MultiByteToWideChar(CP_ACP, 0, pcszFile, -1, wszFile, SIZECHARS(wszFile)); MultiByteToWideChar(CP_ACP, 0, pcszURL, -1, wszURL, SIZECHARS(wszURL));
*pszAppBuf = '\0';
pwszT = (LPWSTR)LocalAlloc(LPTR, CbFromCch(cchAppBuf)); if (pwszT) { hres = AssociateURL(hwndParent, dwInFlags, wszFile, wszURL, pwszT, cchAppBuf);
if (SUCCEEDED(hres)) { WideCharToMultiByte(CP_ACP, 0, pwszT, -1, pszAppBuf, cchAppBuf, NULL, NULL); }
LocalFree(pwszT); pwszT = NULL; } else { hres = E_OUTOFMEMORY; }
return hres; }
}; // extern "C"
|