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.

447 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. routemapi.cpp
  5. Abstract:
  6. This module provides the implemantation of registry manipulations to
  7. route MAPI calls to the Microsoft Outlook mail client
  8. Author:
  9. Mooly Beery (moolyb) 5-Nov-2000
  10. Revision History:
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <tchar.h>
  16. #include <debugex.h>
  17. // cause the module to export its methods
  18. //#define EXPORT_MAPI_ROUTE_CALLS
  19. #include <routemapi.h>
  20. #include "winfax.h"
  21. #include "faxreg.h"
  22. #include "faxutil.h"
  23. #define MS_OUTLOOK _T("Microsoft Outlook")
  24. #define REG_KEY_POP_UP _T("PreFirstRun")
  25. #define REG_KEY_POP_UP_OLD _T("{F779C4BF-4C94-4442-8844-633F0298ED0B}")
  26. #define REG_KEY_MAPI_APPS_OLD _T("{A5159994-A7F8-4C11-8F86-B9877CE02303}")
  27. #define REG_KEY_CLIENTS_MAIL _T("SOFTWARE\\Clients\\Mail")
  28. #define REG_KEY_MAPI_APPS _T("SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps")
  29. CRouteMAPICalls::CRouteMAPICalls()
  30. : m_ptProcessName(NULL),
  31. m_bMSOutlookInstalled(false),
  32. m_bMSOutlookIsDefault(false),
  33. m_bProcessIsRouted(false),
  34. m_bProcessIsRoutedToMsOutlook(false)
  35. {
  36. }
  37. // Function: CRouteMAPICalls::~CRouteMAPICalls
  38. //
  39. // Description: restores the registry to its initial state after
  40. // SetRegistryForSetupMAPICalls was called
  41. // if Microsoft Outlook is installed
  42. // if it's not restore pop-ups which might result from MAPI calls
  43. // if it is check if Microsoft Outlook is the default mail client
  44. // if it is do nothing
  45. // if it's not remove current process from routing all MAPI calls to Micosoft Outlook
  46. //
  47. // author:
  48. // MoolyB (05-NOV-00)
  49. //
  50. CRouteMAPICalls::~CRouteMAPICalls()
  51. {
  52. DWORD rc = ERROR_SUCCESS;
  53. TCHAR* ptPreFirstRun = NULL;
  54. TCHAR* ptPreRouteProcess = NULL;
  55. HKEY hMailKey = NULL;
  56. HKEY hMapiApps = NULL;
  57. DBG_ENTER(_T("CRouteMAPICalls::~CRouteMAPICalls"));
  58. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  59. REG_KEY_CLIENTS_MAIL,
  60. 0,
  61. KEY_ALL_ACCESS,
  62. &hMailKey);
  63. if (rc!=ERROR_SUCCESS)
  64. {
  65. // no mail clients instlled on this machine? this is strange
  66. // anyway, no work needs to be done, since no one will pop-up
  67. // any message and our transport provider is not added anywhere.
  68. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail"), rc);
  69. rc = ERROR_SUCCESS;
  70. goto exit;
  71. }
  72. if (m_bMSOutlookInstalled)
  73. {
  74. VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was installed"));
  75. // Microsoft Outlook was installed, check if we did some changes
  76. if (m_bMSOutlookIsDefault)
  77. {
  78. VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was the default mail client, nothing to resotre"));
  79. goto exit;
  80. }
  81. else
  82. {
  83. VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was not the default mail client"));
  84. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  85. REG_KEY_MAPI_APPS,
  86. 0,
  87. KEY_ALL_ACCESS,
  88. &hMapiApps);
  89. if (rc!=ERROR_SUCCESS)
  90. {
  91. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps"), rc);
  92. goto exit;
  93. }
  94. if (m_bProcessIsRouted)
  95. {
  96. if (m_bProcessIsRoutedToMsOutlook)
  97. {
  98. VERBOSE(DBG_MSG,_T("The process was routed before to MS Outlook, do nothing"));
  99. goto exit;
  100. }
  101. else
  102. {
  103. VERBOSE(DBG_MSG,_T("The process was routed before, restore key..."));
  104. // get old one
  105. ptPreRouteProcess = GetRegistryString(hMapiApps,REG_KEY_MAPI_APPS_OLD,NULL);
  106. if (ptPreRouteProcess==NULL)
  107. {
  108. // we failed to read the previously stored _szProcessName
  109. // fail the recovery attemp, but delete ourselves anyhow.
  110. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString"), rc);
  111. rc = RegDeleteValue(hMapiApps,m_ptProcessName);
  112. if (rc!=ERROR_SUCCESS)
  113. {
  114. CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue m_ptProcessName"), rc);
  115. }
  116. goto exit;
  117. }
  118. // delete backup
  119. rc = RegDeleteValue(hMapiApps,REG_KEY_MAPI_APPS_OLD);
  120. if (rc!=ERROR_SUCCESS)
  121. {
  122. CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue m_ptProcessName"), rc);
  123. }
  124. // set the old registry back
  125. if (!SetRegistryString(hMapiApps,m_ptProcessName,ptPreRouteProcess))
  126. {
  127. rc = GetLastError();
  128. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc);
  129. goto exit;
  130. }
  131. goto exit;
  132. }
  133. }
  134. else
  135. {
  136. VERBOSE(DBG_MSG,_T("The process was not routed before, delete key..."));
  137. rc = RegDeleteValue(hMapiApps,m_ptProcessName);
  138. if (rc!=ERROR_SUCCESS)
  139. {
  140. CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue REG_KEY_MAPI_APPS_OLD"), rc);
  141. goto exit;
  142. }
  143. }
  144. }
  145. }
  146. else
  147. {
  148. // Microsoft Outlook was not installed, so we suppressed the pop-up
  149. // need to restore the pop-up to its original state
  150. VERBOSE(DBG_MSG,_T("Microsoft Mail Client was not installed - restore pop-up"));
  151. // I restore the pop-up by renaming the REG_SZ _PreFirstRun
  152. // under HKLM\\SOFTWARE\\Clients\\Mail
  153. // to PreFirstRun,
  154. ptPreFirstRun = GetRegistryString(hMailKey,REG_KEY_POP_UP_OLD,NULL);
  155. if (ptPreFirstRun==NULL)
  156. {
  157. rc = GetLastError();
  158. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString _PreFirstRun"), rc);
  159. goto exit;
  160. }
  161. rc = RegDeleteValue(hMailKey,REG_KEY_POP_UP_OLD);
  162. if (rc!=ERROR_SUCCESS)
  163. {
  164. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString _PreFirstRun"), rc);
  165. }
  166. if (!SetRegistryString(hMailKey,REG_KEY_POP_UP,ptPreFirstRun))
  167. {
  168. rc = GetLastError();
  169. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString PreFirstRun"), rc);
  170. goto exit;
  171. }
  172. }
  173. exit:
  174. if (hMailKey)
  175. {
  176. RegCloseKey(hMailKey);
  177. }
  178. if (hMapiApps)
  179. {
  180. RegCloseKey(hMapiApps);
  181. }
  182. if (ptPreFirstRun)
  183. {
  184. MemFree(ptPreFirstRun);
  185. }
  186. if (ptPreRouteProcess)
  187. {
  188. MemFree(ptPreRouteProcess);
  189. }
  190. if (m_ptProcessName)
  191. {
  192. MemFree(m_ptProcessName);
  193. }
  194. if (rc!=ERROR_SUCCESS)
  195. {
  196. CALL_FAIL (GENERAL_ERR, TEXT("CRouteMAPICalls::~CRouteMAPICalls"), rc);
  197. }
  198. }
  199. // Function: CRouteMAPICalls::Init
  200. //
  201. // Description: check if Microsoft Outlook is installed
  202. // if it's not supress any pop-ups which might result from MAPI calls
  203. // if it is check if Microsoft Outlook is the default mail client
  204. // if it is do nothing
  205. // if it's not set current process to route all MAPI calls to Micosoft Outlook
  206. //
  207. // author:
  208. // MoolyB (05-NOV-00)
  209. //
  210. DWORD CRouteMAPICalls::Init(LPCTSTR lpctstrProcessName)
  211. {
  212. DWORD rc = ERROR_SUCCESS;
  213. HKEY hMailKey = NULL;
  214. HKEY hMsOutlookKey = NULL;
  215. HKEY hMapiApps = NULL;
  216. TCHAR* ptPreFirstRun = NULL;
  217. TCHAR* ptPreRouteProcess = NULL;
  218. TCHAR* ptDefaultMailClient = NULL;
  219. TCHAR* ptProcessName = NULL;
  220. DBG_ENTER(_T("CRouteMAPICalls::Init"), rc);
  221. int iSize = _tcslen(lpctstrProcessName);
  222. if (iSize==0)
  223. {
  224. VERBOSE(GENERAL_ERR,_T("invalid process name"));
  225. goto exit;
  226. }
  227. m_ptProcessName = (TCHAR*)MemAlloc((iSize+1)*sizeof(TCHAR));
  228. if (m_ptProcessName==NULL)
  229. {
  230. VERBOSE(GENERAL_ERR,_T("failure to allocate memory"));
  231. goto exit;
  232. }
  233. _tcscpy(m_ptProcessName,lpctstrProcessName);
  234. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  235. REG_KEY_CLIENTS_MAIL,
  236. 0,
  237. KEY_ALL_ACCESS,
  238. &hMailKey);
  239. if (rc!=ERROR_SUCCESS)
  240. {
  241. // no mail clients instlled on this machine? this is strange
  242. // anyway, no work needs to be done, since no one will pop-up
  243. // any message and our transport provider is not added anywhere.
  244. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail"), rc);
  245. rc = ERROR_SUCCESS;
  246. goto exit;
  247. }
  248. else
  249. {
  250. // there are a few mail clients
  251. // check if a key called 'Microsoft Outlook' exists.
  252. rc = RegOpenKeyEx( hMailKey,
  253. MS_OUTLOOK,
  254. 0,
  255. KEY_READ,
  256. &hMsOutlookKey);
  257. if (rc!=ERROR_SUCCESS)
  258. {
  259. // Microsoft Outlook is not installed
  260. CALL_FAIL(GENERAL_ERR,_T("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail\\Microsoft Outlook"),rc);
  261. if (rc==ERROR_FILE_NOT_FOUND)
  262. {
  263. // suppress pop-up message
  264. VERBOSE(DBG_MSG,_T("Microsoft Mail Client is not installed - suppress pop-up"));
  265. // I suppress the pop-up by renaming the REG_SZ PreFirstRun
  266. // under HKLM\\SOFTWARE\\Clients\\Mail
  267. // to _PreFirstRun, later, we'll restore this
  268. ptPreFirstRun = GetRegistryString(hMailKey,REG_KEY_POP_UP,NULL);
  269. if (ptPreFirstRun==NULL)
  270. {
  271. rc = GetLastError();
  272. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString PreFirstRun"), rc);
  273. goto exit;
  274. }
  275. if (!SetRegistryString(hMailKey,REG_KEY_POP_UP_OLD,ptPreFirstRun))
  276. {
  277. rc = GetLastError();
  278. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString _PreFirstRun"), rc);
  279. goto exit;
  280. }
  281. rc = RegDeleteValue(hMailKey,REG_KEY_POP_UP);
  282. if (rc!=ERROR_SUCCESS)
  283. {
  284. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString PreFirstRun"), rc);
  285. // try to cleanup, even though this is bad
  286. RegDeleteValue(hMailKey,REG_KEY_POP_UP_OLD);
  287. goto exit;
  288. }
  289. }
  290. else
  291. {
  292. // this is a true error in trying to open the key
  293. // HKLM\\SOFTWARE\\Clients\\Mail\\Microsoft Outlook
  294. goto exit;
  295. }
  296. }
  297. else
  298. {
  299. // Microsoft Outlook is installed
  300. m_bMSOutlookInstalled = true;
  301. // check if it is the deafult mail client
  302. ptDefaultMailClient = GetRegistryString(hMailKey,NULL,NULL);
  303. if ((ptDefaultMailClient==NULL) || (_tcscmp(ptDefaultMailClient,MS_OUTLOOK)))
  304. {
  305. // either there's no default mail client or GetRegistryString failed
  306. // or there is a default mail client and it's not Microsoft Outlook
  307. // in both cases I treat as Microsoft Outlook is not the default mail client
  308. // open HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Messaging Subsystem\MSMapiApps
  309. // and add a REG_SZ called according to szProcessName, set it to "Microsoft Outlook"
  310. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  311. REG_KEY_MAPI_APPS,
  312. 0,
  313. KEY_ALL_ACCESS,
  314. &hMapiApps);
  315. if (rc!=ERROR_SUCCESS)
  316. {
  317. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps"), rc);
  318. goto exit;
  319. }
  320. ptProcessName = GetRegistryString(hMapiApps,m_ptProcessName,NULL);
  321. if (ptProcessName==NULL)
  322. {
  323. // this is the 'good' case, no one wants to route MAPI calls from a process with
  324. // the same name as our own
  325. if (!SetRegistryString(hMapiApps,m_ptProcessName,MS_OUTLOOK))
  326. {
  327. rc = GetLastError();
  328. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc);
  329. goto exit;
  330. }
  331. }
  332. else
  333. {
  334. m_bProcessIsRouted = true;
  335. // this it bad, someone is routing MAPI calls from a process with the same name to
  336. // another app
  337. // check if it's routed to Microsoft Outlook, and if not, rename it and add ourselves
  338. if (_tcscmp(ptProcessName,MS_OUTLOOK)==0)
  339. {
  340. m_bProcessIsRoutedToMsOutlook = true;
  341. VERBOSE(DBG_MSG,_T("MAPI calls are already routed to Microsoft Outlook"));
  342. goto exit;
  343. }
  344. else
  345. {
  346. // set old one to _ prefix
  347. ptPreRouteProcess = GetRegistryString(hMapiApps,m_ptProcessName,NULL);
  348. if (ptPreRouteProcess==NULL)
  349. {
  350. // we failed to read the previously stored _szProcessName
  351. // fail the recovery attemp, but delete ourselves anyhow.
  352. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString"), rc);
  353. goto exit;
  354. }
  355. if (!SetRegistryString(hMapiApps,REG_KEY_MAPI_APPS_OLD,ptPreRouteProcess))
  356. {
  357. rc = GetLastError();
  358. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc);
  359. goto exit;
  360. }
  361. // set ourselves
  362. if (!SetRegistryString(hMapiApps,m_ptProcessName,MS_OUTLOOK))
  363. {
  364. rc = GetLastError();
  365. CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc);
  366. goto exit;
  367. }
  368. }
  369. }
  370. }
  371. else
  372. {
  373. // Microsoft Outlook is the default mail client
  374. m_bMSOutlookIsDefault = true;
  375. goto exit;
  376. }
  377. }
  378. }
  379. exit:
  380. if (hMailKey)
  381. {
  382. RegCloseKey(hMailKey);
  383. }
  384. if (hMsOutlookKey)
  385. {
  386. RegCloseKey(hMsOutlookKey);
  387. }
  388. if (hMapiApps)
  389. {
  390. RegCloseKey(hMapiApps);
  391. }
  392. if (ptPreFirstRun)
  393. {
  394. MemFree(ptPreFirstRun);
  395. }
  396. if (ptDefaultMailClient)
  397. {
  398. MemFree(ptDefaultMailClient);
  399. }
  400. if (ptProcessName)
  401. {
  402. MemFree(ptProcessName);
  403. }
  404. if (ptPreRouteProcess)
  405. {
  406. MemFree(ptPreFirstRun);
  407. }
  408. return rc;
  409. }