Windows-Server-2003/shell/ext/url/contmenu.cpp

312 lines
8.8 KiB
C++

/*
* contmenu.cpp - Context menu implementation for URL class.
*/
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include <mapi.h>
/* Types
********/
/* MAPISendMail() typedef */
typedef ULONG (FAR PASCAL *MAPISENDMAILPROC)(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessageA lpMessage, FLAGS flFlags, ULONG ulReserved);
/* RunDLL32 DLL entry point typedef */
typedef void (WINAPI *RUNDLL32PROC)(HWND hwndParent, HINSTANCE hinst, PSTR pszCmdLine, int nShowCmd);
/* Module Constants
*******************/
// case-insensitive
PRIVATE_DATA const char s_cszFileProtocolPrefix[] = "file:";
PRIVATE_DATA const char s_cszMailToProtocolPrefix[] = "mailto:";
PRIVATE_DATA const char s_cszRLoginProtocolPrefix[] = "rlogin:";
PRIVATE_DATA const char s_cszTelnetProtocolPrefix[] = "telnet:";
PRIVATE_DATA const char s_cszTN3270ProtocolPrefix[] = "tn3270:";
PRIVATE_DATA const char s_cszNewsDLL[] = "mcm.dll";
PRIVATE_DATA const char s_cszTelnetApp[] = "telnet.exe";
PRIVATE_DATA const char s_cszMAPISection[] = "Mail";
PRIVATE_DATA const char s_cszMAPIKey[] = "CMCDLLName32";
PRIVATE_DATA const char s_cszMAPISendMail[] = "MAPISendMail";
PRIVATE_DATA const char s_cszNewsProtocolHandler[] = "NewsProtocolHandler";
#define MyMsgBox(x) //(void)(x)
#define DebugEntry(x)
extern "C" void WINAPI FileProtocolHandler(HWND hwndParent, HINSTANCE hinst,
PSTR pszCmdLine, int nShowCmd)
{
CHAR sz[MAX_PATH];
DWORD cch = ARRAYSIZE(sz);
if (SUCCEEDED(PathCreateFromUrlA(pszCmdLine, sz, &cch, 0)))
pszCmdLine = sz;
ShellExecute(hwndParent, NULL, pszCmdLine, NULL, NULL,
nShowCmd);
}
extern "C" void WINAPI MailToProtocolHandler(HWND hwndParent, HINSTANCE hinst,
PSTR pszCmdLine, int nShowCmd)
{
char szMAPIDLL[MAX_PATH];
if (GetProfileString(s_cszMAPISection, s_cszMAPIKey, "",
szMAPIDLL, sizeof(szMAPIDLL)) > 0)
{
HINSTANCE hinstMAPI = LoadLibrary(szMAPIDLL);
if (hinstMAPI)
{
MAPISENDMAILPROC MAPISendMailProc = (MAPISENDMAILPROC)GetProcAddress(
hinstMAPI,
s_cszMAPISendMail);
if (MAPISendMailProc)
{
PARSEDURLA pu = {sizeof(pu)};
if (SUCCEEDED(ParseURLA(pszCmdLine, &pu)) && URL_SCHEME_MAILTO == pu.nScheme)
{
MapiRecipDescA mapito;
MapiMessage mapimsg;
pszCmdLine = (PSTR) pu.pszSuffix;
ZeroMemory(&mapito, sizeof(mapito));
mapito.ulRecipClass = MAPI_TO;
mapito.lpszName = pszCmdLine;
ZeroMemory(&mapimsg, sizeof(mapimsg));
mapimsg.nRecipCount = 1;
mapimsg.lpRecips = &mapito;
(*MAPISendMailProc)(NULL, 0, &mapimsg,
(MAPI_LOGON_UI | MAPI_DIALOG), 0);
}
}
FreeLibrary(hinstMAPI);
}
}
}
extern "C" void WINAPI NewsProtocolHandler(HWND hwndParent, HINSTANCE hinst,
PSTR pszCmdLine, int nShowCmd)
{
HINSTANCE hinstNews = LoadLibrary(s_cszNewsDLL);
if (hinstNews)
{
RUNDLL32PROC RealNewsProtocolHandler = (RUNDLL32PROC)GetProcAddress(hinstNews, s_cszNewsProtocolHandler);
if (RealNewsProtocolHandler)
{
(*RealNewsProtocolHandler)(hwndParent, hinst, pszCmdLine, nShowCmd);
}
FreeLibrary(hinstNews);
}
}
#ifndef ISSPACE
#define ISSPACE(ch) (((ch) == 32) || ((unsigned)((ch) - 9)) <= 13 - 9)
#endif
#ifndef ISQUOTE
#define ISQUOTE(ch) ((ch) == '\"' || (ch) == '\'')
#endif
void TrimString(PSTR pszTrimMe, PCSTR pszTrimChars)
{
PSTR psz;
PSTR pszStartMeat;
if ( !pszTrimMe )
return;
/* Trim leading characters. */
psz = pszTrimMe;
while (*psz && StrChr(pszTrimChars, *psz))
psz = CharNext(psz);
pszStartMeat = psz;
/* Trim trailing characters. */
if (*psz)
{
psz += lstrlen(psz);
psz = CharPrev(pszStartMeat, psz);
if (psz > pszStartMeat)
{
while (StrChr(pszTrimChars, *psz))
psz = CharPrev(pszStartMeat, psz);
psz = CharNext(psz);
*psz = '\0';
}
}
/* Relocate stripped string. */
if (pszStartMeat > pszTrimMe)
/* (+ 1) for null terminator. */
MoveMemory(pszTrimMe, pszStartMeat, lstrlen(pszStartMeat) + 1);
return;
}
void TrimSlashes(PSTR pszTrimMe)
{
TrimString(pszTrimMe, "\\/");
/* TrimString() validates pszTrimMe on output. */
return;
}
extern "C" void WINAPI TelnetProtocolHandler(HWND hwndParent, HINSTANCE hinst,
PSTR pszCmdLine, int nShowCmd)
{
HRESULT hr;
char *p;
char *pDest;
BOOL fRemove;
PARSEDURLA pu = {sizeof(pu)};
if (SUCCEEDED(ParseURLA(pszCmdLine, &pu)))
{
if ((URL_SCHEME_TELNET == pu.nScheme)
|| (0 == StrCmpNI(pu.pszProtocol, s_cszRLoginProtocolPrefix, pu.cchProtocol))
|| (0 == StrCmpNI(pu.pszProtocol, s_cszTN3270ProtocolPrefix, pu.cchProtocol)))
{
pszCmdLine = (PSTR) pu.pszSuffix;
}
}
// Remove leading and trailing slashes.
TrimSlashes(pszCmdLine);
p = StrChr(pszCmdLine, '@');
if (p)
pszCmdLine = p + 1;
// Eliminate double quotes...should be no need for these
// unless trouble is afoot.
for (pDest = p = pszCmdLine; *p; p++)
{
if (!ISQUOTE(*p))
{
*pDest = *p;
pDest++;
}
}
*pDest = '\0';
// For security reasons, strip the filename cmdline option
if (pszCmdLine)
{
for (p = pszCmdLine; *p; p++)
{
// Be careful and don't nuke servernames that start with -f.
// Since hostnames can't start with a dash, ensure previous char is
// whitespace, or we're at the beginning.
//
// Also, -a sends credentials over the wire, so strip it, too.
if ((*p == '/' || *p == '-') &&
(*(p+1) == 'f' || *(p+1) == 'F' || *(p+1) == 'a' || *(p+1) == 'A'))
{
fRemove = TRUE;
if (!((p == pszCmdLine || ISSPACE(*(p-1)) || ISQUOTE(*(p-1)) )))
{
char *pPortChar = p-1;
// Doesn't meet easy criteria, but it might be harder to
// detect, such as site:-ffilename. In this case, consider
// the -f piece unsafe if everything between -f and a colon
// to the left is a digit (no digits will also be unsafe).
// If anything else is hit first, then consider it to
// be part of the hostname. Walking to the beginning
// be considered safe (e.g. "80-ffilename" would be considered
// the hostname).
while (pPortChar >= pszCmdLine && *pPortChar != ':')
{
if (*pPortChar < '0' || *pPortChar > '9')
{
fRemove = FALSE;
break;
}
pPortChar--;
}
if (pPortChar < pszCmdLine)
fRemove = FALSE;
}
if (!fRemove)
continue;
BOOL fQuotedFilename = FALSE;
LPSTR pStart = p;
// move past -f
p+=2;
// Skip over whitespace and filename following -f option
if (*(p-1) == 'f' || *(p-1) == 'F')
{
while (*p && ISSPACE(*p))
p++;
// but wait, it may be a long filename surrounded by quotes
if (ISQUOTE(*p))
{
fQuotedFilename = TRUE;
p++;
}
// Loop until null OR whitespace if not quoted pathname OR quote if a quoted pathname
while (!((*p == '\0') ||
(ISSPACE(*p) && !fQuotedFilename) ||
(ISQUOTE(*p) && fQuotedFilename)))
p++;
}
// phase out the -a and -f options, but keep going to search the rest of the string
memmove((VOID *)pStart, (VOID *)p, strlen(p)+1);
p = pStart-1;
}
}
}
// If a port has been specified, turn ':' into space, which will make the
// port become the second command line argument.
p = StrChr(pszCmdLine, ':');
if (p)
*p = ' ';
ShellExecute(hwndParent, NULL, s_cszTelnetApp, pszCmdLine, NULL , SW_SHOW);
}