/*++ Copyright (c) 2000 Microsoft Corporation Module Name: routemapi.cpp Abstract: This module provides the implemantation of registry manipulations to route MAPI calls to the Microsoft Outlook mail client Author: Mooly Beery (moolyb) 5-Nov-2000 Revision History: --*/ #include #include #include #include #include // cause the module to export its methods //#define EXPORT_MAPI_ROUTE_CALLS #include #include "winfax.h" #include "faxreg.h" #include "faxutil.h" #define MS_OUTLOOK _T("Microsoft Outlook") #define REG_KEY_POP_UP _T("PreFirstRun") #define REG_KEY_POP_UP_OLD _T("{F779C4BF-4C94-4442-8844-633F0298ED0B}") #define REG_KEY_MAPI_APPS_OLD _T("{A5159994-A7F8-4C11-8F86-B9877CE02303}") #define REG_KEY_CLIENTS_MAIL _T("SOFTWARE\\Clients\\Mail") #define REG_KEY_MAPI_APPS _T("SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps") CRouteMAPICalls::CRouteMAPICalls() : m_ptProcessName(NULL), m_bMSOutlookInstalled(false), m_bMSOutlookIsDefault(false), m_bProcessIsRouted(false), m_bProcessIsRoutedToMsOutlook(false) { } // Function: CRouteMAPICalls::~CRouteMAPICalls // // Description: restores the registry to its initial state after // SetRegistryForSetupMAPICalls was called // if Microsoft Outlook is installed // if it's not restore pop-ups which might result from MAPI calls // if it is check if Microsoft Outlook is the default mail client // if it is do nothing // if it's not remove current process from routing all MAPI calls to Micosoft Outlook // // author: // MoolyB (05-NOV-00) // CRouteMAPICalls::~CRouteMAPICalls() { DWORD rc = ERROR_SUCCESS; TCHAR* ptPreFirstRun = NULL; TCHAR* ptPreRouteProcess = NULL; HKEY hMailKey = NULL; HKEY hMapiApps = NULL; DBG_ENTER(_T("CRouteMAPICalls::~CRouteMAPICalls")); rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_CLIENTS_MAIL, 0, KEY_ALL_ACCESS, &hMailKey); if (rc!=ERROR_SUCCESS) { // no mail clients instlled on this machine? this is strange // anyway, no work needs to be done, since no one will pop-up // any message and our transport provider is not added anywhere. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail"), rc); rc = ERROR_SUCCESS; goto exit; } if (m_bMSOutlookInstalled) { VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was installed")); // Microsoft Outlook was installed, check if we did some changes if (m_bMSOutlookIsDefault) { VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was the default mail client, nothing to resotre")); goto exit; } else { VERBOSE(DBG_MSG,_T("Microsoft Outlook Client was not the default mail client")); rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_MAPI_APPS, 0, KEY_ALL_ACCESS, &hMapiApps); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps"), rc); goto exit; } if (m_bProcessIsRouted) { if (m_bProcessIsRoutedToMsOutlook) { VERBOSE(DBG_MSG,_T("The process was routed before to MS Outlook, do nothing")); goto exit; } else { VERBOSE(DBG_MSG,_T("The process was routed before, restore key...")); // get old one ptPreRouteProcess = GetRegistryString(hMapiApps,REG_KEY_MAPI_APPS_OLD,NULL); if (ptPreRouteProcess==NULL) { // we failed to read the previously stored _szProcessName // fail the recovery attemp, but delete ourselves anyhow. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString"), rc); rc = RegDeleteValue(hMapiApps,m_ptProcessName); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue m_ptProcessName"), rc); } goto exit; } // delete backup rc = RegDeleteValue(hMapiApps,REG_KEY_MAPI_APPS_OLD); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue m_ptProcessName"), rc); } // set the old registry back if (!SetRegistryString(hMapiApps,m_ptProcessName,ptPreRouteProcess)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc); goto exit; } goto exit; } } else { VERBOSE(DBG_MSG,_T("The process was not routed before, delete key...")); rc = RegDeleteValue(hMapiApps,m_ptProcessName); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("RegDeleteValue REG_KEY_MAPI_APPS_OLD"), rc); goto exit; } } } } else { // Microsoft Outlook was not installed, so we suppressed the pop-up // need to restore the pop-up to its original state VERBOSE(DBG_MSG,_T("Microsoft Mail Client was not installed - restore pop-up")); // I restore the pop-up by renaming the REG_SZ _PreFirstRun // under HKLM\\SOFTWARE\\Clients\\Mail // to PreFirstRun, ptPreFirstRun = GetRegistryString(hMailKey,REG_KEY_POP_UP_OLD,NULL); if (ptPreFirstRun==NULL) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString _PreFirstRun"), rc); goto exit; } rc = RegDeleteValue(hMailKey,REG_KEY_POP_UP_OLD); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString _PreFirstRun"), rc); } if (!SetRegistryString(hMailKey,REG_KEY_POP_UP,ptPreFirstRun)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString PreFirstRun"), rc); goto exit; } } exit: if (hMailKey) { RegCloseKey(hMailKey); } if (hMapiApps) { RegCloseKey(hMapiApps); } if (ptPreFirstRun) { MemFree(ptPreFirstRun); } if (ptPreRouteProcess) { MemFree(ptPreRouteProcess); } if (m_ptProcessName) { MemFree(m_ptProcessName); } if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("CRouteMAPICalls::~CRouteMAPICalls"), rc); } } // Function: CRouteMAPICalls::Init // // Description: check if Microsoft Outlook is installed // if it's not supress any pop-ups which might result from MAPI calls // if it is check if Microsoft Outlook is the default mail client // if it is do nothing // if it's not set current process to route all MAPI calls to Micosoft Outlook // // author: // MoolyB (05-NOV-00) // DWORD CRouteMAPICalls::Init(LPCTSTR lpctstrProcessName) { DWORD rc = ERROR_SUCCESS; HKEY hMailKey = NULL; HKEY hMsOutlookKey = NULL; HKEY hMapiApps = NULL; TCHAR* ptPreFirstRun = NULL; TCHAR* ptPreRouteProcess = NULL; TCHAR* ptDefaultMailClient = NULL; TCHAR* ptProcessName = NULL; DBG_ENTER(_T("CRouteMAPICalls::Init"), rc); int iSize = _tcslen(lpctstrProcessName); if (iSize==0) { VERBOSE(GENERAL_ERR,_T("invalid process name")); goto exit; } m_ptProcessName = (TCHAR*)MemAlloc((iSize+1)*sizeof(TCHAR)); if (m_ptProcessName==NULL) { VERBOSE(GENERAL_ERR,_T("failure to allocate memory")); goto exit; } _tcscpy(m_ptProcessName,lpctstrProcessName); rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_CLIENTS_MAIL, 0, KEY_ALL_ACCESS, &hMailKey); if (rc!=ERROR_SUCCESS) { // no mail clients instlled on this machine? this is strange // anyway, no work needs to be done, since no one will pop-up // any message and our transport provider is not added anywhere. CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail"), rc); rc = ERROR_SUCCESS; goto exit; } else { // there are a few mail clients // check if a key called 'Microsoft Outlook' exists. rc = RegOpenKeyEx( hMailKey, MS_OUTLOOK, 0, KEY_READ, &hMsOutlookKey); if (rc!=ERROR_SUCCESS) { // Microsoft Outlook is not installed CALL_FAIL(GENERAL_ERR,_T("RegOpenKeyEx HKLM\\SOFTWARE\\Clients\\Mail\\Microsoft Outlook"),rc); if (rc==ERROR_FILE_NOT_FOUND) { // suppress pop-up message VERBOSE(DBG_MSG,_T("Microsoft Mail Client is not installed - suppress pop-up")); // I suppress the pop-up by renaming the REG_SZ PreFirstRun // under HKLM\\SOFTWARE\\Clients\\Mail // to _PreFirstRun, later, we'll restore this ptPreFirstRun = GetRegistryString(hMailKey,REG_KEY_POP_UP,NULL); if (ptPreFirstRun==NULL) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString PreFirstRun"), rc); goto exit; } if (!SetRegistryString(hMailKey,REG_KEY_POP_UP_OLD,ptPreFirstRun)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString _PreFirstRun"), rc); goto exit; } rc = RegDeleteValue(hMailKey,REG_KEY_POP_UP); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString PreFirstRun"), rc); // try to cleanup, even though this is bad RegDeleteValue(hMailKey,REG_KEY_POP_UP_OLD); goto exit; } } else { // this is a true error in trying to open the key // HKLM\\SOFTWARE\\Clients\\Mail\\Microsoft Outlook goto exit; } } else { // Microsoft Outlook is installed m_bMSOutlookInstalled = true; // check if it is the deafult mail client ptDefaultMailClient = GetRegistryString(hMailKey,NULL,NULL); if ((ptDefaultMailClient==NULL) || (_tcscmp(ptDefaultMailClient,MS_OUTLOOK))) { // either there's no default mail client or GetRegistryString failed // or there is a default mail client and it's not Microsoft Outlook // in both cases I treat as Microsoft Outlook is not the default mail client // open HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Messaging Subsystem\MSMapiApps // and add a REG_SZ called according to szProcessName, set it to "Microsoft Outlook" rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_MAPI_APPS, 0, KEY_ALL_ACCESS, &hMapiApps); if (rc!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx SOFTWARE\\Microsoft\\Windows Messaging Subsystem\\MSMapiApps"), rc); goto exit; } ptProcessName = GetRegistryString(hMapiApps,m_ptProcessName,NULL); if (ptProcessName==NULL) { // this is the 'good' case, no one wants to route MAPI calls from a process with // the same name as our own if (!SetRegistryString(hMapiApps,m_ptProcessName,MS_OUTLOOK)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc); goto exit; } } else { m_bProcessIsRouted = true; // this it bad, someone is routing MAPI calls from a process with the same name to // another app // check if it's routed to Microsoft Outlook, and if not, rename it and add ourselves if (_tcscmp(ptProcessName,MS_OUTLOOK)==0) { m_bProcessIsRoutedToMsOutlook = true; VERBOSE(DBG_MSG,_T("MAPI calls are already routed to Microsoft Outlook")); goto exit; } else { // set old one to _ prefix ptPreRouteProcess = GetRegistryString(hMapiApps,m_ptProcessName,NULL); if (ptPreRouteProcess==NULL) { // we failed to read the previously stored _szProcessName // fail the recovery attemp, but delete ourselves anyhow. CALL_FAIL (GENERAL_ERR, TEXT("GetRegistryString"), rc); goto exit; } if (!SetRegistryString(hMapiApps,REG_KEY_MAPI_APPS_OLD,ptPreRouteProcess)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc); goto exit; } // set ourselves if (!SetRegistryString(hMapiApps,m_ptProcessName,MS_OUTLOOK)) { rc = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryString"), rc); goto exit; } } } } else { // Microsoft Outlook is the default mail client m_bMSOutlookIsDefault = true; goto exit; } } } exit: if (hMailKey) { RegCloseKey(hMailKey); } if (hMsOutlookKey) { RegCloseKey(hMsOutlookKey); } if (hMapiApps) { RegCloseKey(hMapiApps); } if (ptPreFirstRun) { MemFree(ptPreFirstRun); } if (ptDefaultMailClient) { MemFree(ptDefaultMailClient); } if (ptProcessName) { MemFree(ptProcessName); } if (ptPreRouteProcess) { MemFree(ptPreFirstRun); } return rc; }