/*++ Copyright (c) 1996 Microsoft Corporation Module Name: mapi.c Abstract: This file implements wrappers for all mapi apis. The wrappers are necessary because mapi does not implement unicode and this code must be non-unicode. Environment: WIN32 User Mode Author: Wesley Witt (wesw) 7-Aug-1996 --*/ #undef UNICODE #undef _UNICODE #include #include #include #include #define INTERNAL 1 #include "common.h" #define MAPISVC_INF "%windir%\\system32\\mapisvc.inf" #define PAB_FILE_NAME "%windir%\\msfax.pab" #define PST_FILE_NAME "%windir%\\msfax.pst" #define FAXAB_SERVICE_NAME "MSFAX AB" #define FAXXP_SERVICE_NAME "MSFAX XP" #define MSAB_SERVICE_NAME "MSPST AB" #define MSPST_SERVICE_NAME "MSPST MS" #define CONTAB_SERVICE_NAME "CONTAB" #define MSAB_SERVICE_NAME_W L"MSPST AB" #define MSPST_SERVICE_NAME_W L"MSPST MS" #define FAXAB_SERVICE_NAME_W L"MSFAX AB" #define CONTAB_SERVICE_NAME_W L"CONTAB" // // pab property tags // #define PR_PAB_PATH PROP_TAG( PT_TSTRING, 0x6600 ) #define PR_PAB_PATH_W PROP_TAG( PT_UNICODE, 0x6600 ) #define PR_PAB_PATH_A PROP_TAG( PT_STRING8, 0x6600 ) #define PR_PAB_DET_DIR_VIEW_BY PROP_TAG( PT_LONG, 0x6601 ) #define PAB_DIR_VIEW_FIRST_THEN_LAST 0 #define PAB_DIR_VIEW_LAST_THEN_FIRST 1 // // pst property tags // #define PR_PST_PATH PROP_TAG( PT_STRING8, 0x6700 ) #define PR_PST_REMEMBER_PW PROP_TAG( PT_BOOLEAN, 0x6701 ) #define PR_PST_ENCRYPTION PROP_TAG( PT_LONG, 0x6702 ) #define PR_PST_PW_SZ_OLD PROP_TAG( PT_STRING8, 0x6703 ) #define PR_PST_PW_SZ_NEW PROP_TAG( PT_STRING8, 0x6704 ) #define PSTF_NO_ENCRYPTION ((DWORD)0x80000000) #define PSTF_COMPRESSABLE_ENCRYPTION ((DWORD)0x40000000) #define PSTF_BEST_ENCRYPTION ((DWORD)0x20000000) // // externs & globals // extern BOOL MapiAvail; static HMODULE MapiMod = NULL; static LPMAPIADMINPROFILES MapiAdminProfiles = NULL; static LPMAPIINITIALIZE MapiInitialize = NULL; static LPMAPILOGONEX MapiLogonEx; static LPMAPIUNINITIALIZE MapiUnInitialize = NULL; static LPMAPIFREEBUFFER pMAPIFreeBuffer = NULL; static LPPROFADMIN lpProfAdmin; static CHAR MapiSvcInf[MAX_PATH*2]; static BOOL MapiStartedByLogon; static LPWSTR AnsiStringToUnicodeString( LPSTR AnsiString, LPWSTR UnicodeString ) { DWORD Count; // // first see how big the buffer needs to be // Count = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, AnsiString, -1, NULL, 0 ); // // i guess the input string is empty // if (!Count) { return NULL; } // // convert the string // Count = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, AnsiString, -1, UnicodeString, Count ); // // the conversion failed // if (!Count) { return NULL; } return UnicodeString; } static LPSTR UnicodeStringToAnsiString( LPWSTR UnicodeString, LPSTR AnsiString ) { DWORD Count; // // first see how big the buffer needs to be // Count = WideCharToMultiByte( CP_ACP, 0, UnicodeString, -1, NULL, 0, NULL, NULL ); // // i guess the input string is empty // if (!Count) { return NULL; } // // convert the string // Count = WideCharToMultiByte( CP_ACP, 0, UnicodeString, -1, AnsiString, Count, NULL, NULL ); // // the conversion failed // if (!Count) { return NULL; } return AnsiString; } VOID MyWriteProfileString( LPTSTR SectionName, LPTSTR KeyName, LPTSTR Value ) { WritePrivateProfileString( SectionName, KeyName, Value, MapiSvcInf ); } VOID AddFaxAbToMapiSvcInf( VOID ) { MyWriteProfileString( "Default Services", "MSFAX AB", "Fax Address Book" ); MyWriteProfileString( "Services", "MSFAX AB", "Fax Address Book" ); MyWriteProfileString( "MSFAX AB", "PR_DISPLAY_NAME", "Fax Address Book" ); MyWriteProfileString( "MSFAX AB", "Providers", "MSFAX ABP" ); MyWriteProfileString( "MSFAX AB", "PR_SERVICE_DLL_NAME", "FAXAB.DLL" ); MyWriteProfileString( "MSFAX AB", "PR_SERVICE_SUPPORT_FILES", "FAXAB.DLL" ); MyWriteProfileString( "MSFAX AB", "PR_SERVICE_ENTRY_NAME", "FABServiceEntry" ); MyWriteProfileString( "MSFAX AB", "PR_RESOURCE_FLAGS", "SERVICE_SINGLE_COPY|SERVICE_NO_PRIMARY_IDENTITY" ); MyWriteProfileString( "MSFAX ABP", "PR_PROVIDER_DLL_NAME", "FAXAB.DLL" ); MyWriteProfileString( "MSFAX ABP", "PR_RESOURCE_TYPE", "MAPI_AB_PROVIDER" ); MyWriteProfileString( "MSFAX ABP", "PR_DISPLAY_NAME", "Fax Address Book" ); MyWriteProfileString( "MSFAX ABP", "PR_PROVIDER_DISPLAY", "Fax Address Book" ); } VOID AddFaxXpToMapiSvcInf( VOID ) { MyWriteProfileString( "Default Services", "MSFAX XP", "Fax Mail Transport" ); MyWriteProfileString( "Services", "MSFAX XP", "Fax Mail Transport" ); MyWriteProfileString( "MSFAX XP", "PR_DISPLAY_NAME", "Fax Mail Transport" ); MyWriteProfileString( "MSFAX XP", "Providers", "MSFAX XPP" ); MyWriteProfileString( "MSFAX XP", "PR_SERVICE_DLL_NAME", "FAXXP.DLL" ); MyWriteProfileString( "MSFAX XP", "PR_SERVICE_SUPPORT_FILES", "FAXXP.DLL" ); MyWriteProfileString( "MSFAX XP", "PR_SERVICE_ENTRY_NAME", "ServiceEntry" ); MyWriteProfileString( "MSFAX XP", "PR_RESOURCE_FLAGS", "SERVICE_SINGLE_COPY|SERVICE_NO_PRIMARY_IDENTITY" ); MyWriteProfileString( "MSFAX XPP", "PR_PROVIDER_DLL_NAME", "FAXXP.DLL" ); MyWriteProfileString( "MSFAX XPP", "PR_RESOURCE_TYPE", "MAPI_TRANSPORT_PROVIDER" ); MyWriteProfileString( "MSFAX XPP", "PR_RESOURCE_FLAGS", "STATUS_NO_DEFAULT_STORE" ); MyWriteProfileString( "MSFAX XPP", "PR_DISPLAY_NAME", "Fax Mail Transport" ); MyWriteProfileString( "MSFAX XPP", "PR_PROVIDER_DISPLAY", "Fax Mail Transport" ); } VOID FreeSRowSet( LPSRowSet prws ) { ULONG irw; if (!prws) { return; } for(irw = 0; irw < prws->cRows; irw++) { pMAPIFreeBuffer( prws->aRow[irw].lpProps ); } pMAPIFreeBuffer( prws ); } ULONG MLCRelease( LPUNKNOWN punk ) { return (punk) ? punk->lpVtbl->Release(punk) : 0; } BOOL ValidateProp( LPSPropValue pval, ULONG ulPropTag ) { if (pval->ulPropTag != ulPropTag) { pval->ulPropTag = ulPropTag; pval->Value.lpszA = "???"; return TRUE; } return FALSE; } BOOL IsMapiServiceInstalled( LPWSTR ProfileNameW, LPWSTR ServiceNameW ) { SPropTagArray taga = {2,{PR_DISPLAY_NAME,PR_SERVICE_NAME}}; BOOL rVal = FALSE; LPSERVICEADMIN lpSvcAdmin; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; DWORD i; LPSPropValue pval; CHAR ProfileName[128]; CHAR ServiceName[64]; if (!MapiAvail) { goto exit; } UnicodeStringToAnsiString( ProfileNameW, ProfileName ); UnicodeStringToAnsiString( ServiceNameW, ServiceName ); if (lpProfAdmin->lpVtbl->AdminServices( lpProfAdmin, ProfileName, NULL, 0, 0, &lpSvcAdmin )) { goto exit; } if (lpSvcAdmin->lpVtbl->GetMsgServiceTable( lpSvcAdmin, 0, &pmt )) { goto exit; } if (pmt->lpVtbl->SetColumns( pmt, &taga, 0 )) { goto exit; } if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; ValidateProp( &pval[0], PR_DISPLAY_NAME ); ValidateProp( &pval[1], PR_SERVICE_NAME ); if (_stricmp( pval[1].Value.lpszA, ServiceName ) == 0) { rVal = TRUE; break; } } exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL InstallFaxAddressBook( HWND hwnd, LPWSTR ProfileNameW ) { SPropTagArray taga = {2,{PR_SERVICE_NAME,PR_SERVICE_UID}}; SPropValue spvProps[2] = { 0 }; BOOL rVal = FALSE; LPSERVICEADMIN lpSvcAdmin; CHAR ProfileName[128]; CHAR Buffer[128]; HRESULT hResult; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; DWORD i; LPSPropValue pval; BOOL ConfigurePst = FALSE; BOOL ConfigurePab = FALSE; LPMAPISESSION Session = NULL; if (!MapiAvail) { goto exit; } UnicodeStringToAnsiString( ProfileNameW, ProfileName ); if (IsMapiServiceInstalled( ProfileNameW, CONTAB_SERVICE_NAME_W )) { // // we don't need a pab/fab if we have the outlook contact address book // goto exit; } hResult = lpProfAdmin->lpVtbl->AdminServices( lpProfAdmin, ProfileName, NULL, 0, 0, &lpSvcAdmin ); if (hResult) { goto exit; } if (!IsMapiServiceInstalled( ProfileNameW, MSAB_SERVICE_NAME_W )) { hResult = lpSvcAdmin->lpVtbl->CreateMsgService( lpSvcAdmin, MSAB_SERVICE_NAME, NULL, 0, 0 ); if (hResult && hResult != MAPI_E_NO_ACCESS) { // // mapi will return MAPI_E_NO_ACCESS when the service is already installed // goto exit; } ConfigurePab = TRUE; } if (!IsMapiServiceInstalled( ProfileNameW, MSPST_SERVICE_NAME_W )) { hResult = lpSvcAdmin->lpVtbl->CreateMsgService( lpSvcAdmin, MSPST_SERVICE_NAME, NULL, 0, 0 ); if (hResult && hResult != MAPI_E_NO_ACCESS) { // // mapi will return MAPI_E_NO_ACCESS when the service is already installed // goto exit; } ConfigurePst = TRUE; } if (!IsMapiServiceInstalled( ProfileNameW, FAXAB_SERVICE_NAME_W )) { hResult = lpSvcAdmin->lpVtbl->CreateMsgService( lpSvcAdmin, FAXAB_SERVICE_NAME, NULL, 0, 0 ); if (hResult && hResult != MAPI_E_NO_ACCESS) { // // mapi will return MAPI_E_NO_ACCESS when the service is already installed // goto exit; } } // // now configure the address book and pst // if (lpSvcAdmin->lpVtbl->GetMsgServiceTable( lpSvcAdmin, 0, &pmt )) { goto exit; } if (pmt->lpVtbl->SetColumns( pmt, &taga, 0 )) { goto exit; } if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; ValidateProp( &pval[0], PR_SERVICE_NAME ); if (ConfigurePab && (_stricmp( pval[0].Value.lpszA, MSAB_SERVICE_NAME) == 0)) { // // configure the pab service // ExpandEnvironmentStrings( PAB_FILE_NAME, Buffer, sizeof(Buffer) ); spvProps[0].ulPropTag = PR_PAB_PATH; spvProps[0].Value.LPSZ = Buffer; spvProps[1].ulPropTag = PR_PAB_DET_DIR_VIEW_BY; spvProps[1].Value.ul = PAB_DIR_VIEW_FIRST_THEN_LAST; if (lpSvcAdmin->lpVtbl->ConfigureMsgService( lpSvcAdmin, (LPMAPIUID)pval[1].Value.bin.lpb, (ULONG) hwnd, 0, 2, spvProps )) { } } if (ConfigurePst && (_stricmp( pval[0].Value.lpszA, MSPST_SERVICE_NAME) == 0)) { // // configure the pst service // ExpandEnvironmentStrings( PST_FILE_NAME, Buffer, sizeof(Buffer) ); spvProps[0].ulPropTag = PR_PST_PATH; spvProps[0].Value.LPSZ = Buffer; spvProps[1].ulPropTag = PR_PST_ENCRYPTION; spvProps[1].Value.ul = PSTF_NO_ENCRYPTION; if (lpSvcAdmin->lpVtbl->ConfigureMsgService( lpSvcAdmin, (LPMAPIUID)pval[1].Value.bin.lpb, (ULONG) hwnd, 0, 2, spvProps )) { } } } if (ConfigurePab || ConfigurePst) { __try { if (MapiLogonEx( 0, ProfileName, NULL, MAPI_NEW_SESSION | MAPI_EXTENDED, &Session ) == 0) { MapiStartedByLogon = TRUE; Session->lpVtbl->Logoff( Session, 0, 0, 0 ); } } __except (EXCEPTION_EXECUTE_HANDLER) { } } rVal = TRUE; exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL InstallFaxTransport( LPWSTR ProfileNameW ) { BOOL rVal = FALSE; LPSERVICEADMIN lpSvcAdmin; CHAR ProfileName[128]; if (!MapiAvail) { goto exit; } UnicodeStringToAnsiString( ProfileNameW, ProfileName ); if (lpProfAdmin->lpVtbl->AdminServices( lpProfAdmin, ProfileName, NULL, 0, 0, &lpSvcAdmin )) { goto exit; } if (lpSvcAdmin->lpVtbl->CreateMsgService( lpSvcAdmin, FAXXP_SERVICE_NAME, NULL, 0, 0 )) { goto exit; } rVal = TRUE; exit: return rVal; } BOOL CreateDefaultMapiProfile( LPWSTR ProfileNameW ) { BOOL rVal = FALSE; CHAR ProfileName[128]; if (!MapiAvail) { goto exit; } UnicodeStringToAnsiString( ProfileNameW, ProfileName ); // // create the new profile // if (lpProfAdmin->lpVtbl->CreateProfile( lpProfAdmin, ProfileName, NULL, 0, 0 )) { goto exit; } if (lpProfAdmin->lpVtbl->SetDefaultProfile( lpProfAdmin, ProfileName, 0 )) { goto exit; } rVal = TRUE; exit: return rVal; } BOOL GetDefaultMapiProfile( LPWSTR ProfileName ) { BOOL rVal = FALSE; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; LPSPropValue pval; DWORD i; DWORD j; if (!MapiAvail) { goto exit; } // // get the mapi profile table object // if (lpProfAdmin->lpVtbl->GetProfileTable( lpProfAdmin, 0, &pmt )) { goto exit; } // // get the actual profile data, FINALLY // if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } // // enumerate the profiles looking for the default profile // for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; for (j = 0; j < 2; j++) { if (pval[j].ulPropTag == PR_DEFAULT_PROFILE && pval[j].Value.b) { // // this is the default profile // AnsiStringToUnicodeString( pval[0].Value.lpszA, ProfileName ); rVal = TRUE; break; } } } exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL DeleteMessageService( LPSTR ProfileName ) { SPropTagArray taga = {2,{PR_SERVICE_NAME,PR_SERVICE_UID}}; BOOL rVal = FALSE; LPSERVICEADMIN lpSvcAdmin; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; DWORD i; LPSPropValue pval; if (!MapiAvail) { goto exit; } if (lpProfAdmin->lpVtbl->AdminServices( lpProfAdmin, ProfileName, NULL, 0, 0, &lpSvcAdmin )) { goto exit; } if (lpSvcAdmin->lpVtbl->GetMsgServiceTable( lpSvcAdmin, 0, &pmt )) { goto exit; } if (pmt->lpVtbl->SetColumns( pmt, &taga, 0 )) { goto exit; } if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; ValidateProp( &pval[0], PR_SERVICE_NAME ); if (_stricmp( pval[0].Value.lpszA, "MSFAX AB" ) == 0) { lpSvcAdmin->lpVtbl->DeleteMsgService( lpSvcAdmin, (LPMAPIUID) pval[1].Value.bin.lpb ); } if (_stricmp( pval[0].Value.lpszA, "MSFAX XP" ) == 0) { lpSvcAdmin->lpVtbl->DeleteMsgService( lpSvcAdmin, (LPMAPIUID) pval[1].Value.bin.lpb ); } } exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL DeleteFaxMsgServices( VOID ) { BOOL rVal = FALSE; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; LPSPropValue pval; DWORD i; DWORD j; if (!MapiAvail) { goto exit; } // // get the mapi profile table object // if (lpProfAdmin->lpVtbl->GetProfileTable( lpProfAdmin, 0, &pmt )) { goto exit; } // // get the actual profile data, FINALLY // if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } // // enumerate the profiles looking for the default profile // for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; for (j = 0; j < 2; j++) { if (pval[j].ulPropTag == PR_DISPLAY_NAME) { DeleteMessageService( pval[j].Value.lpszA ); break; } } } exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL IsExchangeInstalled( VOID ) { BOOL MapiAvail = FALSE; CHAR MapiOption[4]; HKEY hKey; LONG rVal; DWORD Bytes; DWORD Type; rVal = RegOpenKey( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows Messaging Subsystem", &hKey ); if (rVal == ERROR_SUCCESS) { Bytes = sizeof(MapiOption); rVal = RegQueryValueEx( hKey, "MAPIX", NULL, &Type, (LPBYTE) MapiOption, &Bytes ); if (rVal == ERROR_SUCCESS) { if (Bytes && MapiOption[0] == '1') { MapiAvail = TRUE; } } RegCloseKey( hKey ); } return MapiAvail; } BOOL InitializeMapi( VOID ) { MAPIINIT_0 MapiInit; ExpandEnvironmentStrings( MAPISVC_INF, MapiSvcInf, sizeof(MapiSvcInf) ); MapiAvail = IsExchangeInstalled(); if (!MapiAvail) { goto exit; } // // load the mapi dll // MapiMod = LoadLibrary( "mapi32.dll" ); if (!MapiMod) { MapiAvail = FALSE; goto exit; } // // get the addresses of the mapi functions that we need // MapiAdminProfiles = (LPMAPIADMINPROFILES) GetProcAddress( MapiMod, "MAPIAdminProfiles" ); MapiInitialize = (LPMAPIINITIALIZE) GetProcAddress( MapiMod, "MAPIInitialize" ); MapiUnInitialize = (LPMAPIUNINITIALIZE) GetProcAddress( MapiMod, "MAPIUninitialize" ); pMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress( MapiMod, "MAPIFreeBuffer" ); MapiLogonEx = (LPMAPILOGONEX) GetProcAddress( MapiMod, "MAPILogonEx" ); if ((!MapiAdminProfiles) || (!MapiInitialize) || (!MapiUnInitialize) || (!pMAPIFreeBuffer) || (!MapiLogonEx)) { MapiAvail = FALSE; goto exit; } // // initialize mapi for our calls // MapiInit.ulVersion = 0; MapiInit.ulFlags = 0; if (MapiInitialize( &MapiInit )) { MapiAvail = FALSE; goto exit; } // // get the admin profile object // if (MapiAdminProfiles( 0, &lpProfAdmin )) { MapiAvail = FALSE; goto exit; } exit: return MapiAvail; } BOOL GetMapiProfiles( HWND hwnd, DWORD ResourceId ) { BOOL rVal = FALSE; HMODULE MapiMod = NULL; LPMAPITABLE pmt = NULL; LPSRowSet prws = NULL; LPSPropValue pval; DWORD i; // // add the default profile // SendDlgItemMessageA( hwnd, ResourceId, CB_ADDSTRING, 0, (LPARAM) "" ); SendDlgItemMessage( hwnd, ResourceId, CB_SETCURSEL, 0, 0 ); if (!MapiAvail) { goto exit; } // // get the mapi table object // if (lpProfAdmin->lpVtbl->GetProfileTable( lpProfAdmin, 0, &pmt )) { goto exit; } // // get the actual profile data, FINALLY // if (pmt->lpVtbl->QueryRows( pmt, 4000, 0, &prws )) { goto exit; } // // enumerate the profiles and put the name // of each profile in the combo box // for (i=0; icRows; i++) { pval = prws->aRow[i].lpProps; SendDlgItemMessageA( hwnd, ResourceId, CB_ADDSTRING, 0, (LPARAM) pval[0].Value.lpszA ); if (pval[2].Value.b) { // // this is the default profile // } } // // set the first one to be the current one // SendDlgItemMessage( hwnd, ResourceId, CB_SETCURSEL, 0, 0 ); rVal = TRUE; exit: FreeSRowSet( prws ); MLCRelease( (LPUNKNOWN)pmt ); return rVal; } BOOL GetExchangeInstallCommand( LPWSTR InstallCommandW ) { HKEY hKey; LONG rVal; DWORD Bytes; DWORD Type; CHAR InstallCommand[512]; rVal = RegOpenKey( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows Messaging Subsystem", &hKey ); if (rVal == ERROR_SUCCESS) { Bytes = sizeof(InstallCommand); rVal = RegQueryValueEx( hKey, "InstallCmd", NULL, &Type, (LPBYTE) InstallCommand, &Bytes ); RegCloseKey( hKey ); if (rVal == ERROR_SUCCESS) { AnsiStringToUnicodeString( InstallCommand, InstallCommandW ); return TRUE; } } return FALSE; } BOOL InstallExchangeClientExtension( LPSTR ExtensionName, LPSTR FileName, LPSTR ContextMask ) { HKEY hKey; LONG rVal; CHAR Buffer[512]; CHAR ExpandedFileName[MAX_PATH]; rVal = RegOpenKey( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Exchange\\Client\\Extensions", &hKey ); if (rVal == ERROR_SUCCESS) { ExpandEnvironmentStrings( FileName, ExpandedFileName, sizeof(ExpandedFileName) ); sprintf( Buffer, "4.0;%s;1;%s", ExpandedFileName, ContextMask ); rVal = RegSetValueEx( hKey, ExtensionName, 0, REG_SZ, (LPBYTE) Buffer, strlen(Buffer) + 1 ); RegCloseKey( hKey ); return rVal == ERROR_SUCCESS; } return FALSE; } DWORD IsExchangeRunning( VOID ) { #define MAX_TASKS 256 DWORD TaskCount; PTASK_LIST TaskList = NULL; DWORD ExchangePid = 0; DWORD i; if (MapiStartedByLogon) { return 0; } TaskList = (PTASK_LIST) malloc( MAX_TASKS * sizeof(TASK_LIST) ); if (!TaskList) { goto exit; } TaskCount = GetTaskList( TaskList, MAX_TASKS ); if (!TaskCount) { goto exit; } for (i=0; i