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.

1424 lines
45 KiB

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