Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
9.1 KiB

  1. /*
  2. * contmenu.cpp - Context menu implementation for URL class.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include <mapi.h>
  9. /* Types
  10. ********/
  11. /* MAPISendMail() typedef */
  12. typedef ULONG (FAR PASCAL *MAPISENDMAILPROC)(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessageA lpMessage, FLAGS flFlags, ULONG ulReserved);
  13. /* RunDLL32 DLL entry point typedef */
  14. typedef void (WINAPI *RUNDLL32PROC)(HWND hwndParent, HINSTANCE hinst, PSTR pszCmdLine, int nShowCmd);
  15. /* Module Constants
  16. *******************/
  17. // case-insensitive
  18. PRIVATE_DATA const char s_cszFileProtocolPrefix[] = "file:";
  19. PRIVATE_DATA const char s_cszMailToProtocolPrefix[] = "mailto:";
  20. PRIVATE_DATA const char s_cszRLoginProtocolPrefix[] = "rlogin:";
  21. PRIVATE_DATA const char s_cszTelnetProtocolPrefix[] = "telnet:";
  22. PRIVATE_DATA const char s_cszTN3270ProtocolPrefix[] = "tn3270:";
  23. PRIVATE_DATA const char s_cszNewsDLL[] = "mcm.dll";
  24. PRIVATE_DATA const char s_cszTelnetApp[] = "telnet.exe";
  25. PRIVATE_DATA const char s_cszMAPISection[] = "Mail";
  26. PRIVATE_DATA const char s_cszMAPIKey[] = "CMCDLLName32";
  27. PRIVATE_DATA const char s_cszMAPISendMail[] = "MAPISendMail";
  28. PRIVATE_DATA const char s_cszNewsProtocolHandler[] = "NewsProtocolHandler";
  29. #define MyMsgBox(x) //(void)(x)
  30. #define DebugEntry(x)
  31. extern "C" void WINAPI FileProtocolHandler(HWND hwndParent, HINSTANCE hinst,
  32. PSTR pszCmdLine, int nShowCmd)
  33. {
  34. CHAR sz[MAX_PATH];
  35. DWORD cch = ARRAYSIZE(sz);
  36. if (SUCCEEDED(PathCreateFromUrlA(pszCmdLine, sz, &cch, 0)))
  37. pszCmdLine = sz;
  38. ShellExecute(hwndParent, NULL, pszCmdLine, NULL, NULL,
  39. nShowCmd);
  40. }
  41. extern "C" void WINAPI MailToProtocolHandler(HWND hwndParent, HINSTANCE hinst,
  42. PSTR pszCmdLine, int nShowCmd)
  43. {
  44. char szMAPIDLL[MAX_PATH];
  45. if (GetProfileString(s_cszMAPISection, s_cszMAPIKey, "",
  46. szMAPIDLL, sizeof(szMAPIDLL)) > 0)
  47. {
  48. HINSTANCE hinstMAPI = LoadLibrary(szMAPIDLL);
  49. if (hinstMAPI)
  50. {
  51. MAPISENDMAILPROC MAPISendMailProc = (MAPISENDMAILPROC)GetProcAddress(
  52. hinstMAPI,
  53. s_cszMAPISendMail);
  54. if (MAPISendMailProc)
  55. {
  56. PARSEDURLA pu = {sizeof(pu)};
  57. if (SUCCEEDED(ParseURLA(pszCmdLine, &pu)) && URL_SCHEME_MAILTO == pu.nScheme)
  58. {
  59. MapiRecipDescA mapito;
  60. MapiMessage mapimsg;
  61. pszCmdLine = (PSTR) pu.pszSuffix;
  62. ZeroMemory(&mapito, sizeof(mapito));
  63. mapito.ulRecipClass = MAPI_TO;
  64. mapito.lpszName = pszCmdLine;
  65. ZeroMemory(&mapimsg, sizeof(mapimsg));
  66. mapimsg.nRecipCount = 1;
  67. mapimsg.lpRecips = &mapito;
  68. (*MAPISendMailProc)(NULL, 0, &mapimsg,
  69. (MAPI_LOGON_UI | MAPI_DIALOG), 0);
  70. }
  71. }
  72. FreeLibrary(hinstMAPI);
  73. }
  74. }
  75. }
  76. extern "C" void WINAPI NewsProtocolHandler(HWND hwndParent, HINSTANCE hinst,
  77. PSTR pszCmdLine, int nShowCmd)
  78. {
  79. HINSTANCE hinstNews = LoadLibrary(s_cszNewsDLL);
  80. if (hinstNews)
  81. {
  82. RUNDLL32PROC RealNewsProtocolHandler = (RUNDLL32PROC)GetProcAddress(hinstNews, s_cszNewsProtocolHandler);
  83. if (RealNewsProtocolHandler)
  84. {
  85. (*RealNewsProtocolHandler)(hwndParent, hinst, pszCmdLine, nShowCmd);
  86. }
  87. FreeLibrary(hinstNews);
  88. }
  89. }
  90. #ifndef ISSPACE
  91. #define ISSPACE(ch) (((ch) == 32) || ((unsigned)((ch) - 9)) <= 13 - 9)
  92. #endif
  93. #ifndef ISQUOTE
  94. #define ISQUOTE(ch) ((ch) == '\"' || (ch) == '\'')
  95. #endif
  96. void TrimString(PSTR pszTrimMe, PCSTR pszTrimChars)
  97. {
  98. PSTR psz;
  99. PSTR pszStartMeat;
  100. if ( !pszTrimMe )
  101. return;
  102. /* Trim leading characters. */
  103. psz = pszTrimMe;
  104. while (*psz && StrChr(pszTrimChars, *psz))
  105. psz = CharNext(psz);
  106. pszStartMeat = psz;
  107. /* Trim trailing characters. */
  108. if (*psz)
  109. {
  110. psz += lstrlen(psz);
  111. psz = CharPrev(pszStartMeat, psz);
  112. if (psz > pszStartMeat)
  113. {
  114. while (StrChr(pszTrimChars, *psz))
  115. psz = CharPrev(pszStartMeat, psz);
  116. psz = CharNext(psz);
  117. *psz = '\0';
  118. }
  119. }
  120. /* Relocate stripped string. */
  121. if (pszStartMeat > pszTrimMe)
  122. /* (+ 1) for null terminator. */
  123. MoveMemory(pszTrimMe, pszStartMeat, lstrlen(pszStartMeat) + 1);
  124. return;
  125. }
  126. void TrimSlashes(PSTR pszTrimMe)
  127. {
  128. TrimString(pszTrimMe, "\\/");
  129. /* TrimString() validates pszTrimMe on output. */
  130. return;
  131. }
  132. extern "C" void WINAPI TelnetProtocolHandler(HWND hwndParent, HINSTANCE hinst,
  133. PSTR pszCmdLine, int nShowCmd)
  134. {
  135. HRESULT hr;
  136. char *p;
  137. char *pDest;
  138. BOOL fRemove;
  139. PARSEDURLA pu = {sizeof(pu)};
  140. if (SUCCEEDED(ParseURLA(pszCmdLine, &pu)))
  141. {
  142. if ((URL_SCHEME_TELNET == pu.nScheme)
  143. || (0 == StrCmpNI(pu.pszProtocol, s_cszRLoginProtocolPrefix, pu.cchProtocol))
  144. || (0 == StrCmpNI(pu.pszProtocol, s_cszTN3270ProtocolPrefix, pu.cchProtocol)))
  145. {
  146. pszCmdLine = (PSTR) pu.pszSuffix;
  147. }
  148. }
  149. // Remove leading and trailing slashes.
  150. TrimSlashes(pszCmdLine);
  151. p = StrChr(pszCmdLine, '@');
  152. if (p)
  153. pszCmdLine = p + 1;
  154. // Eliminate double quotes...should be no need for these
  155. // unless trouble is afoot.
  156. for (pDest = p = pszCmdLine; *p; p++)
  157. {
  158. if (!ISQUOTE(*p))
  159. {
  160. *pDest = *p;
  161. pDest++;
  162. }
  163. }
  164. *pDest = '\0';
  165. // For security reasons, strip the filename cmdline option
  166. if (pszCmdLine)
  167. {
  168. for (p = pszCmdLine; *p; p++)
  169. {
  170. // Be careful and don't nuke servernames that start with -f.
  171. // Since hostnames can't start with a dash, ensure previous char is
  172. // whitespace, or we're at the beginning.
  173. //
  174. // Also, -a sends credentials over the wire, so strip it, too.
  175. if ((*p == '/' || *p == '-') &&
  176. (*(p+1) == 'f' || *(p+1) == 'F' || *(p+1) == 'a' || *(p+1) == 'A'))
  177. {
  178. fRemove = TRUE;
  179. if (!((p == pszCmdLine || ISSPACE(*(p-1)) || ISQUOTE(*(p-1)) )))
  180. {
  181. char *pPortChar = p-1;
  182. // Doesn't meet easy criteria, but it might be harder to
  183. // detect, such as site:-ffilename. In this case, consider
  184. // the -f piece unsafe if everything between -f and a colon
  185. // to the left is a digit (no digits will also be unsafe).
  186. // If anything else is hit first, then consider it to
  187. // be part of the hostname. Walking to the beginning
  188. // be considered safe (e.g. "80-ffilename" would be considered
  189. // the hostname).
  190. while (pPortChar >= pszCmdLine && *pPortChar != ':')
  191. {
  192. if (*pPortChar < '0' || *pPortChar > '9')
  193. {
  194. fRemove = FALSE;
  195. break;
  196. }
  197. pPortChar--;
  198. }
  199. if (pPortChar < pszCmdLine)
  200. fRemove = FALSE;
  201. }
  202. if (!fRemove)
  203. continue;
  204. BOOL fQuotedFilename = FALSE;
  205. LPSTR pStart = p;
  206. // move past -f
  207. p+=2;
  208. // Skip over whitespace and filename following -f option
  209. if (*(p-1) == 'f' || *(p-1) == 'F')
  210. {
  211. while (*p && ISSPACE(*p))
  212. p++;
  213. // but wait, it may be a long filename surrounded by quotes
  214. if (ISQUOTE(*p))
  215. {
  216. fQuotedFilename = TRUE;
  217. p++;
  218. }
  219. // Loop until null OR whitespace if not quoted pathname OR quote if a quoted pathname
  220. while (!((*p == '\0') ||
  221. (ISSPACE(*p) && !fQuotedFilename) ||
  222. (ISQUOTE(*p) && fQuotedFilename)))
  223. p++;
  224. }
  225. // phase out the -a and -f options, but keep going to search the rest of the string
  226. memmove((VOID *)pStart, (VOID *)p, strlen(p)+1);
  227. p = pStart-1;
  228. }
  229. }
  230. }
  231. // If a port has been specified, turn ':' into space, which will make the
  232. // port become the second command line argument.
  233. p = StrChr(pszCmdLine, ':');
  234. if (p)
  235. *p = ' ';
  236. ShellExecute(hwndParent, NULL, s_cszTelnetApp, pszCmdLine, NULL , SW_SHOW);
  237. }