hmmapi.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 46k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "pch.hxx"
  2. #include <winuser.h>
  3. #include <hlink.h>
  4. #include <shellapi.h>
  5. #define INITGUID
  6. #include <initguid.h>
  7. #include <exdisp.h>
  8. #include <tchar.h>
  9. #define USENAVIGATE     1
  10. #define USEATTFILE 1
  11. #define USEPOST 0
  12. #define ARRAYSIZE(buf) (sizeof(buf) / sizeof(buf[0]))
  13. HINSTANCE       g_hInstMAPI = NULL;
  14. ////////////////////////////////////////////////////////////////////////
  15. //
  16. //  dll entry point
  17. //
  18. ////////////////////////////////////////////////////////////////////////
  19. STDAPI_(BOOL) APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpRsrvd)
  20. {
  21.     switch (dwReason)
  22. {
  23. case DLL_PROCESS_ATTACH:
  24. g_hInstMAPI = hDll;
  25. break;
  26. case DLL_PROCESS_DETACH:
  27. break;
  28. } // switch
  29.     return(TRUE);
  30. }
  31. BOOL FRunningOnNTEx(LPDWORD pdwVersion)
  32. {
  33.     static BOOL fIsNT = 2 ;
  34.     static DWORD dwVersion = (DWORD)0;
  35.     OSVERSIONINFO VerInfo;
  36.     
  37.     // If we have calculated this before just pass that back.
  38.     // else find it now.
  39.     //
  40.     if (fIsNT == 2)
  41.     {
  42.         VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  43.         
  44.         GetVersionEx(&VerInfo);
  45.         // Also, we don't check for failure on the above call as it
  46.         // should succeed if we are on NT 4.0 or Win 9X!
  47.         //
  48.         fIsNT = (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  49.         if (fIsNT)
  50.             dwVersion = VerInfo.dwMajorVersion;
  51.     }
  52.     if (pdwVersion)
  53.         *pdwVersion = dwVersion;
  54.     
  55.     return fIsNT;
  56. }
  57. // Then next 2 functions are stollen from shlwapi. Needed to modiy them, because
  58. // we had to handle SFN.
  59. // Also there is a bug in the Ansi versin of ExpandEnvironmentStrings, where the
  60. // function returns the number of bytes the string would have if it would be
  61. // UNICODE. Since we have to convert the string anyway to SFN I use lstrlen to 
  62. // get the real length.
  63. //
  64. //  If the given environment variable exists as the first part of the path,
  65. //  then the environment variable is inserted into the output buffer.
  66. //
  67. //  Returns TRUE if pszResult is filled in.
  68. //
  69. //  Example:  Input  -- C:WINNTSYSTEM32FOO.TXT -and- lpEnvVar = %SYSTEMROOT%
  70. //            Output -- %SYSTEMROOT%SYSTEM32FOO.TXT
  71. //
  72. BOOL MyUnExpandEnvironmentString(LPCTSTR pszPath, LPCTSTR pszEnvVar, LPTSTR pszResult, UINT cbResult)
  73. {
  74.     TCHAR szEnvVar[MAX_PATH];
  75.     DWORD dwEnvVar = SHExpandEnvironmentStrings(pszEnvVar, szEnvVar, ARRAYSIZE(szEnvVar));
  76.     if (dwEnvVar)
  77.     {
  78.         // Convert the string to short file name
  79.         GetShortPathName(szEnvVar, szEnvVar, ARRAYSIZE(szEnvVar));
  80.         dwEnvVar = lstrlen(szEnvVar);
  81.         if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, szEnvVar, dwEnvVar, pszPath, dwEnvVar) == 2)
  82.         {
  83.             if (lstrlen(pszPath) - (int)dwEnvVar + lstrlen(pszEnvVar) < (int)cbResult)
  84.             {
  85.                 lstrcpy(pszResult, pszEnvVar);
  86.                 lstrcat(pszResult, pszPath + dwEnvVar);
  87.                 return TRUE;
  88.             }
  89.         }
  90.     }
  91.     return FALSE;
  92. }
  93. // note: %USERPROFILE% is relative to the user making the call, so this does
  94. // not work if we are being impresonated from a service, for example
  95. // dawrin installs apps from the system process this way
  96. STDAPI_(BOOL) MyPathUnExpandEnvStrings(LPCTSTR pszPath, LPTSTR pszBuf, UINT cchBuf)
  97. {
  98.     if (pszPath && pszBuf)
  99.     {
  100.         return (MyUnExpandEnvironmentString(pszPath, TEXT("%USERPROFILE%"), pszBuf, cchBuf)       ||
  101.                 MyUnExpandEnvironmentString(pszPath, TEXT("%ALLUSERSPROFILE%"), pszBuf, cchBuf)   ||
  102.                 MyUnExpandEnvironmentString(pszPath, TEXT("%ProgramFiles%"), pszBuf, cchBuf)      ||
  103.                 MyUnExpandEnvironmentString(pszPath, TEXT("%SystemRoot%"), pszBuf, cchBuf)        ||
  104.                 MyUnExpandEnvironmentString(pszPath, TEXT("%SystemDrive%"), pszBuf, cchBuf));
  105.     }
  106.     else
  107.     {
  108.         return FALSE;
  109.     }
  110. }
  111. static void GetPostUrl(LPSTR lpszData, DWORD dwSize)
  112. {
  113. HKEY hkDefClient;
  114. HKEY hkClient;
  115. TCHAR szClient[64];
  116. DWORD type;
  117. DWORD dwClientSize = sizeof(TCHAR) * 64;
  118. LONG err = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\Clients\Mail"), &hkClient);
  119. if (err == ERROR_SUCCESS)
  120. {
  121. err = RegQueryValueEx(hkClient, NULL, 0, &type, (LPBYTE)szClient, &dwClientSize);
  122. if (err == ERROR_SUCCESS)
  123. {
  124. err = RegOpenKey(hkClient, szClient, &hkDefClient);
  125. if (err == ERROR_SUCCESS)
  126. {
  127. DWORD type;
  128. err = RegQueryValueEx(hkDefClient, TEXT("posturl"), 0, &type, (LPBYTE)lpszData, &dwSize);
  129. RegCloseKey(hkDefClient);
  130. }
  131. }
  132. RegCloseKey(hkClient);
  133. }
  134. if (err != ERROR_SUCCESS)
  135.     {
  136.         LoadString(g_hInstMAPI, IDS_DEFAULTPOSTURL, lpszData, dwSize);
  137.     }
  138. }
  139. typedef HRESULT (STDAPICALLTYPE DynNavigate)(DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pibsc,
  140.  LPCWSTR pszTargetFrame, LPCWSTR pszUrl, LPCWSTR pszLocation);
  141. typedef DynNavigate FAR *LPDynNavigate;
  142. STDAPI HlinkFrameNavigateNHL(DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pibsc,
  143.  LPCWSTR pszTargetFrame, LPCWSTR pszUrl, LPCWSTR pszLocation)
  144. {
  145. HRESULT hr;
  146.     HINSTANCE   hinst;
  147. LPDynNavigate fpNavigate = NULL;
  148. hinst = LoadLibraryA("SHDOCVW.DLL");
  149.     // If that failed because the module was not be found,
  150.     // then try to find the module in the directory we were
  151.     // loaded from.
  152.     if (!hinst)
  153. goto Error;
  154.     fpNavigate = (LPDynNavigate)GetProcAddress(hinst, "HlinkFrameNavigateNHL");
  155.     if (!fpNavigate)
  156. goto Error;
  157.     hr = fpNavigate(grfHLNF, pbc, pibsc, pszTargetFrame, pszUrl, pszLocation);
  158. FreeLibrary(hinst);
  159. return hr;
  160. Error:
  161.     return GetLastError();
  162. }
  163. static void SimpleNavigate(LPTSTR lpszUrl, BOOL bUseFrame = false)
  164. {
  165.     DWORD cch = (lstrlen(lpszUrl) + 1);
  166. LPWSTR pwszData = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(WCHAR));
  167.     if (pwszData)
  168.     {
  169.         SHTCharToUnicode(lpszUrl, pwszData, cch);
  170.         if (bUseFrame)
  171.             HlinkFrameNavigateNHL(HLNF_OPENINNEWWINDOW, NULL, NULL, NULL, pwszData, NULL);
  172.         else
  173.             HlinkSimpleNavigateToString(pwszData, NULL, NULL, NULL, NULL, NULL, 0, 0);
  174.         HeapFree(GetProcessHeap(), 0, (LPVOID)pwszData);
  175.     }
  176. }
  177. // Pack some data into a SAFEARRAY of BYTEs. Return in a VARIANT
  178. static HRESULT GetPostData(LPVARIANT pvPostData, LPTSTR lpszData)
  179. {
  180. HRESULT hr;
  181. LPSAFEARRAY psa;
  182. UINT cElems = lstrlen(lpszData);
  183. LPSTR pPostData;
  184. if (!pvPostData)
  185. return E_POINTER;
  186. VariantInit(pvPostData);
  187. psa = SafeArrayCreateVector(VT_UI1, 0, cElems);
  188. if (!psa)
  189. return E_OUTOFMEMORY;
  190. hr = SafeArrayAccessData(psa, (LPVOID*)&pPostData);
  191. memcpy(pPostData, lpszData, cElems);
  192. hr = SafeArrayUnaccessData(psa);
  193. V_VT(pvPostData) = VT_ARRAY | VT_UI1;
  194. V_ARRAY(pvPostData) = psa;
  195. return NOERROR;
  196. }
  197. static void DoNavigate(LPTSTR lpszUrl, LPTSTR lpszData, BOOL bPlainIntf = TRUE)
  198. {
  199. HRESULT hr;
  200. IWebBrowser2* pWBApp = NULL; // Derived from IWebBrowser
  201. BSTR bstrURL = NULL, bstrHeaders = NULL;
  202. VARIANT vFlags = {0};
  203. VARIANT vTargetFrameName = {0};
  204. VARIANT vPostData = {0};
  205. VARIANT vHeaders = {0};
  206. LPWSTR pwszData = NULL;
  207. LPTSTR pszUrl = NULL;
  208.     DWORD cch;
  209. if (FAILED(hr = CoInitialize(NULL)))
  210. return;
  211. if (FAILED(hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER, IID_IWebBrowser2, (LPVOID*)&pWBApp)))
  212. goto Error;
  213. #if USEPOST
  214.     cch = lstrlen(lpszUrl) + 1;
  215. pwszData = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(WCHAR));
  216. if (!pwszData)
  217. goto Error;
  218.     SHTCharToUnicode(lpszUrl, pwszData, cch);
  219. bstrURL = SysAllocString(pwszData);
  220. HeapFree(GetProcessHeap(), 0, (LPVOID)pwszData);
  221. if (!bstrURL)
  222. goto Error;
  223. bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencodedrn");
  224. if (!bstrHeaders)
  225. goto Error;
  226. V_VT(&vHeaders) = VT_BSTR;
  227. V_BSTR(&vHeaders) = bstrHeaders;
  228. hr = GetPostData(&vPostData, lpszData);
  229. hr = pWBApp->Navigate(bstrURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
  230. #else
  231.     cch = lstrlen(lpszUrl) + lstrlen(lpszData) + 2;
  232. pszUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(TCHAR));
  233. if (!pszUrl)
  234. goto Error;
  235. lstrcpy(pszUrl, lpszUrl);
  236. lstrcat(pszUrl, "?");
  237. lstrcat(pszUrl, lpszData);
  238. cch = lstrlen(pszUrl) + 1;
  239. pwszData = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(WCHAR));
  240. if (!pwszData)
  241. {
  242. HeapFree(GetProcessHeap(), 0, (LPVOID)pszUrl);
  243. goto Error;
  244. }
  245.     SHTCharToUnicode(pszUrl, pwszData, cch);
  246. HeapFree(GetProcessHeap(), 0, (LPVOID)pszUrl);
  247. bstrURL = SysAllocString(pwszData);
  248. HeapFree(GetProcessHeap(), 0, (LPVOID)pwszData);
  249. if (!bstrURL)
  250. goto Error;
  251. hr = pWBApp->Navigate(bstrURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
  252. #endif
  253. if (bPlainIntf)
  254. {
  255. pWBApp->put_AddressBar(VARIANT_FALSE);
  256. pWBApp->put_MenuBar(VARIANT_FALSE);
  257. pWBApp->put_ToolBar(VARIANT_FALSE);
  258. }
  259. pWBApp->put_Visible(VARIANT_TRUE);
  260. Error:
  261. if (bstrURL)
  262. SysFreeString(bstrURL);
  263. if (bstrHeaders)
  264. SysFreeString(bstrHeaders);
  265. VariantClear(&vPostData);
  266. if (pWBApp)
  267. pWBApp->Release();
  268. CoUninitialize();
  269. }
  270. // Helpers for Form Submit - copied from IE3 and modified approriately
  271. //
  272. static char x_hex_digit(int c)
  273. {
  274.     if (c >= 0 && c <= 9)
  275.     {
  276. return c + '0';
  277.     }
  278.     if (c >= 10 && c <= 15)
  279.     {
  280. return c - 10 + 'A';
  281.     }
  282.     return '0';
  283. }
  284. static const unsigned char isAcceptable[96] =
  285. /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
  286. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0,    /* 2x   !"#$%&'()*+,-./  */
  287.  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,    /* 3x  0123456789:;<=>?  */
  288.  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    /* 4x  @ABCDEFGHIJKLMNO  */
  289.  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,    /* 5x  PQRSTUVWXYZ[]^_  */
  290.  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    /* 6x  `abcdefghijklmno  */
  291.  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};   /* 7x  pqrstuvwxyz{}~  DEL */
  292. // Performs URL-encoding of null-terminated strings. Pass NULL in pbOut
  293. // to find buffer length required. Note that '' is not written out.
  294. // 2/9/99  cchLimit param added for safety -- no more than cchLimit chars are
  295. // written out.  If pbOut is NULL then cchLimit is ignored.  If the caller uses 
  296. // the style Buffer[URLEncode(Buffer, ...)] = 0, then cchLimit should be the 
  297. // buffer size minus one.
  298.    
  299. int
  300. URLEncode(LPTSTR pbOut, const char * pchIn, const int cchLimit)
  301. {
  302.     int     lenOut = 0;
  303.     char *  pchOut = (char *)pbOut;
  304.     for (; *pchIn && (!pchOut || lenOut < cchLimit); pchIn++, lenOut++)
  305.     {
  306.         if (*pchIn == ' ')
  307.         {
  308.             if (pchOut)
  309.                 *pchOut++ = '+';
  310.         }
  311.         else if (*pchIn >= 32 && *pchIn <= 127 && isAcceptable[*pchIn - 32])
  312.         {
  313.             if (pchOut)
  314.                 *pchOut++ = (TCHAR)*pchIn;
  315.         }
  316.         else
  317.         {
  318.             if (pchOut) 
  319.             {
  320.                 if (lenOut <= cchLimit - 3)
  321.                 {
  322.                     // enough room for this encoding
  323.                     *pchOut++ = '%';
  324.                     *pchOut++ = x_hex_digit((*pchIn >> 4) & 0xf);
  325.                     *pchOut++ = x_hex_digit(*pchIn & 0xf);
  326.                     lenOut += 2; 
  327.                 }
  328.                 else
  329.                     return lenOut;
  330.             }
  331.             else
  332.                 lenOut += 2; // for expression handles 3rd inc  
  333.         }
  334.     }
  335.     return lenOut;
  336. }
  337. ///////////////////////////////////////////////////////////////////////
  338. //
  339. // MAPILogon
  340. //
  341. ///////////////////////////////////////////////////////////////////////
  342. ULONG FAR PASCAL MAPILogon(ULONG ulUIParam,
  343.    LPSTR lpszProfileName,
  344.    LPSTR lpszPassword,
  345.    FLAGS flFlags,
  346.    ULONG ulReserved,
  347.    LPLHANDLE lplhSession)
  348. {
  349. *lplhSession = 1;
  350. return SUCCESS_SUCCESS;
  351. }
  352. ///////////////////////////////////////////////////////////////////////
  353. //
  354. // MAPILogoff
  355. //
  356. ///////////////////////////////////////////////////////////////////////
  357. ULONG FAR PASCAL MAPILogoff(LHANDLE lhSession,
  358.     ULONG ulUIParam,
  359.     FLAGS flFlags,
  360.     ULONG ulReserved)
  361. {
  362. return SUCCESS_SUCCESS;
  363. }
  364. ///////////////////////////////////////////////////////////////////////
  365. //
  366. // MAPIFreeBuffer
  367. //
  368. ///////////////////////////////////////////////////////////////////////
  369. ULONG FAR PASCAL MAPIFreeBuffer(LPVOID lpv)
  370. {
  371. return MAPI_E_FAILURE;
  372. }
  373. ///////////////////////////////////////////////////////////////////////
  374. //
  375. // MAPISendMail
  376. //
  377. ///////////////////////////////////////////////////////////////////////
  378. ULONG FAR PASCAL MAPISendMail(LHANDLE lhSession,          
  379.                   ULONG ulUIParam,
  380.                   lpMapiMessage lpMessage,
  381.                   FLAGS flFlags,
  382.                   ULONG ulReserved)
  383. {
  384.     TCHAR szUrl[256];
  385.     GetPostUrl(szUrl, sizeof(TCHAR) * 256);
  386.     
  387.     // Calculate the buffer size needed to create the url
  388.     ULONG i;
  389. #if USENAVIGATE
  390.     DWORD dwUrlSize = 32; // "?action=compose" + slop
  391. #else
  392.     DWORD dwUrlSize = lstrlen(szUrl) + 32; // "?action=compose" + slop
  393. #endif
  394.     DWORD dwMaxSize = 0;
  395.     DWORD dwSize;
  396.     DWORD dwFileSizes = 0;
  397.     HANDLE hFile;
  398.     if (lpMessage->lpszSubject)
  399.     {
  400.         dwSize = URLEncode(NULL, lpMessage->lpszSubject, 0);
  401.         dwMaxSize = max(dwMaxSize, dwSize + 1);
  402.         dwUrlSize += dwMaxSize + 9; // "&subject=%s"
  403.     }
  404.     if (lpMessage->lpszNoteText)
  405.     {
  406.         dwSize = URLEncode(NULL, lpMessage->lpszNoteText, 0);
  407.         dwMaxSize = max(dwMaxSize, dwSize + 1);
  408.         dwUrlSize += dwSize + 6; // "&body=%s"
  409.     }
  410.     for (i = 0; i < lpMessage->nRecipCount; i++)
  411.     {
  412.         dwSize = URLEncode(NULL, lpMessage->lpRecips[i].lpszName, 0);
  413.         dwMaxSize = max(dwMaxSize, dwSize + 1);
  414.         dwUrlSize += dwSize + 4; // "&to=%s" || "&cc=%s"
  415.         if (lpMessage->lpRecips[i].ulRecipClass == MAPI_BCC)
  416.             dwUrlSize++; // extra character for bcc
  417.     }
  418.     if (lpMessage->nFileCount)
  419.     {
  420.         dwUrlSize += 14; // "&filecount=xxx"
  421.         for (i = 0; i < lpMessage->nFileCount; i++)
  422.         {
  423.             if (!lpMessage->lpFiles[i].lpszPathName)
  424.                 continue;
  425.             TCHAR szFileSize[32];
  426.             hFile = CreateFile(lpMessage->lpFiles[i].lpszPathName, 0 /*GENERIC_READ*/, 0 /*FILE_SHARE_READ*/, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  427.             if (hFile == INVALID_HANDLE_VALUE)
  428.             {
  429.                 LPVOID lpMsgBuf;
  430.                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
  431.                 MessageBox(NULL, (char*)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
  432.                 LocalFree(lpMsgBuf);
  433.                 continue;
  434.             }
  435.             dwSize = GetFileSize(hFile, NULL);
  436.             CloseHandle(hFile);
  437.             if (dwSize == -1)
  438.                 continue;
  439.             dwFileSizes += dwSize;
  440.             wnsprintf(szFileSize, ARRAYSIZE(szFileSize), "&size%d=%d", i, dwSize);
  441.             dwSize = lstrlen(szFileSize);
  442.             dwMaxSize = max(dwMaxSize, dwSize + 1);
  443.             dwUrlSize += dwSize;
  444.             dwSize = URLEncode(NULL, lpMessage->lpFiles[i].lpszPathName, 0) + 4;    // in case we need to append a ^
  445.             dwMaxSize = max(dwMaxSize, dwSize + 1);
  446.             dwUrlSize += dwSize + 9; // "&pathxxx=%s"
  447.             if (lpMessage->lpFiles[i].lpszFileName)
  448.             {
  449.                 dwSize = URLEncode(NULL, lpMessage->lpFiles[i].lpszFileName, 0);
  450.                 dwMaxSize = max(dwMaxSize, dwSize + 1);
  451.                 dwUrlSize += dwSize + 9; // "&filexxx=%s"
  452.             }
  453. #if USEATTFILE
  454.             else 
  455.             {
  456.                 // ATTFILE code further down just tacks on the path when lpszFileName is NULL
  457.                 dwUrlSize += URLEncode(NULL, lpMessage->lpFiles[i].lpszPathName, 0) + 4;
  458.             }
  459. #endif
  460.         }
  461.     }
  462. #if USEATTFILE
  463.     dwSize = ARRAYSIZE("&attfile=") + (URLEncode(NULL, "::", 0) * lpMessage->nFileCount * 3);
  464. #else
  465.     dwSize = ARRAYSIZE("&filecount=xxx");
  466. #endif
  467.     dwMaxSize = max(dwMaxSize, dwSize + 1);
  468.     dwUrlSize += dwSize;
  469.     LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwUrlSize * sizeof(TCHAR));
  470.     if (!pszData)
  471.         return MAPI_E_FAILURE;
  472.     LPTSTR pszBuf = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwMaxSize * sizeof(TCHAR));
  473.     if (!pszBuf) 
  474.     {
  475.         HeapFree(GetProcessHeap(), 0, (LPVOID) pszData);
  476.         return MAPI_E_FAILURE;
  477.     }
  478.     // Build the URL
  479. #if USENAVIGATE
  480.     lstrcpyn(pszData, "action=compose", dwUrlSize);
  481. #else
  482.     wnsprintf(pszData, dwUrlSize, "%s?action=compose", szUrl);
  483. #endif
  484.     for (i = 0; i < lpMessage->nRecipCount; i++)
  485.     {
  486.         switch (lpMessage->lpRecips[i].ulRecipClass)
  487.         {
  488.             case MAPI_TO:
  489.                 StrCatBuff(pszData, "&to=", dwUrlSize);
  490.                 break;
  491.             case MAPI_CC:
  492.                 StrCatBuff(pszData, "&cc=", dwUrlSize);
  493.                 break;
  494.             case MAPI_BCC:
  495.                 StrCatBuff(pszData, "&bcc=", dwUrlSize);
  496.                 break;
  497.         }
  498.         pszBuf[URLEncode(pszBuf, lpMessage->lpRecips[i].lpszName, dwMaxSize-1)] = 0;
  499.         StrCatBuff(pszData, pszBuf, dwUrlSize);
  500.     }
  501.     if (lpMessage->lpszSubject)
  502.     {
  503.         StrCatBuff(pszData, "&subject=", dwUrlSize);
  504.         pszBuf[URLEncode(pszBuf, lpMessage->lpszSubject, dwMaxSize-1)] = 0;
  505.         StrCatBuff(pszData, pszBuf, dwUrlSize);
  506.     }
  507.     if (lpMessage->lpszNoteText)
  508.     {
  509.         StrCatBuff(pszData, "&body=", dwUrlSize);
  510.         pszBuf[URLEncode(pszBuf, lpMessage->lpszNoteText, dwMaxSize-1)] = 0;
  511.         StrCatBuff(pszData, pszBuf, dwUrlSize);
  512.     }
  513.     if (lpMessage->nFileCount)
  514.     {
  515. #if USEATTFILE
  516.         TCHAR szSep[32];
  517.         TCHAR szPath[MAX_PATH];
  518.         TCHAR szTemp[MAX_PATH];
  519.         GetTempPath(MAX_PATH - 1, szTemp);
  520.         BOOL bIsTemp;
  521.         StrCatBuff(pszData, "&attfile=", dwUrlSize);
  522. #else
  523.         wnsprintf(pszBuf, dwMaxSize, "&filecount=%d", lpMessage->nFileCount);
  524.         StrCatBuff(pszData, pszBuf, dwUrlSize);
  525. #endif
  526.         for (i = 0; i < lpMessage->nFileCount; i++)
  527.         {
  528.             if (!lpMessage->lpFiles[i].lpszPathName)
  529.                 continue;
  530.             bIsTemp = FALSE;
  531.             lstrcpyn(szPath, lpMessage->lpFiles[i].lpszPathName, ARRAYSIZE(szPath));
  532.             hFile = CreateFile(szPath, 0, 0 /*GENERIC_READ, FILE_SHARE_READ*/, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  533.             if (hFile == INVALID_HANDLE_VALUE)
  534.                 continue;
  535.             dwSize = GetFileSize(hFile, NULL);
  536.             // Handle the case where this is a temporary file
  537.             if (CompareString(LOCALE_SYSTEM_DEFAULT, 0, szTemp, lstrlen(szTemp), szPath, lstrlen(szTemp)) == CSTR_EQUAL)
  538.             {
  539.                 // If the file was created in the last 2 seconds assume that it is really temporary
  540.                 FILETIME ftLastWrite, ftSystem;
  541.                 LARGE_INTEGER liLastWrite, liSystem;
  542.                 if (GetFileTime(hFile, NULL, NULL, &ftLastWrite))
  543.                 {
  544.                     GetSystemTimeAsFileTime(&ftSystem);
  545.                     liLastWrite.LowPart = ftLastWrite.dwLowDateTime;
  546.                     liLastWrite.HighPart = ftLastWrite.dwHighDateTime;
  547.                     liSystem.LowPart = ftSystem.dwLowDateTime;
  548.                     liSystem.HighPart = ftSystem.dwHighDateTime;
  549.                     //jeffif (liLastWrite.QuadPart - liSystem.QuadPart < 30000000L)
  550.                         bIsTemp = TRUE;
  551.                 }
  552.             }
  553.             CloseHandle(hFile);
  554.             if (dwSize == -1)
  555.                 continue;
  556.             if (bIsTemp)
  557.             {
  558.                 StrCatBuff(szPath, "^", ARRAYSIZE(szPath));
  559.                 MoveFile(lpMessage->lpFiles[i].lpszPathName, szPath);
  560.                 SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);
  561.             }
  562. #if USEATTFILE
  563.             szSep[URLEncode(szSep, "::", ARRAYSIZE(szSep)-1)] = 0;
  564.             pszBuf[URLEncode(pszBuf, szPath, dwMaxSize-1)] = 0;
  565.             StrCatBuff(pszData, pszBuf, dwUrlSize);
  566.             StrCatBuff(pszData, szSep, dwUrlSize);
  567.             if (lpMessage->lpFiles[i].lpszFileName)
  568.             {
  569.                 pszBuf[URLEncode(pszBuf, lpMessage->lpFiles[i].lpszFileName, dwMaxSize-1)] = 0;
  570.                 StrCatBuff(pszData, pszBuf, dwUrlSize);
  571.             }
  572.             else
  573.                 StrCatBuff(pszData, pszBuf, dwUrlSize);
  574.             StrCatBuff(pszData, szSep, dwUrlSize);
  575.             wnsprintf(szSep, ARRAYSIZE(szSep), "^%d;", dwSize);
  576.             pszBuf[URLEncode(pszBuf, szSep, dwMaxSize-1)] = 0;
  577.             StrCatBuff(pszData, pszBuf, dwUrlSize);
  578. #else
  579.             wnsprintf(pszBuf, dwMaxSize, "&size%d=%d", i, dwSize);
  580.             StrCatBuff(pszData, pszBuf, dwUrlSize);
  581.             wnsprintf(pszBuf, dwMaxSize, "&path%d=", i);
  582.             StrCatBuff(pszData, pszBuf, dwUrlSize);
  583.             pszBuf[URLEncode(pszBuf, szPath, dwMaxSize-1)] = 0;
  584.             StrCatBuff(pszData, pszBuf, dwUrlSize);
  585.             if (lpMessage->lpFiles[i].lpszFileName)
  586.             {
  587.                 wnsprintf(pszBuf, dwMaxSize-1, "&file%d=", i);
  588.                 StrCatBuff(pszData, pszBuf, dwUrlSize);
  589.                 pszBuf[URLEncode(pszBuf, lpMessage->lpFiles[i].lpszFileName, dwMaxSize-1)] = 0;
  590.                 StrCatBuff(pszData, pszBuf, dwUrlSize);
  591.             }
  592. #endif
  593.         }
  594.     }
  595.     HeapFree(GetProcessHeap(), 0, (LPVOID)pszBuf);
  596. #if USENAVIGATE
  597.     DoNavigate(szUrl, pszData, FALSE);
  598. #else
  599.     SimpleNavigate(pszData, TRUE);
  600. #endif
  601.     HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
  602.     return SUCCESS_SUCCESS;
  603. }
  604. ///////////////////////////////////////////////////////////////////////
  605. //
  606. // MAPISendDocuments
  607. //
  608. ///////////////////////////////////////////////////////////////////////
  609. ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam,
  610.    LPSTR lpszDelimChar,
  611.    LPSTR lpszFullPaths,
  612.    LPSTR lpszFileNames,
  613.    ULONG ulReserved)
  614. {
  615. return MAPI_E_FAILURE;
  616. }
  617. ///////////////////////////////////////////////////////////////////////
  618. //
  619. // MAPIAddress
  620. //
  621. ///////////////////////////////////////////////////////////////////////
  622. ULONG FAR PASCAL MAPIAddress(LHANDLE lhSession,
  623.      ULONG ulUIParam,
  624.      LPTSTR lpszCaption,
  625.      ULONG nEditFields,
  626.      LPTSTR lpszLabels,
  627.      ULONG nRecips,
  628.      lpMapiRecipDesc lpRecips,
  629.      FLAGS flFlags,
  630.      ULONG ulReserved,
  631.      LPULONG lpnNewRecips,
  632.      lpMapiRecipDesc FAR * lppNewRecips)
  633. {
  634. return MAPI_E_FAILURE;
  635. }
  636. ///////////////////////////////////////////////////////////////////////
  637. //
  638. // MAPIDetails
  639. //
  640. ///////////////////////////////////////////////////////////////////////
  641. ULONG FAR PASCAL MAPIDetails(LHANDLE lhSession,
  642.      ULONG ulUIParam,
  643.      lpMapiRecipDesc lpRecip,
  644.      FLAGS flFlags,
  645.      ULONG ulReserved)
  646. {
  647. return MAPI_E_FAILURE;
  648. }
  649. ///////////////////////////////////////////////////////////////////////
  650. //
  651. // MAPIResolveName
  652. //
  653. ///////////////////////////////////////////////////////////////////////
  654. ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession,
  655.  ULONG ulUIParam,
  656.  LPSTR lpszName,
  657.  FLAGS flFlags,
  658.  ULONG ulReserved,
  659.  lpMapiRecipDesc FAR *lppRecip)
  660. {
  661. return MAPI_E_FAILURE;
  662. }
  663. ///////////////////////////////////////////////////////////////////////
  664. //
  665. // MAPIFindNext
  666. //
  667. ///////////////////////////////////////////////////////////////////////
  668. ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession,
  669.       ULONG ulUIParam,
  670.       LPSTR lpszMessageType,
  671.       LPSTR lpszSeedMessageID,
  672.       FLAGS flFlags,
  673.       ULONG ulReserved,
  674.       LPSTR lpszMessageID)
  675. {
  676. return MAPI_E_FAILURE;
  677. }
  678. ///////////////////////////////////////////////////////////////////////
  679. //
  680. // MAPIReadMail
  681. //
  682. ///////////////////////////////////////////////////////////////////////
  683. ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession,
  684.       ULONG ulUIParam,
  685.       LPSTR lpszMessageID,
  686.       FLAGS flFlags,
  687.       ULONG ulReserved,
  688.       lpMapiMessage FAR *lppMessage)
  689. {
  690. return MAPI_E_FAILURE;
  691. }
  692. ///////////////////////////////////////////////////////////////////////
  693. //
  694. // MAPISaveMail
  695. //
  696. ///////////////////////////////////////////////////////////////////////
  697. ULONG FAR PASCAL MAPISaveMail(LHANDLE lhSession,
  698.       ULONG ulUIParam,
  699.       lpMapiMessage lpMessage,
  700.       FLAGS flFlags,
  701.       ULONG ulReserved,
  702.       LPSTR lpszMessageID)
  703. {
  704. return MAPI_E_FAILURE;
  705. }
  706. ///////////////////////////////////////////////////////////////////////
  707. //
  708. // MAPIDeleteMail
  709. //
  710. ///////////////////////////////////////////////////////////////////////
  711. ULONG FAR PASCAL MAPIDeleteMail(LHANDLE lhSession,
  712. ULONG ulUIParam,
  713. LPSTR lpszMessageID,
  714. FLAGS flFlags,
  715. ULONG ulReserved)
  716. {
  717. return MAPI_E_FAILURE;
  718. }
  719. ///////////////////////////////////////////////////////////////////////
  720. //
  721. // BMAPISendMail
  722. //
  723. ///////////////////////////////////////////////////////////////////////
  724. BMAPI_ENTRY BMAPISendMail (LHANDLE                      hSession,
  725.    ULONG                        ulUIParam,
  726.    LPVB_MESSAGE         lpM,
  727.    LPSAFEARRAY *        lppsaRecips,
  728.    LPSAFEARRAY *        lppsaFiles,
  729.    ULONG                        flFlags,
  730.    ULONG                        ulReserved)
  731. {
  732. return MAPI_E_FAILURE;
  733. }
  734. ///////////////////////////////////////////////////////////////////////
  735. //
  736. // BMAPIFindNext
  737. //
  738. ///////////////////////////////////////////////////////////////////////
  739. BMAPI_ENTRY BMAPIFindNext( LHANDLE      hSession,       // Session
  740.    ULONG        ulUIParam,      // UIParam
  741.    BSTR *       lpbstrType,     // MessageType
  742.    BSTR *       lpbstrSeed,     // Seed message Id
  743.    ULONG        flFlags,        // Flags
  744.    ULONG        ulReserved,     // Reserved
  745.    BSTR *       lpbstrId) 
  746. {
  747. return MAPI_E_FAILURE;
  748. }
  749. ///////////////////////////////////////////////////////////////////////
  750. //
  751. // BMAPIReadMail
  752. //
  753. ///////////////////////////////////////////////////////////////////////
  754. BMAPI_ENTRY BMAPIReadMail( LPULONG      lpulMessage,    // pointer to output data (out)
  755.    LPULONG      nRecips,        // number of recipients (out)
  756.    LPULONG      nFiles,         // number of file attachments (out)
  757.    LHANDLE      hSession,       // Session
  758.    ULONG        ulUIParam,      // UIParam
  759.    BSTR *       lpbstrID,       // Message Id
  760.    ULONG        flFlags,        // Flags
  761.    ULONG        ulReserved )    // Reserved
  762. {
  763. return MAPI_E_FAILURE;
  764. }
  765. ///////////////////////////////////////////////////////////////////////
  766. //
  767. // BMAPIGetReadMail
  768. //
  769. ///////////////////////////////////////////////////////////////////////
  770. BMAPI_ENTRY BMAPIGetReadMail( ULONG             lpMessage,       // Pointer to MAPI Mail
  771.       LPVB_MESSAGE      lpvbMessage, // Pointer to VB Message Buffer (out)
  772.       LPSAFEARRAY * lppsaRecips, // Pointer to VB Recipient Buffer (out)
  773.       LPSAFEARRAY * lppsaFiles,  // Pointer to VB File attachment Buffer (out)
  774.       LPVB_RECIPIENT lpvbOrig)   // Pointer to VB Originator Buffer (out)
  775. {
  776. return MAPI_E_FAILURE;
  777. }
  778. ///////////////////////////////////////////////////////////////////////
  779. //
  780. // BMAPISaveMail
  781. //
  782. ///////////////////////////////////////////////////////////////////////
  783. BMAPI_ENTRY BMAPISaveMail( LHANDLE                      hSession,       // Session
  784.    ULONG                        ulUIParam,      // UIParam
  785.    LPVB_MESSAGE         lpM,            // Pointer to VB Message Buffer
  786.    LPSAFEARRAY *        lppsaRecips,    // Pointer to VB Recipient Buffer
  787.    LPSAFEARRAY *        lppsaFiles,     // Pointer to VB File Attacment Buffer
  788.    ULONG                        flFlags,        // Flags
  789.    ULONG                        ulReserved,     // Reserved
  790.    BSTR *                       lpbstrID)       // Message ID
  791. {
  792. return MAPI_E_FAILURE;
  793. }
  794. ///////////////////////////////////////////////////////////////////////
  795. //
  796. // BMAPIAddress
  797. //
  798. ///////////////////////////////////////////////////////////////////////
  799. BMAPI_ENTRY BMAPIAddress( LPULONG                       lpulRecip,       // Pointer to New Recipient Buffer (out)
  800.   LHANDLE                       hSession,        // Session
  801.   ULONG                         ulUIParam,       // UIParam
  802.   BSTR *                        lpbstrCaption,   // Caption string
  803.   ULONG                         ulEditFields,    // Number of Edit Controls
  804.   BSTR *                        lpbstrLabel,     // Label string
  805.   LPULONG                       lpulRecipients,  // Pointer to number of Recipients (in/out)
  806.   LPSAFEARRAY *         lppsaRecip,      // Pointer to Initial Recipients VB_RECIPIENT
  807.   ULONG                         ulFlags,         // Flags
  808.   ULONG                         ulReserved )     // Reserved
  809. {
  810. return MAPI_E_FAILURE;
  811. }
  812. ///////////////////////////////////////////////////////////////////////
  813. //
  814. // BMAPIGetAddress
  815. //
  816. ///////////////////////////////////////////////////////////////////////
  817. BMAPI_ENTRY BMAPIGetAddress (ULONG                      ulRecipientData, // Pointer to recipient data
  818.      ULONG                      cRecipients,     // Number of recipients
  819.  LPSAFEARRAY *  lppsaRecips )    // VB recipient array
  820. {
  821. return MAPI_E_FAILURE;
  822. }
  823. ///////////////////////////////////////////////////////////////////////
  824. //
  825. // BMAPIDetails
  826. //
  827. ///////////////////////////////////////////////////////////////////////
  828. BMAPI_ENTRY BMAPIDetails (LHANDLE                       hSession,   // Session
  829.   ULONG                         ulUIParam,      // UIParam
  830.   LPVB_RECIPIENT        lpVB,           // Pointer to VB recipient stucture
  831.   ULONG                         ulFlags,    // Flags
  832.   ULONG                         ulReserved) // Reserved
  833. {
  834. return MAPI_E_FAILURE;
  835. }
  836. ///////////////////////////////////////////////////////////////////////
  837. //
  838. // BMAPIResolveName
  839. //
  840. ///////////////////////////////////////////////////////////////////////
  841. BMAPI_ENTRY BMAPIResolveName (LHANDLE                   hSession,     // Session
  842.       ULONG                     ulUIParam,    // UIParam
  843.       BSTR                              bstrMapiName, // Name to be resolved
  844.       ULONG                     ulFlags,      // Flags
  845.       ULONG                     ulReserved,   // Reserved
  846.       LPVB_RECIPIENT    lpVB)             // Pointer to VB recipient structure (out)
  847. {
  848. return MAPI_E_FAILURE;
  849. }
  850. ///////////////////////////////////////////////////////////////////////
  851. //
  852. // MailToProtocolHandler
  853. //
  854. ///////////////////////////////////////////////////////////////////////
  855. void CALLBACK MailToProtocolHandler(HWND      hwnd,
  856.     HINSTANCE hinst,
  857. LPSTR     lpszCmdLine,
  858. int       nCmdShow)
  859. {
  860. TCHAR pszUrl[256];
  861. GetPostUrl(pszUrl, sizeof(TCHAR) * 256);
  862. #if USENAVIGATE
  863. LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlen(lpszCmdLine) + 32) * sizeof(TCHAR));
  864. wsprintf(pszData, "action=compose&to=%s", &lpszCmdLine[7]);
  865. // Convert the extraneous '?' to '&'
  866. for (LPTSTR p = pszData; *p; p++)
  867. if (*p == '?')
  868. *p = '&';
  869. DoNavigate(pszUrl, pszData, FALSE);
  870. HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
  871. #else
  872. LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlen(lpszCmdLine) + lstrlen(pszUrl) + 32) * sizeof(TCHAR));
  873. wsprintf(pszData, "%s?action=compose&to=%s", pszUrl, &lpszCmdLine[7]);
  874. // Convert the extraneous '?' to '&'
  875. for (LPTSTR p = &pszData[lstrlen(pszUrl) + 1]; *p; p++)
  876. if (*p == '?')
  877. *p = '&';
  878. SimpleNavigate(pszData);
  879. HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
  880. #endif
  881. }
  882. ///////////////////////////////////////////////////////////////////////
  883. //
  884. // OpenInboxHandler
  885. //
  886. ///////////////////////////////////////////////////////////////////////
  887. void CALLBACK OpenInboxHandler(HWND      hwnd,
  888.        HINSTANCE hinst,
  889.    LPSTR     lpszCmdLine,
  890.    int       nCmdShow)
  891. {
  892. TCHAR pszUrl[256];
  893. GetPostUrl(pszUrl, sizeof(TCHAR) * 256);
  894. #if USENAVIGATE
  895. DoNavigate(pszUrl, "action=inbox", FALSE);
  896. #else
  897. LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlen(pszUrl) + 32) * sizeof(TCHAR));
  898. wsprintf(pszData, "%s?action=inbox", pszUrl);
  899. SimpleNavigate(pszData);
  900. HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
  901. #endif
  902. }
  903. ///////////////////////////////////////////////////////////////////////
  904. //
  905. // Layout of Registry Usage
  906. //
  907. //
  908. // HKEY_CLASSES_ROOTmailto
  909. // HKEY_CLASSES_ROOTmailtoDefaultIcon
  910. // HKEY_CLASSES_ROOTmailtoshellopencommand
  911. //
  912. // HKEY_LOCAL_MACHINESOFTWAREClientsMail
  913. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmail
  914. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmailProtocolsmailto
  915. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmailProtocolsmailtoDefaultIcon
  916. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmailProtocolsmailtoshellopencommand
  917. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmailshellopencommand
  918. // HKEY_LOCAL_MACHINESOFTWAREClientsMailHotmailbackup
  919. //
  920. ///////////////////////////////////////////////////////////////////////
  921. #define MAILTO          TEXT("mailto")
  922. #define PROTOCOLS       TEXT("Protocols")
  923. #define DEFAULTICON     TEXT("DefaultIcon")
  924. #define COMMAND         TEXT("shell\open\command")
  925. #define MAIL            TEXT("SOFTWARE\Clients\Mail")
  926. #define POSTURL         TEXT("posturl")
  927. #define BACKUP          TEXT("backup")
  928. ///////////////////////////////////////////////////////////////////////
  929. //
  930. // SetRegStringValue
  931. //
  932. ///////////////////////////////////////////////////////////////////////
  933. static LONG SetRegStringValue(HKEY hkKey, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszPath, DWORD dwType)
  934. {
  935.     if (!(dwType == REG_SZ) && !(dwType == REG_EXPAND_SZ))
  936.         return ERROR_INVALID_PARAMETER;
  937. if (lpszPath)
  938. {
  939. TCHAR szValue[MAX_PATH + 32];
  940. wsprintf(szValue, lpszValue, lpszPath);
  941. return RegSetValueEx(hkKey, lpszKey, 0, dwType, (LPBYTE)szValue, (lstrlen(szValue) + 1) * sizeof(TCHAR));
  942. }
  943. return RegSetValueEx(hkKey, lpszKey, 0, dwType, (LPBYTE)lpszValue, (lstrlen(lpszValue) + 1) * sizeof(TCHAR));
  944. }
  945. ///////////////////////////////////////////////////////////////////////
  946. //
  947. // CreateMailToEntries
  948. //
  949. ///////////////////////////////////////////////////////////////////////
  950. static LONG CreateMailToEntries(HKEY hkKey, TCHAR* lpszPath, BOOL fRegExpandSz)
  951. {
  952. LONG err;
  953. HKEY hkMailToProt;
  954. HKEY hkDefaultIcon;
  955. HKEY hkCommand;
  956. err = RegCreateKey(hkKey, MAILTO, &hkMailToProt);
  957. if (err == ERROR_SUCCESS)
  958. {
  959. err = SetRegStringValue(hkMailToProt, NULL, TEXT("URL:MailTo Protocol"), NULL, REG_SZ);
  960. if (err == ERROR_SUCCESS)
  961. {
  962. DWORD editFlags = 2; 
  963. err = RegSetValueEx(hkMailToProt, TEXT("EditFlags"), 0, REG_BINARY, (LPBYTE)&editFlags, sizeof(DWORD));
  964. }
  965. if (err == ERROR_SUCCESS)
  966. err = SetRegStringValue(hkMailToProt, TEXT("URL Protocol"), TEXT(""), NULL, REG_SZ);
  967. if (err == ERROR_SUCCESS)
  968. err = RegCreateKey(hkMailToProt, DEFAULTICON, &hkDefaultIcon);
  969. if (err == ERROR_SUCCESS)
  970. {
  971. err = SetRegStringValue(hkDefaultIcon, NULL, "%s,1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  972. RegCloseKey(hkDefaultIcon);
  973. }
  974. if (err == ERROR_SUCCESS)
  975. err = RegCreateKey(hkMailToProt, COMMAND, &hkCommand);
  976. if (err == ERROR_SUCCESS)
  977. {
  978.             DWORD dwNTVer = 0;
  979.             // BUGBUG: Only the rundll32 on NT5 can handle double quotes around the path
  980.             // Lucky on Win9x and NT4 the epand sz path will never be a long file name and the old
  981.             // rundll32 works, but we cannot have double quotes
  982.             if (FRunningOnNTEx(&dwNTVer) && (dwNTVer >= 5))
  983.             {
  984.                 err = SetRegStringValue(hkCommand, NULL, "rundll32.exe "%s",MailToProtocolHandler %%1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  985.             }
  986.             else
  987.             {
  988.                 err = SetRegStringValue(hkCommand, NULL, "rundll32.exe %s,MailToProtocolHandler %%1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  989.             }
  990. RegCloseKey(hkCommand);
  991. }
  992. RegCloseKey(hkMailToProt);
  993. }
  994. return err;
  995. }
  996. ///////////////////////////////////////////////////////////////////////
  997. //
  998. // DoAddService
  999. //
  1000. ///////////////////////////////////////////////////////////////////////
  1001. STDAPI DoAddService(LPSTR lpszService, LPSTR lpszPostURL)
  1002. {
  1003. LONG err;
  1004.     TCHAR szLongPath[MAX_PATH];
  1005.     TCHAR szPath[MAX_PATH];
  1006. HKEY hkClientsMail;
  1007. HKEY hkService;
  1008. HKEY hkProtocols;
  1009. HKEY hkCommand;
  1010. HKEY hkBackup;
  1011.     BOOL fExistingMailClient = FALSE;
  1012.     BOOL fRegExpandSz = FALSE;
  1013.     GetModuleFileName(g_hInstMAPI, szLongPath, MAX_PATH);  // get path to this DLL
  1014.     GetShortPathName(szLongPath, szPath, MAX_PATH);
  1015. // First setup the info for the protocol in clients section
  1016. err = RegCreateKey(HKEY_LOCAL_MACHINE, MAIL, &hkClientsMail);
  1017. if (err == ERROR_SUCCESS)
  1018. {
  1019.         fRegExpandSz = MyPathUnExpandEnvStrings(szPath, szLongPath, ARRAYSIZE(szLongPath));
  1020.         if (fRegExpandSz)
  1021.             lstrcpy(szPath, szLongPath);
  1022. err = RegCreateKey(hkClientsMail, lpszService, &hkService);
  1023. if (err == ERROR_SUCCESS)
  1024. {
  1025. err = SetRegStringValue(hkService, NULL, lpszService, NULL, REG_SZ);
  1026. if (err == ERROR_SUCCESS)
  1027.             {
  1028.                 err = SetRegStringValue(hkService, TEXT("DLLPath"), szPath, NULL,
  1029.                                           fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  1030.             }
  1031. if (err == ERROR_SUCCESS && lpszPostURL && lstrlen(lpszPostURL))
  1032. err = SetRegStringValue(hkService, TEXT("posturl"), lpszPostURL, NULL, REG_SZ);
  1033. if (err == ERROR_SUCCESS)
  1034. err = RegCreateKey(hkService, PROTOCOLS, &hkProtocols);
  1035. if (err == ERROR_SUCCESS)
  1036. {
  1037. err = CreateMailToEntries(hkProtocols, szPath, fRegExpandSz);
  1038. RegCloseKey(hkProtocols);
  1039. }
  1040. if (err == ERROR_SUCCESS)
  1041. err = RegCreateKey(hkService, COMMAND, &hkCommand);
  1042. if (err == ERROR_SUCCESS)
  1043. {
  1044.                 DWORD dwNTVer = 0;
  1045.                 // BUGBUG: Only the rundll32 on NT5 can handle double quotes around the path
  1046.                 // Lucky on Win9x and NT4 the epand sz path will never be a long file name and the old
  1047.                 // rundll32 works, but we cannot have double quotes
  1048.                 if (FRunningOnNTEx(&dwNTVer) && (dwNTVer >= 5))
  1049.                 {
  1050.     err = SetRegStringValue(hkCommand, NULL, "rundll32.exe "%s",OpenInboxHandler", szPath,
  1051.                                             fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  1052.                 }
  1053.                 else
  1054.                 {
  1055.     err = SetRegStringValue(hkCommand, NULL, "rundll32.exe %s,OpenInboxHandler", szPath,
  1056.                                             fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
  1057.                 }
  1058. RegCloseKey(hkCommand);
  1059. }
  1060. if (err == ERROR_SUCCESS)
  1061. err = RegCreateKey(hkService, BACKUP, &hkBackup);
  1062. if (err == ERROR_SUCCESS)
  1063. {
  1064. TCHAR szValue[MAX_PATH];
  1065. DWORD size;
  1066. DWORD type;
  1067. HKEY hkDefaultIcon;
  1068. HKEY hkCommand;
  1069. err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\DefaultIcon"), &hkDefaultIcon);
  1070. if (err == ERROR_SUCCESS)
  1071. {
  1072. size = sizeof(TCHAR) * MAX_PATH;
  1073. err = RegQueryValueEx(hkDefaultIcon, NULL, 0, &type, (LPBYTE)szValue, &size);
  1074. if (err == ERROR_SUCCESS)
  1075. err = RegSetValueEx(hkBackup, DEFAULTICON, 0, type, (LPBYTE)szValue, size);
  1076. RegCloseKey(hkDefaultIcon);
  1077. }
  1078. err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\shell\open\command"), &hkCommand);
  1079. if (err == ERROR_SUCCESS)
  1080. {
  1081. size = sizeof(TCHAR) * MAX_PATH;
  1082. err = RegQueryValueEx(hkCommand, NULL, 0, &type, (LPBYTE)szValue, &size);
  1083. if (err == ERROR_SUCCESS)
  1084.                     {
  1085.                         fExistingMailClient = TRUE;
  1086. err = RegSetValueEx(hkBackup, TEXT("command"), 0, type, (LPBYTE)szValue, size);
  1087.                     }
  1088. RegCloseKey(hkCommand);
  1089. }
  1090. size = sizeof(TCHAR) * MAX_PATH;
  1091. err = RegQueryValueEx(hkClientsMail, NULL, 0, &type, (LPBYTE)szValue, &size);
  1092. if (err == ERROR_SUCCESS)
  1093. err = RegSetValueEx(hkBackup, TEXT("mail"), 0, type, (LPBYTE)szValue, size);
  1094. RegCloseKey(hkBackup);
  1095. }
  1096.     RegCloseKey(hkService);
  1097. }
  1098. if (err == ERROR_SUCCESS && !fExistingMailClient)
  1099. SetRegStringValue(hkClientsMail, NULL, lpszService, NULL, REG_SZ);
  1100.     RegCloseKey(hkClientsMail);
  1101. }
  1102. if (err == ERROR_SUCCESS && !fExistingMailClient)
  1103. err = CreateMailToEntries(HKEY_CLASSES_ROOT, szPath, fRegExpandSz);
  1104.     //
  1105.     // REVIEW Backup fails sometimes. Need to clean up registry changes and 
  1106.     // probably remove all backup registry entirely.
  1107.     // For now just safe to return S_OK
  1108.     // 
  1109. #if 0
  1110.     if (err != ERROR_SUCCESS)
  1111. return HRESULT_FROM_WIN32(err);
  1112. #else
  1113.     return S_OK;
  1114. #endif
  1115. }
  1116. ///////////////////////////////////////////////////////////////////////
  1117. //
  1118. // DeleteKeyAndSubKeys
  1119. //
  1120. ///////////////////////////////////////////////////////////////////////
  1121. static LONG DeleteKeyAndSubKeys(HKEY hkIn, LPCTSTR pszSubKey)
  1122. {
  1123.     HKEY  hk;
  1124.     TCHAR szTmp[MAX_PATH];
  1125.     DWORD dwTmpSize;
  1126.     long  l;
  1127.     int   x;
  1128. l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
  1129. if (l != ERROR_SUCCESS) 
  1130. return l;
  1131.     // loop through all subkeys, blowing them away.
  1132.     //
  1133.     x = 0;
  1134.     while (l == ERROR_SUCCESS)
  1135. {
  1136. dwTmpSize = MAX_PATH;
  1137. l = RegEnumKeyEx(hk, 0, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
  1138. if (l != ERROR_SUCCESS)
  1139.     break;
  1140. l = DeleteKeyAndSubKeys(hk, szTmp);
  1141.     }
  1142.     // there are no subkeys left, [or we'll just generate an error and return FALSE].
  1143.     // let's go blow this dude away.
  1144.     //
  1145. RegCloseKey(hk);
  1146.     return RegDeleteKey(hkIn, pszSubKey);
  1147. }
  1148. ///////////////////////////////////////////////////////////////////////
  1149. //
  1150. // DoRemoveService
  1151. //
  1152. ///////////////////////////////////////////////////////////////////////
  1153. STDAPI DoRemoveService(LPSTR lpszService)
  1154. {
  1155. TCHAR szValue[MAX_PATH];
  1156. DWORD size;
  1157. LONG err;
  1158. DWORD type;
  1159. HKEY hkDefaultIcon;
  1160. HKEY hkCommand;
  1161. HKEY hkBackup;
  1162. HKEY hkService;
  1163. HKEY hkClientsMail;
  1164.     //
  1165. // Restore the previous values if HMMAPI is the current provider
  1166.     //
  1167. err = RegOpenKey(HKEY_LOCAL_MACHINE, MAIL, &hkClientsMail);
  1168. if (err == ERROR_SUCCESS)
  1169. {
  1170.         //
  1171.         // Find the name of the current provider
  1172.         //
  1173.         TCHAR szCurrent[MAX_PATH];
  1174.         DWORD cb = sizeof(szCurrent);
  1175.         err = RegQueryValueEx(hkClientsMail, NULL, NULL, NULL, (LPBYTE)szCurrent, &cb);
  1176.         if (err == ERROR_SUCCESS)
  1177.         {
  1178.             //
  1179.             // Check if it is HMMAPI
  1180.             //
  1181.             if (StrCmp(szCurrent, lpszService) == 0)
  1182.             {
  1183.         err = RegOpenKey(hkClientsMail, lpszService, &hkService);
  1184.         if (err == ERROR_SUCCESS)
  1185.         {
  1186.         err = RegOpenKey(hkService, BACKUP, &hkBackup);
  1187.         if (err == ERROR_SUCCESS)
  1188.         {
  1189.         err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\DefaultIcon"), &hkDefaultIcon);
  1190.         if (err == ERROR_SUCCESS)
  1191.         {
  1192.                             size = sizeof(TCHAR) * MAX_PATH;
  1193.         err = RegQueryValueEx(hkBackup, DEFAULTICON, 0, &type, (LPBYTE)szValue, &size);
  1194.         if (err == ERROR_SUCCESS)
  1195.         err = RegSetValueEx(hkDefaultIcon, NULL, 0, type, (LPBYTE)szValue, size);
  1196.         RegCloseKey(hkDefaultIcon);
  1197.         }
  1198.         err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\shell\open\command"), &hkCommand);
  1199.         if (err == ERROR_SUCCESS)
  1200.         {
  1201.         size = sizeof(TCHAR) * MAX_PATH;
  1202.         err = RegQueryValueEx(hkBackup, TEXT("command"), 0, &type, (LPBYTE)szValue, &size);
  1203.         if (err == ERROR_SUCCESS)
  1204.         err = RegSetValueEx(hkCommand, NULL, 0, type, (LPBYTE)szValue, size);
  1205.         RegCloseKey(hkCommand);
  1206.         }
  1207.         size = sizeof(TCHAR) * MAX_PATH;
  1208.         err = RegQueryValueEx(hkBackup, TEXT("mail"), 0, &type, (LPBYTE)szValue, &size);
  1209.         if (err == ERROR_SUCCESS)
  1210.         err = RegSetValueEx(hkClientsMail, NULL, 0, type, (LPBYTE)szValue, size);
  1211.         RegCloseKey(hkBackup);
  1212.         }
  1213.         RegCloseKey(hkService);
  1214.         }
  1215.             }
  1216.             err = DeleteKeyAndSubKeys(hkClientsMail, lpszService);
  1217.         }
  1218.         RegCloseKey(hkClientsMail);
  1219. }
  1220.     //
  1221.     // REVIEW Backup fails sometimes. Need to clean up registry changes and 
  1222.     // probably remove all backup registry entirely.
  1223.     // For now just safe to return S_OK
  1224.     // 
  1225. #if 0
  1226.     if (err != ERROR_SUCCESS)
  1227. return HRESULT_FROM_WIN32(err);
  1228. #else
  1229.     return S_OK;
  1230. #endif
  1231. }
  1232. ///////////////////////////////////////////////////////////////////////
  1233. //
  1234. // AddService
  1235. //
  1236. ///////////////////////////////////////////////////////////////////////
  1237. void CALLBACK AddService(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  1238. {
  1239. LPSTR lpszService = lpszCmdLine;
  1240. LPSTR lpszPostUrl = NULL;
  1241. if (*lpszService == '"')
  1242. {
  1243. lpszService++;
  1244. lpszPostUrl = StrChr(lpszService, '"');
  1245. if (lpszPostUrl)
  1246. {
  1247. *lpszPostUrl = 0;
  1248. lpszPostUrl++;
  1249. while (*lpszPostUrl && *lpszPostUrl == ' ')
  1250. lpszPostUrl++;
  1251. if (*lpszPostUrl == 0)
  1252. lpszPostUrl = NULL;
  1253. }
  1254. }
  1255. else
  1256. {
  1257. lpszPostUrl = StrChr(lpszService, ' ');
  1258. if (lpszPostUrl)
  1259. {
  1260. *lpszPostUrl = 0;
  1261. lpszPostUrl++;
  1262. }
  1263. }
  1264. DoAddService(lpszService, lpszPostUrl);
  1265. }
  1266. ///////////////////////////////////////////////////////////////////////
  1267. //
  1268. // RemoveService
  1269. //
  1270. ///////////////////////////////////////////////////////////////////////
  1271. void CALLBACK RemoveService(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  1272. {
  1273. DWORD dwLen = (lpszCmdLine) ? lstrlen(lpszCmdLine) : 0;
  1274. if (dwLen)
  1275. {
  1276. if (*lpszCmdLine == '"' && lpszCmdLine[dwLen - 1] == '"')
  1277. {
  1278. lpszCmdLine[dwLen - 1] = 0;
  1279. lpszCmdLine++;
  1280. }
  1281. DoRemoveService(lpszCmdLine);
  1282. }
  1283. }
  1284. ///////////////////////////////////////////////////////////////////////
  1285. //
  1286. // DllRegisterServer
  1287. //
  1288. ///////////////////////////////////////////////////////////////////////
  1289. STDAPI DllRegisterServer(void)
  1290. {
  1291.     return DoAddService(TEXT("Hotmail"), NULL);
  1292. }
  1293. ///////////////////////////////////////////////////////////////////////
  1294. //
  1295. // DllUnregisterServer
  1296. //
  1297. ///////////////////////////////////////////////////////////////////////
  1298. STDAPI DllUnregisterServer(void)
  1299. {
  1300.     return DoRemoveService(TEXT("Hotmail"));
  1301. }