mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 10:57:34 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
36
mailnews/mapi/mapihook/build/Makefile.in
Normal file
36
mailnews/mapi/mapihook/build/Makefile.in
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MIDL_GENERATED_FILES = msgMapi.h msgMapi_p.c msgMapi_i.c dlldata.c
|
||||
|
||||
INSTALL_TARGETS += msgmapi
|
||||
msgmapi_FILES := msgMapi.h
|
||||
msgmapi_DEST = $(DIST)/include
|
||||
msgmapi_TARGET := export
|
||||
|
||||
SRCDIR_CSRCS = $(addprefix $(srcdir)/,$(CSRCS))
|
||||
|
||||
GARBAGE += $(MIDL_GENERATED_FILES) done_gen $(CSRCS) $(SRCDIR_CSRCS)
|
||||
|
||||
EMBED_MANIFEST_AT = 2
|
||||
|
||||
CSRCS += \
|
||||
dlldata.c \
|
||||
msgMapi_i.c \
|
||||
msgMapi_p.c \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
$(MIDL_GENERATED_FILES): done_gen
|
||||
|
||||
done_gen: msgMapi.idl
|
||||
$(RM) $(SRCDIR_CSRCS)
|
||||
$(MIDL) $(MIDL_FLAGS) $(UNICODE_FLAGS) $(srcdir)/msgMapi.idl
|
||||
touch $@
|
||||
|
||||
export:: done_gen
|
||||
|
||||
|
||||
13
mailnews/mapi/mapihook/build/MapiProxy.def
Normal file
13
mailnews/mapi/mapihook/build/MapiProxy.def
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
LIBRARY MapiProxy.dll
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
GetProxyDllInfo PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
|
||||
6
mailnews/mapi/mapihook/build/module.ver
Normal file
6
mailnews/mapi/mapihook/build/module.ver
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
WIN32_MODULE_FILEVERSION=0,8,0,0
|
||||
WIN32_MODULE_FILEVERSION_STRING=0.8
|
||||
WIN32_MODULE_COPYRIGHT=©Thunderbird and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable.
|
||||
WIN32_MODULE_COMPANYNAME=Mozilla.org
|
||||
WIN32_MODULE_TRADEMARKS=Mozilla
|
||||
WIN32_MODULE_COMMENT=Mozilla Thunderbird Thunderbird MAPI Proxy Dll
|
||||
22
mailnews/mapi/mapihook/build/moz.build
Normal file
22
mailnews/mapi/mapihook/build/moz.build
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SharedLibrary('MapiProxy')
|
||||
|
||||
OS_LIBS += [
|
||||
'rpcrt4',
|
||||
]
|
||||
|
||||
for var in ('REGISTER_PROXY_DLL', 'UNICODE', '_UNICODE'):
|
||||
DEFINES[var] = True
|
||||
|
||||
# This produces a compile warning mozilla-config.h(145): warning C4005: '_WIN32_WINNT': macro redefinition
|
||||
#DEFINES['_WIN32_WINNT'] = '0x400'
|
||||
|
||||
if not CONFIG['MOZ_INCOMPLETE_EXTERNAL_LINKAGE']:
|
||||
DEFINES['MOZILLA_INTERNAL_API'] = True
|
||||
|
||||
DEFFILE = SRCDIR + '/MapiProxy.def'
|
||||
|
||||
93
mailnews/mapi/mapihook/build/msgMapi.idl
Normal file
93
mailnews/mapi/mapihook/build/msgMapi.idl
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This idl will be compiled by MIDL. MS-COM is used
|
||||
// as bridge between MAPI clients and the Mozilla.
|
||||
|
||||
import "unknwn.idl";
|
||||
|
||||
typedef wchar_t LOGIN_PW_TYPE[256];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
unsigned long flFlags; /* Flags */
|
||||
unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
|
||||
LPTSTR lpszPathName; /* Full path name including file name */
|
||||
LPTSTR lpszFileName; /* Real (original) file name */
|
||||
unsigned char * lpFileType_NotUsed ;
|
||||
} nsMapiFileDesc, * lpnsMapiFileDesc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
|
||||
LPSTR lpszName; /* Recipient name to display */
|
||||
LPSTR lpszAddress; /* Recipient email address */
|
||||
unsigned long ulEIDSize_NotUsed;
|
||||
unsigned char * lpEntryID_NotUsed ;
|
||||
} nsMapiRecipDesc, * lpnsMapiRecipDesc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long ulReserved;
|
||||
LPSTR lpszSubject; /* Message Subject */
|
||||
LPSTR lpszNoteText; /* Message Text */
|
||||
LPSTR lpszMessageType;
|
||||
LPSTR lpszDateReceived; /* in YYYY/MM/DD HH:MM format */
|
||||
LPSTR lpszConversationID_NotUsed; /* conversation thread ID */
|
||||
unsigned long flFlags; /* unread,return receipt */
|
||||
lpnsMapiRecipDesc lpOriginator; /* Originator descriptor */
|
||||
unsigned long nRecipCount; /* Number of recipients */
|
||||
[size_is (nRecipCount)] lpnsMapiRecipDesc lpRecips;/* Recipient descriptors */
|
||||
unsigned long nFileCount; /* # of file attachments */
|
||||
[size_is (nFileCount)] lpnsMapiFileDesc lpFiles; /* Attachment descriptors */
|
||||
} nsMapiMessage, * lpnsMapiMessage;
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(6EDCD38E-8861-11d5-A3DD-00B0D0F3BAA7),
|
||||
helpstring("nsIMapi Inteface"),
|
||||
pointer_default(unique)
|
||||
]
|
||||
|
||||
interface nsIMapi : IUnknown
|
||||
{
|
||||
HRESULT Login([in] unsigned long aUIArg, [in, unique] LOGIN_PW_TYPE aLogin,
|
||||
[in, unique] LOGIN_PW_TYPE aPassWord, [in] unsigned long aFlags,
|
||||
[out] unsigned long *aSessionId);
|
||||
|
||||
HRESULT Initialize();
|
||||
HRESULT IsValid();
|
||||
HRESULT IsValidSession([in] unsigned long aSession);
|
||||
|
||||
HRESULT SendMail([in] unsigned long aSession, [in, unique] lpnsMapiMessage aMessage,
|
||||
[in] short aRecipCount, [in, size_is(aRecipCount)] lpnsMapiRecipDesc aRecips,
|
||||
[in] short aFileCount, [in, size_is(aFileCount)] lpnsMapiFileDesc aFiles,
|
||||
[in] unsigned long aFlags, [in] unsigned long aReserved) ;
|
||||
|
||||
HRESULT SendDocuments( [in] unsigned long aSession,
|
||||
[in, unique] LPTSTR aDelimChar, [in, unique] LPTSTR aFilePaths,
|
||||
[in, unique] LPTSTR aFileNames, [in] ULONG aFlags ) ;
|
||||
|
||||
HRESULT FindNext( [in] unsigned long aSession, [in] ULONG ulUIParam, [in, unique] LPTSTR lpszMessageType,
|
||||
[in, unique] LPTSTR lpszSeedMessageID, [in] ULONG flFlags, [in] ULONG ulReserved,
|
||||
[in] [out] char lpszMessageID[64] ) ;
|
||||
|
||||
HRESULT ReadMail( [in] unsigned long lhSession, [in] ULONG ulUIParam, [in, unique] LPTSTR lpszMessageID,
|
||||
[in] ULONG flFlags, [in] ULONG ulReserved, [out] lpnsMapiMessage *lppMessage);
|
||||
|
||||
HRESULT DeleteMail( [in] unsigned long lhSession, [in] ULONG ulUIParam, [in, unique] LPTSTR lpszMessageID,
|
||||
[in] ULONG flFlags, [in] ULONG ulReserved);
|
||||
|
||||
HRESULT SaveMail( [in] unsigned long lhSession, [in] ULONG ulUIParam, [in, unique] lpnsMapiMessage lppMessage,
|
||||
[in] ULONG flFlags, [in] ULONG ulReserved, [in, unique] LPTSTR lpszMessageID);
|
||||
|
||||
HRESULT Logoff (unsigned long aSession);
|
||||
HRESULT CleanUp();
|
||||
};
|
||||
|
||||
|
||||
|
||||
11
mailnews/mapi/mapihook/moz.build
Normal file
11
mailnews/mapi/mapihook/moz.build
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'public',
|
||||
'build',
|
||||
'src',
|
||||
]
|
||||
|
||||
11
mailnews/mapi/mapihook/public/moz.build
Normal file
11
mailnews/mapi/mapihook/public/moz.build
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIMapiSupport.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'mapihook'
|
||||
|
||||
44
mailnews/mapi/mapihook/public/nsIMapiSupport.idl
Normal file
44
mailnews/mapi/mapihook/public/nsIMapiSupport.idl
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* This interface provides support for registering Mozilla as a COM component
|
||||
* for extending the use of Mail/News through Simple MAPI.
|
||||
*
|
||||
*/
|
||||
|
||||
[noscript, uuid(2907B676-C4BD-49af-880A-E27A0616291E)]
|
||||
interface nsIMapiSupport : nsISupports {
|
||||
|
||||
/** Initiates MAPI support
|
||||
*/
|
||||
|
||||
void initializeMAPISupport();
|
||||
|
||||
/** Shuts down the MAPI support
|
||||
*/
|
||||
|
||||
void shutdownMAPISupport();
|
||||
|
||||
/** registerServer - register the mapi DLL with the desktop
|
||||
* Typically called by the window shell service when we are
|
||||
* made the default mail app
|
||||
*/
|
||||
void registerServer();
|
||||
|
||||
/** unRegisterServer - unregister the mapi DLL with the desktop
|
||||
* Typically called by the window shell service when we are
|
||||
* removed as the default mail app.
|
||||
*/
|
||||
void unRegisterServer();
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_IMAPISUPPORT_CONTRACTID "@mozilla.org/mapisupport;1"
|
||||
#define NS_IMAPISUPPORT_CLASSNAME "Mozilla MAPI Support"
|
||||
%}
|
||||
|
||||
|
||||
6
mailnews/mapi/mapihook/src/Makefile.in
Normal file
6
mailnews/mapi/mapihook/src/Makefile.in
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
CSRCS += ../build/msgMapi_i.c
|
||||
291
mailnews/mapi/mapihook/src/Registry.cpp
Normal file
291
mailnews/mapi/mapihook/src/Registry.cpp
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
|
||||
#include <objbase.h>
|
||||
#include "nsStringGlue.h"
|
||||
#include "Registry.h"
|
||||
|
||||
#define MAPI_PROXY_DLL_NAME "MapiProxy.dll"
|
||||
#define MAPI_STARTUP_ARG " /MAPIStartUp"
|
||||
#define MAX_SIZE 2048
|
||||
|
||||
// Size of a CLSID as a string
|
||||
const int CLSID_STRING_SIZE = 39;
|
||||
|
||||
// Proxy/Stub Dll Routines
|
||||
|
||||
typedef HRESULT (__stdcall ProxyServer)();
|
||||
|
||||
|
||||
// Convert a CLSID to a char string.
|
||||
|
||||
BOOL CLSIDtochar(const CLSID& clsid, char* szCLSID,
|
||||
int length)
|
||||
{
|
||||
LPOLESTR wszCLSID = NULL;
|
||||
|
||||
// Get CLSID
|
||||
HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
// Covert from wide characters to non-wide.
|
||||
wcstombs(szCLSID, wszCLSID, length);
|
||||
|
||||
// Free memory.
|
||||
CoTaskMemFree(wszCLSID);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create a key and set its value.
|
||||
|
||||
BOOL setKeyAndValue(nsAutoCString keyName, const char* subKey,
|
||||
const char* theValue)
|
||||
{
|
||||
HKEY hKey;
|
||||
BOOL retValue = TRUE;
|
||||
|
||||
nsAutoCString theKey(keyName);
|
||||
if (subKey != NULL)
|
||||
{
|
||||
theKey += "\\";
|
||||
theKey += subKey;
|
||||
}
|
||||
|
||||
// Create and open key and subkey.
|
||||
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, theKey.get(),
|
||||
0, NULL, REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, &hKey, NULL);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
return FALSE ;
|
||||
|
||||
// Set the Value.
|
||||
if (theValue != NULL)
|
||||
{
|
||||
lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)theValue,
|
||||
strlen(theValue)+1);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
retValue = FALSE;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Delete a key and all of its descendents.
|
||||
|
||||
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
|
||||
const char* lpszKeyChild) // Key to delete
|
||||
{
|
||||
// Open the child.
|
||||
HKEY hKeyChild ;
|
||||
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
|
||||
KEY_ALL_ACCESS, &hKeyChild) ;
|
||||
if (lRes != ERROR_SUCCESS)
|
||||
{
|
||||
return lRes ;
|
||||
}
|
||||
|
||||
// Enumerate all of the decendents of this child.
|
||||
FILETIME time ;
|
||||
char szBuffer[MAX_SIZE] ;
|
||||
DWORD dwSize = MAX_SIZE ;
|
||||
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
|
||||
NULL, NULL, &time) == S_OK)
|
||||
{
|
||||
// Delete the decendents of this child.
|
||||
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
|
||||
if (lRes != ERROR_SUCCESS)
|
||||
{
|
||||
// Cleanup before exiting.
|
||||
RegCloseKey(hKeyChild) ;
|
||||
return lRes;
|
||||
}
|
||||
dwSize = MAX_SIZE;
|
||||
}
|
||||
|
||||
// Close the child.
|
||||
RegCloseKey(hKeyChild) ;
|
||||
|
||||
// Delete this child.
|
||||
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
|
||||
}
|
||||
|
||||
void RegisterProxy()
|
||||
{
|
||||
HINSTANCE h = NULL;
|
||||
ProxyServer *RegisterFunc = NULL;
|
||||
|
||||
char szModule[MAX_SIZE];
|
||||
char *pTemp = NULL;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
|
||||
sizeof(szModule)/sizeof(char));
|
||||
if (dwResult == 0)
|
||||
return;
|
||||
|
||||
pTemp = strrchr(szModule, '\\');
|
||||
if (pTemp == NULL)
|
||||
return;
|
||||
|
||||
*pTemp = '\0';
|
||||
nsAutoCString proxyPath(szModule);
|
||||
|
||||
proxyPath += "\\";
|
||||
proxyPath += MAPI_PROXY_DLL_NAME;
|
||||
|
||||
h = LoadLibrary(proxyPath.get());
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
||||
RegisterFunc = (ProxyServer *) GetProcAddress(h, "DllRegisterServer");
|
||||
if (RegisterFunc)
|
||||
RegisterFunc();
|
||||
|
||||
FreeLibrary(h);
|
||||
}
|
||||
|
||||
void UnRegisterProxy()
|
||||
{
|
||||
HINSTANCE h = NULL;
|
||||
ProxyServer *UnRegisterFunc = NULL;
|
||||
|
||||
char szModule[MAX_SIZE];
|
||||
char *pTemp = NULL;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
|
||||
sizeof(szModule)/sizeof(char));
|
||||
if (dwResult == 0)
|
||||
return;
|
||||
|
||||
pTemp = strrchr(szModule, '\\');
|
||||
if (pTemp == NULL)
|
||||
return;
|
||||
|
||||
*pTemp = '\0';
|
||||
nsAutoCString proxyPath(szModule);
|
||||
|
||||
proxyPath += "\\";
|
||||
proxyPath += MAPI_PROXY_DLL_NAME;
|
||||
|
||||
h = LoadLibrary(proxyPath.get());
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
||||
UnRegisterFunc = (ProxyServer *) GetProcAddress(h, "DllUnregisterServer");
|
||||
if (UnRegisterFunc)
|
||||
UnRegisterFunc();
|
||||
|
||||
FreeLibrary(h);
|
||||
}
|
||||
|
||||
// Register the component in the registry.
|
||||
|
||||
HRESULT RegisterServer(const CLSID& clsid, // Class ID
|
||||
const char* szFriendlyName, // Friendly Name
|
||||
const char* szVerIndProgID, // Programmatic
|
||||
const char* szProgID) // IDs
|
||||
{
|
||||
HMODULE hModule = GetModuleHandle(NULL);
|
||||
char szModuleName[MAX_SIZE];
|
||||
char szCLSID[CLSID_STRING_SIZE];
|
||||
|
||||
nsAutoCString independentProgId(szVerIndProgID);
|
||||
nsAutoCString progId(szProgID);
|
||||
|
||||
DWORD dwResult = ::GetModuleFileName(hModule, szModuleName,
|
||||
sizeof(szModuleName)/sizeof(char));
|
||||
|
||||
if (dwResult == 0)
|
||||
return S_FALSE;
|
||||
|
||||
nsAutoCString moduleName(szModuleName);
|
||||
nsAutoCString registryKey("CLSID\\");
|
||||
|
||||
moduleName += MAPI_STARTUP_ARG;
|
||||
|
||||
// Convert the CLSID into a char.
|
||||
|
||||
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
|
||||
return S_FALSE;
|
||||
registryKey += szCLSID;
|
||||
|
||||
// Add the CLSID to the registry.
|
||||
if (!setKeyAndValue(registryKey, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
|
||||
if (!setKeyAndValue(registryKey, "LocalServer32", moduleName.get()))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the ProgID subkey under the CLSID key.
|
||||
if (!setKeyAndValue(registryKey, "ProgID", szProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the version-independent ProgID subkey under CLSID key.
|
||||
if (!setKeyAndValue(registryKey, "VersionIndependentProgID", szVerIndProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
|
||||
if (!setKeyAndValue(independentProgId, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(independentProgId, "CLSID", szCLSID))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(independentProgId, "CurVer", szProgID))
|
||||
return S_FALSE;
|
||||
|
||||
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
|
||||
if (!setKeyAndValue(progId, NULL, szFriendlyName))
|
||||
return S_FALSE;
|
||||
if (!setKeyAndValue(progId, "CLSID", szCLSID))
|
||||
return S_FALSE;
|
||||
|
||||
RegisterProxy();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LONG UnregisterServer(const CLSID& clsid, // Class ID
|
||||
const char* szVerIndProgID, // Programmatic
|
||||
const char* szProgID) // IDs
|
||||
{
|
||||
LONG lResult = S_OK;
|
||||
|
||||
// Convert the CLSID into a char.
|
||||
|
||||
char szCLSID[CLSID_STRING_SIZE];
|
||||
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
|
||||
return S_FALSE;
|
||||
|
||||
UnRegisterProxy();
|
||||
|
||||
nsAutoCString registryKey("CLSID\\");
|
||||
registryKey += szCLSID;
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
|
||||
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
registryKey += "\\LocalServer32";
|
||||
|
||||
// Delete only the path for this server.
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
|
||||
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
// Delete the version-independent ProgID Key.
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
|
||||
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
|
||||
return lResult;
|
||||
|
||||
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
|
||||
|
||||
return lResult;
|
||||
}
|
||||
23
mailnews/mapi/mapihook/src/Registry.h
Normal file
23
mailnews/mapi/mapihook/src/Registry.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _REGISTRY_H_
|
||||
#define _REGISTRY_H_
|
||||
|
||||
#include <objbase.h>
|
||||
|
||||
// This function will register a component in the Registry.
|
||||
|
||||
HRESULT RegisterServer(const CLSID& clsid,
|
||||
const char* szFriendlyName,
|
||||
const char* szVerIndProgID,
|
||||
const char* szProgID) ;
|
||||
|
||||
// This function will unregister a component.
|
||||
|
||||
HRESULT UnregisterServer(const CLSID& clsid,
|
||||
const char* szVerIndProgID,
|
||||
const char* szProgID) ;
|
||||
|
||||
#endif
|
||||
25
mailnews/mapi/mapihook/src/moz.build
Normal file
25
mailnews/mapi/mapihook/src/moz.build
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
'msgMapiFactory.cpp',
|
||||
'msgMapiHook.cpp',
|
||||
'msgMapiImp.cpp',
|
||||
'msgMapiMain.cpp',
|
||||
'msgMapiSupport.cpp',
|
||||
'Registry.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INCOMPLETE_EXTERNAL_LINKAGE']:
|
||||
XPCOMBinaryComponent('msgMapi')
|
||||
else:
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
OS_LIBS += [
|
||||
'ole32',
|
||||
]
|
||||
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
85
mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal file
85
mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#undef UNICODE
|
||||
#undef _UNICODE
|
||||
|
||||
#include "msgMapiFactory.h"
|
||||
#include "msgMapiImp.h"
|
||||
#include "msgMapi.h"
|
||||
|
||||
CMapiFactory ::CMapiFactory()
|
||||
: m_cRef(1)
|
||||
{
|
||||
}
|
||||
|
||||
CMapiFactory::~CMapiFactory()
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::QueryInterface(const IID& aIid, void** aPpv)
|
||||
{
|
||||
if ((aIid == IID_IUnknown) || (aIid == IID_IClassFactory))
|
||||
{
|
||||
*aPpv = static_cast<IClassFactory*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPpv = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiFactory::AddRef()
|
||||
{
|
||||
return ++m_cRef;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiFactory::Release()
|
||||
{
|
||||
int32_t temp = --m_cRef;
|
||||
if (m_cRef == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::CreateInstance(IUnknown* aUnknownOuter,
|
||||
const IID& aIid,
|
||||
void** aPpv)
|
||||
{
|
||||
// Cannot aggregate.
|
||||
|
||||
if (aUnknownOuter != nullptr)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION ;
|
||||
}
|
||||
|
||||
// Create component.
|
||||
|
||||
CMapiImp* pImp = new CMapiImp();
|
||||
if (pImp == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY ;
|
||||
}
|
||||
|
||||
// Get the requested interface.
|
||||
HRESULT hr = pImp->QueryInterface(aIid, aPpv);
|
||||
|
||||
// Release the IUnknown pointer.
|
||||
// (If QueryInterface failed, component will delete itself.)
|
||||
|
||||
pImp->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiFactory::LockServer(BOOL aLock)
|
||||
{
|
||||
return S_OK ;
|
||||
}
|
||||
39
mailnews/mapi/mapihook/src/msgMapiFactory.h
Normal file
39
mailnews/mapi/mapihook/src/msgMapiFactory.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MSG_MAPI_FACTORY_H
|
||||
#define MSG_MAPI_FACTORY_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
#include "nspr.h"
|
||||
#include "nsISupportsImpl.h" // ThreadSafeAutoRefCnt
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
class CMapiFactory : public IClassFactory
|
||||
{
|
||||
public :
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP QueryInterface (REFIID aIid, void** aPpv);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IClassFactory
|
||||
|
||||
STDMETHODIMP CreateInstance (LPUNKNOWN aUnkOuter, REFIID aIid, void **aPpv);
|
||||
STDMETHODIMP LockServer (BOOL aLock);
|
||||
|
||||
CMapiFactory ();
|
||||
|
||||
private:
|
||||
mozilla::ThreadSafeAutoRefCnt m_cRef;
|
||||
|
||||
~CMapiFactory ();
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_FACTORY_H
|
||||
|
||||
829
mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal file
829
mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal file
|
|
@ -0,0 +1,829 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#define MAPI_STARTUP_ARG "/MAPIStartUp"
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
#include <tchar.h>
|
||||
#include <direct.h>
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsIAppStartup.h"
|
||||
#include "nsIAppShellService.h"
|
||||
#include "mozIDOMWindow.h"
|
||||
#include "nsINativeAppSupport.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIMsgAttachment.h"
|
||||
#include "nsIMsgCompFields.h"
|
||||
#include "nsIMsgComposeParams.h"
|
||||
#include "nsIMsgCompose.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsIMsgSend.h"
|
||||
#include "nsIMsgComposeService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIDirectoryService.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "msgMapi.h"
|
||||
#include "msgMapiHook.h"
|
||||
#include "msgMapiSupport.h"
|
||||
#include "msgMapiMain.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsEmbedCID.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern PRLogModuleInfo *MAPI;
|
||||
|
||||
class nsMAPISendListener : public nsIMsgSendListener
|
||||
{
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
/* void OnStartSending (in string aMsgID, in uint32_t aMsgSize); */
|
||||
NS_IMETHOD OnStartSending(const char *aMsgID, uint32_t aMsgSize) { return NS_OK; }
|
||||
|
||||
/* void OnProgress (in string aMsgID, in uint32_t aProgress, in uint32_t aProgressMax); */
|
||||
NS_IMETHOD OnProgress(const char *aMsgID, uint32_t aProgress, uint32_t aProgressMax) { return NS_OK;}
|
||||
|
||||
/* void OnStatus (in string aMsgID, in wstring aMsg); */
|
||||
NS_IMETHOD OnStatus(const char *aMsgID, const char16_t *aMsg) { return NS_OK;}
|
||||
|
||||
/* void OnStopSending (in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFile returnFile); */
|
||||
NS_IMETHOD OnStopSending(const char *aMsgID, nsresult aStatus, const char16_t *aMsg,
|
||||
nsIFile *returnFile) {
|
||||
PR_CEnterMonitor(this);
|
||||
PR_CNotifyAll(this);
|
||||
m_done = true;
|
||||
PR_CExitMonitor(this);
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/* void OnSendNotPerformed */
|
||||
NS_IMETHOD OnSendNotPerformed(const char *aMsgID, nsresult aStatus)
|
||||
{
|
||||
return OnStopSending(aMsgID, aStatus, nullptr, nullptr) ;
|
||||
}
|
||||
|
||||
/* void OnGetDraftFolderURI (); */
|
||||
NS_IMETHOD OnGetDraftFolderURI(const char *aFolderURI) {return NS_OK;}
|
||||
|
||||
static nsresult CreateMAPISendListener( nsIMsgSendListener **ppListener);
|
||||
|
||||
bool IsDone() { return m_done ; }
|
||||
|
||||
protected :
|
||||
nsMAPISendListener() {
|
||||
m_done = false;
|
||||
}
|
||||
|
||||
bool m_done;
|
||||
private:
|
||||
virtual ~nsMAPISendListener() { }
|
||||
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMAPISendListener, nsIMsgSendListener)
|
||||
|
||||
nsresult nsMAPISendListener::CreateMAPISendListener( nsIMsgSendListener **ppListener)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(ppListener) ;
|
||||
|
||||
*ppListener = new nsMAPISendListener();
|
||||
if (! *ppListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*ppListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsMapiHook::isMapiService = false;
|
||||
|
||||
void nsMapiHook::CleanUp()
|
||||
{
|
||||
// This routine will be fully implemented in future
|
||||
// to cleanup mapi related stuff inside mozilla code.
|
||||
}
|
||||
|
||||
bool nsMapiHook::DisplayLoginDialog(bool aLogin, char16_t **aUsername,
|
||||
char16_t **aPassword)
|
||||
{
|
||||
nsresult rv;
|
||||
bool btnResult = false;
|
||||
|
||||
nsCOMPtr<nsIPromptService> dlgService(do_GetService(NS_PROMPTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && dlgService)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (!bundleService) return false;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
|
||||
if (NS_FAILED(rv) || !bundle) return false;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> brandBundle;
|
||||
rv = bundleService->CreateBundle(
|
||||
"chrome://branding/locale/brand.properties",
|
||||
getter_AddRefs(brandBundle));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
nsString brandName;
|
||||
rv = brandBundle->GetStringFromName(
|
||||
u"brandFullName",
|
||||
getter_Copies(brandName));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
nsString loginTitle;
|
||||
const char16_t *brandStrings[] = { brandName.get() };
|
||||
NS_NAMED_LITERAL_STRING(loginTitlePropertyTag, "loginTitle");
|
||||
const char16_t *dTitlePropertyTag = loginTitlePropertyTag.get();
|
||||
rv = bundle->FormatStringFromName(dTitlePropertyTag, brandStrings, 1,
|
||||
getter_Copies(loginTitle));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
if (aLogin)
|
||||
{
|
||||
nsString loginText;
|
||||
rv = bundle->GetStringFromName(u"loginTextwithName",
|
||||
getter_Copies(loginText));
|
||||
if (NS_FAILED(rv) || loginText.IsEmpty()) return false;
|
||||
|
||||
bool dummyValue = false;
|
||||
rv = dlgService->PromptUsernameAndPassword(nullptr, loginTitle.get(),
|
||||
loginText.get(), aUsername, aPassword,
|
||||
nullptr, &dummyValue, &btnResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
//nsString loginString;
|
||||
nsString loginText;
|
||||
const char16_t *userNameStrings[] = { *aUsername };
|
||||
|
||||
NS_NAMED_LITERAL_STRING(loginTextPropertyTag, "loginText");
|
||||
const char16_t *dpropertyTag = loginTextPropertyTag.get();
|
||||
rv = bundle->FormatStringFromName(dpropertyTag, userNameStrings, 1,
|
||||
getter_Copies(loginText));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
bool dummyValue = false;
|
||||
rv = dlgService->PromptPassword(nullptr, loginTitle.get(), loginText.get(),
|
||||
aPassword, nullptr, &dummyValue, &btnResult);
|
||||
}
|
||||
}
|
||||
|
||||
return btnResult;
|
||||
}
|
||||
|
||||
bool nsMapiHook::VerifyUserName(const nsString& aUsername, nsCString& aIdKey)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aUsername.IsEmpty())
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
nsCOMPtr<nsIArray> identities;
|
||||
rv = accountManager->GetAllIdentities(getter_AddRefs(identities));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
uint32_t numIndentities = 0;
|
||||
identities->GetLength(&numIndentities);
|
||||
|
||||
for (uint32_t i = 0; i < numIndentities; i++)
|
||||
{
|
||||
nsCOMPtr<nsIMsgIdentity> thisIdentity(do_QueryElementAt(identities, i, &rv));
|
||||
if (NS_SUCCEEDED(rv) && thisIdentity)
|
||||
{
|
||||
nsCString email;
|
||||
rv = thisIdentity->GetEmail(email);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// get the username from the email and compare with the username
|
||||
int32_t index = email.FindChar('@');
|
||||
if (index != -1)
|
||||
email.SetLength(index);
|
||||
|
||||
if (aUsername.Equals(NS_ConvertASCIItoUTF16(email)))
|
||||
return NS_SUCCEEDED(thisIdentity->GetKey(aIdKey));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsMapiHook::IsBlindSendAllowed()
|
||||
{
|
||||
bool enabled = false;
|
||||
bool warn = true;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefBranch) {
|
||||
prefBranch->GetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND, &warn);
|
||||
prefBranch->GetBoolPref(PREF_MAPI_BLIND_SEND_ENABLED, &enabled);
|
||||
}
|
||||
if (!enabled)
|
||||
return false;
|
||||
|
||||
if (!warn)
|
||||
return true; // Everything is okay.
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (!bundleService) return false;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
|
||||
if (NS_FAILED(rv) || !bundle) return false;
|
||||
|
||||
nsString warningMsg;
|
||||
rv = bundle->GetStringFromName(u"mapiBlindSendWarning",
|
||||
getter_Copies(warningMsg));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
nsString dontShowAgainMessage;
|
||||
rv = bundle->GetStringFromName(u"mapiBlindSendDontShowAgain",
|
||||
getter_Copies(dontShowAgainMessage));
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
nsCOMPtr<nsIPromptService> dlgService(do_GetService(NS_PROMPTSERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || !dlgService) return false;
|
||||
|
||||
bool continueToWarn = true;
|
||||
bool okayToContinue = false;
|
||||
dlgService->ConfirmCheck(nullptr, nullptr, warningMsg.get(), dontShowAgainMessage.get(), &continueToWarn, &okayToContinue);
|
||||
|
||||
if (!continueToWarn && okayToContinue && prefBranch)
|
||||
prefBranch->SetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND, false);
|
||||
|
||||
return okayToContinue;
|
||||
}
|
||||
|
||||
// this is used for Send without UI
|
||||
nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (!IsBlindSendAllowed())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
/** create nsIMsgComposeParams obj and other fields to populate it **/
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> hiddenWindow;
|
||||
// get parent window
|
||||
nsCOMPtr<nsIAppShellService> appService = do_GetService( "@mozilla.org/appshell/appShellService;1", &rv);
|
||||
if (NS_FAILED(rv)|| (!appService) ) return rv ;
|
||||
|
||||
rv = appService->GetHiddenDOMWindow(getter_AddRefs(hiddenWindow));
|
||||
if ( NS_FAILED(rv) ) return rv ;
|
||||
// smtp password and Logged in used IdKey from MapiConfig (session obj)
|
||||
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
|
||||
if (!pMapiConfig) return NS_ERROR_FAILURE ; // get the singelton obj
|
||||
char16_t * password = pMapiConfig->GetPassword(aSession) ;
|
||||
// password
|
||||
nsAutoCString smtpPassword;
|
||||
LossyCopyUTF16toASCII(password, smtpPassword);
|
||||
|
||||
// Id key
|
||||
nsCString MsgIdKey;
|
||||
pMapiConfig->GetIdKey(aSession, MsgIdKey);
|
||||
|
||||
// get the MsgIdentity for the above key using AccountManager
|
||||
nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService (NS_MSGACCOUNTMANAGER_CONTRACTID) ;
|
||||
if (NS_FAILED(rv) || (!accountManager) ) return rv ;
|
||||
|
||||
nsCOMPtr <nsIMsgIdentity> pMsgId ;
|
||||
rv = accountManager->GetIdentity (MsgIdKey, getter_AddRefs(pMsgId)) ;
|
||||
if (NS_FAILED(rv) ) return rv ;
|
||||
|
||||
// create a send listener to get back the send status
|
||||
nsCOMPtr <nsIMsgSendListener> sendListener ;
|
||||
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
|
||||
if (NS_FAILED(rv) || (!sendListener) ) return rv;
|
||||
|
||||
// create the compose params object
|
||||
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
|
||||
|
||||
// populate the compose params
|
||||
bool forcePlainText;
|
||||
aCompFields->GetForcePlainText(&forcePlainText);
|
||||
pMsgComposeParams->SetType(nsIMsgCompType::New);
|
||||
pMsgComposeParams->SetFormat(forcePlainText ? nsIMsgCompFormat::PlainText : nsIMsgCompFormat::HTML);
|
||||
pMsgComposeParams->SetIdentity(pMsgId);
|
||||
pMsgComposeParams->SetComposeFields(aCompFields);
|
||||
pMsgComposeParams->SetSendListener(sendListener) ;
|
||||
pMsgComposeParams->SetSmtpPassword(smtpPassword.get());
|
||||
|
||||
// create the nsIMsgCompose object to send the object
|
||||
nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgCompose) ) return rv ;
|
||||
|
||||
/** initialize nsIMsgCompose, Send the message, wait for send completion response **/
|
||||
|
||||
rv = pMsgCompose->Initialize(pMsgComposeParams, hiddenWindow, nullptr);
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// If we're in offline mode, we'll need to queue it for later. No point in trying to send it.
|
||||
return pMsgCompose->SendMsg(WeAreOffline() ? nsIMsgSend::nsMsgQueueForLater : nsIMsgSend::nsMsgDeliverNow,
|
||||
pMsgId, nullptr, nullptr, nullptr);
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// assign to interface pointer from nsCOMPtr to facilitate typecast below
|
||||
nsIMsgSendListener * pSendListener = sendListener ;
|
||||
|
||||
// we need to wait here to make sure that we return only after send is completed
|
||||
// so we will have a event loop here which will process the events till the Send IsDone.
|
||||
nsCOMPtr<nsIThread> thread(do_GetCurrentThread());
|
||||
while ( !((nsMAPISendListener *) pSendListener)->IsDone() )
|
||||
{
|
||||
PR_CEnterMonitor(pSendListener);
|
||||
PR_CWait(pSendListener, PR_MicrosecondsToInterval(1000UL));
|
||||
PR_CExitMonitor(pSendListener);
|
||||
NS_ProcessPendingEvents(thread);
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this is used to populate comp fields with Unicode data
|
||||
nsresult nsMapiHook::PopulateCompFields(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (aMessage->lpOriginator)
|
||||
aCompFields->SetFrom (NS_ConvertASCIItoUTF16((char *) aMessage->lpOriginator->lpszAddress));
|
||||
|
||||
nsAutoString To ;
|
||||
nsAutoString Cc ;
|
||||
nsAutoString Bcc ;
|
||||
|
||||
NS_NAMED_LITERAL_STRING(Comma, ",");
|
||||
|
||||
if (aMessage->lpRecips)
|
||||
{
|
||||
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
|
||||
{
|
||||
if (aMessage->lpRecips[i].lpszAddress || aMessage->lpRecips[i].lpszName)
|
||||
{
|
||||
const char *addressWithoutType = (aMessage->lpRecips[i].lpszAddress)
|
||||
? aMessage->lpRecips[i].lpszAddress : aMessage->lpRecips[i].lpszName;
|
||||
if (!PL_strncasecmp(addressWithoutType, "SMTP:", 5))
|
||||
addressWithoutType += 5;
|
||||
switch (aMessage->lpRecips[i].ulRecipClass)
|
||||
{
|
||||
case MAPI_TO :
|
||||
if (!To.IsEmpty())
|
||||
To += Comma;
|
||||
To.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break;
|
||||
|
||||
case MAPI_CC :
|
||||
if (!Cc.IsEmpty())
|
||||
Cc += Comma;
|
||||
Cc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break;
|
||||
|
||||
case MAPI_BCC :
|
||||
if (!Bcc.IsEmpty())
|
||||
Bcc += Comma;
|
||||
Bcc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("to: %s cc: %s bcc: %s \n", NS_ConvertUTF16toUTF8(To).get(), NS_ConvertUTF16toUTF8(Cc).get(), NS_ConvertUTF16toUTF8(Bcc).get()));
|
||||
// set To, Cc, Bcc
|
||||
aCompFields->SetTo (To) ;
|
||||
aCompFields->SetCc (Cc) ;
|
||||
aCompFields->SetBcc (Bcc) ;
|
||||
|
||||
// set subject
|
||||
if (aMessage->lpszSubject)
|
||||
aCompFields->SetSubject(NS_ConvertASCIItoUTF16(aMessage->lpszSubject));
|
||||
|
||||
// handle attachments as File URL
|
||||
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, true) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// set body
|
||||
if (aMessage->lpszNoteText)
|
||||
{
|
||||
nsString Body;
|
||||
CopyASCIItoUTF16(aMessage->lpszNoteText, Body);
|
||||
if (Body.IsEmpty() || Body.Last() != '\n')
|
||||
Body.AppendLiteral(CRLF);
|
||||
|
||||
// This is needed when Simple MAPI is used without a compose window.
|
||||
// See bug 1366196.
|
||||
if (Body.Find("<html>") == kNotFound)
|
||||
aCompFields->SetForcePlainText(true);
|
||||
|
||||
rv = aCompFields->SetBody(Body) ;
|
||||
}
|
||||
return rv ;
|
||||
}
|
||||
|
||||
nsresult nsMapiHook::HandleAttachments (nsIMsgCompFields * aCompFields, int32_t aFileCount,
|
||||
lpnsMapiFileDesc aFiles, BOOL aIsUnicode)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
nsAutoCString Attachments ;
|
||||
nsAutoCString TempFiles ;
|
||||
|
||||
nsCOMPtr <nsIFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pFile) ) return rv ;
|
||||
nsCOMPtr <nsIFile> pTempDir = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pTempDir) ) return rv ;
|
||||
|
||||
for (int i=0 ; i < aFileCount ; i++)
|
||||
{
|
||||
if (aFiles[i].lpszPathName)
|
||||
{
|
||||
// check if attachment exists
|
||||
if (aIsUnicode)
|
||||
pFile->InitWithPath (nsDependentString(aFiles[i].lpszPathName));
|
||||
else
|
||||
pFile->InitWithNativePath (nsDependentCString((const char*)aFiles[i].lpszPathName));
|
||||
|
||||
bool bExist ;
|
||||
rv = pFile->Exists(&bExist) ;
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("nsMapiHook::HandleAttachments: filename: %s path: %s exists = %s \n", (const char*)aFiles[i].lpszFileName, (const char*)aFiles[i].lpszPathName, bExist ? "true" : "false"));
|
||||
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
|
||||
|
||||
//Temp Directory
|
||||
nsCOMPtr <nsIFile> pTempDir;
|
||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pTempDir));
|
||||
|
||||
// create a new sub directory called moz_mapi underneath the temp directory
|
||||
pTempDir->AppendRelativePath(NS_LITERAL_STRING("moz_mapi"));
|
||||
pTempDir->Exists (&bExist) ;
|
||||
if (!bExist)
|
||||
{
|
||||
rv = pTempDir->Create(nsIFile::DIRECTORY_TYPE, 777) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
}
|
||||
|
||||
// rename or copy the existing temp file with the real file name
|
||||
|
||||
nsAutoString leafName ;
|
||||
// convert to Unicode using Platform charset
|
||||
// leafName already contains a unicode leafName from lpszPathName. If we were given
|
||||
// a value for lpszFileName, use it. Otherwise stick with leafName
|
||||
if (aFiles[i].lpszFileName)
|
||||
{
|
||||
nsAutoString wholeFileName;
|
||||
if (aIsUnicode)
|
||||
wholeFileName.Assign(aFiles[i].lpszFileName);
|
||||
else
|
||||
ConvertToUnicode(nsMsgI18NFileSystemCharset(), (char *) aFiles[i].lpszFileName, wholeFileName);
|
||||
// need to find the last '\' and find the leafname from that.
|
||||
int32_t lastSlash = wholeFileName.RFindChar(char16_t('\\'));
|
||||
if (lastSlash != kNotFound)
|
||||
leafName.Assign(Substring(wholeFileName, lastSlash + 1));
|
||||
else
|
||||
leafName.Assign(wholeFileName);
|
||||
}
|
||||
else
|
||||
pFile->GetLeafName (leafName);
|
||||
|
||||
nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
attachment->SetName(leafName);
|
||||
|
||||
nsCOMPtr<nsIFile> pTempFile;
|
||||
rv = pTempDir->Clone(getter_AddRefs(pTempFile));
|
||||
if (NS_FAILED(rv) || !pTempFile)
|
||||
return rv;
|
||||
|
||||
pTempFile->Append(leafName);
|
||||
pTempFile->Exists(&bExist);
|
||||
if (bExist)
|
||||
{
|
||||
rv = pTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0777);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
pTempFile->Remove(false); // remove so we can copy over it.
|
||||
pTempFile->GetLeafName(leafName);
|
||||
}
|
||||
// copy the file to its new location and file name
|
||||
pFile->CopyTo(pTempDir, leafName);
|
||||
// point pFile to the new location of the attachment
|
||||
pFile->InitWithFile(pTempDir);
|
||||
pFile->Append(leafName);
|
||||
|
||||
// create MsgCompose attachment object
|
||||
attachment->SetTemporary(true); // this one is a temp file so set the flag for MsgCompose
|
||||
|
||||
// now set the attachment object
|
||||
nsAutoCString pURL ;
|
||||
NS_GetURLSpecFromFile(pFile, pURL);
|
||||
attachment->SetUrl(pURL);
|
||||
|
||||
// set the file size
|
||||
int64_t fileSize;
|
||||
pFile->GetFileSize(&fileSize);
|
||||
attachment->SetSize(fileSize);
|
||||
|
||||
// add the attachment
|
||||
rv = aCompFields->AddAttachment (attachment);
|
||||
if (NS_FAILED(rv))
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("nsMapiHook::HandleAttachments: AddAttachment rv = %lx\n", rv));
|
||||
}
|
||||
}
|
||||
return rv ;
|
||||
}
|
||||
|
||||
|
||||
// this is used to convert non Unicode data and then populate comp fields
|
||||
nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (aMessage->lpOriginator)
|
||||
{
|
||||
nsAutoString From;
|
||||
From.Append(NS_ConvertASCIItoUTF16((char *) aMessage->lpOriginator->lpszAddress));
|
||||
aCompFields->SetFrom (From);
|
||||
}
|
||||
|
||||
nsAutoString To;
|
||||
nsAutoString Cc;
|
||||
nsAutoString Bcc;
|
||||
NS_NAMED_LITERAL_STRING(Comma, ",");
|
||||
if (aMessage->lpRecips)
|
||||
{
|
||||
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
|
||||
{
|
||||
if (aMessage->lpRecips[i].lpszAddress || aMessage->lpRecips[i].lpszName)
|
||||
{
|
||||
const char *addressWithoutType = (aMessage->lpRecips[i].lpszAddress)
|
||||
? aMessage->lpRecips[i].lpszAddress : aMessage->lpRecips[i].lpszName;
|
||||
if (!PL_strncasecmp(addressWithoutType, "SMTP:", 5))
|
||||
addressWithoutType += 5;
|
||||
|
||||
switch (aMessage->lpRecips[i].ulRecipClass)
|
||||
{
|
||||
case MAPI_TO :
|
||||
if (!To.IsEmpty())
|
||||
To += Comma ;
|
||||
To.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break ;
|
||||
|
||||
case MAPI_CC :
|
||||
if (!Cc.IsEmpty())
|
||||
Cc += Comma ;
|
||||
Cc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break ;
|
||||
|
||||
case MAPI_BCC :
|
||||
if (!Bcc.IsEmpty())
|
||||
Bcc += Comma ;
|
||||
Bcc.Append(NS_ConvertASCIItoUTF16(addressWithoutType));
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set To, Cc, Bcc
|
||||
aCompFields->SetTo (To) ;
|
||||
aCompFields->SetCc (Cc) ;
|
||||
aCompFields->SetBcc (Bcc) ;
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("to: %s cc: %s bcc: %s \n", NS_ConvertUTF16toUTF8(To).get(), NS_ConvertUTF16toUTF8(Cc).get(), NS_ConvertUTF16toUTF8(Bcc).get()));
|
||||
|
||||
nsAutoCString platformCharSet;
|
||||
// set subject
|
||||
if (aMessage->lpszSubject)
|
||||
{
|
||||
nsAutoString Subject ;
|
||||
if (platformCharSet.IsEmpty())
|
||||
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
|
||||
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszSubject, Subject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
aCompFields->SetSubject(Subject);
|
||||
}
|
||||
|
||||
// handle attachments as File URL
|
||||
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, false) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
// set body
|
||||
if (aMessage->lpszNoteText)
|
||||
{
|
||||
nsAutoString Body ;
|
||||
if (platformCharSet.IsEmpty())
|
||||
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
|
||||
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszNoteText, Body);
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
if (Body.IsEmpty() || Body.Last() != '\n')
|
||||
Body.AppendLiteral(CRLF);
|
||||
|
||||
// This is needed when Simple MAPI is used without a compose window.
|
||||
// See bug 1366196.
|
||||
if (Body.Find("<html>") == kNotFound)
|
||||
aCompFields->SetForcePlainText(true);
|
||||
|
||||
rv = aCompFields->SetBody(Body) ;
|
||||
}
|
||||
|
||||
#ifdef RAJIV_DEBUG
|
||||
// testing what all was set in CompFields
|
||||
printf ("To : %S \n", To.get()) ;
|
||||
printf ("CC : %S \n", Cc.get() ) ;
|
||||
printf ("BCC : %S \n", Bcc.get() ) ;
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this is used to populate the docs as attachments in the Comp fields for Send Documents
|
||||
nsresult nsMapiHook::PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields, ULONG aFlags,
|
||||
LPTSTR aDelimChar, LPTSTR aFilePaths)
|
||||
{
|
||||
nsAutoString strDelimChars ;
|
||||
nsString strFilePaths;
|
||||
nsresult rv = NS_OK ;
|
||||
bool bExist ;
|
||||
|
||||
if (aDelimChar)
|
||||
strDelimChars.Assign(aDelimChar);
|
||||
if (aFilePaths)
|
||||
strFilePaths.Assign(aFilePaths);
|
||||
|
||||
// check for comma in filename
|
||||
if (strDelimChars.FindChar(',') == kNotFound) // if comma is not in the delimiter specified by user
|
||||
{
|
||||
if (strFilePaths.FindChar(',') != kNotFound) // if comma found in filenames return error
|
||||
return NS_ERROR_FILE_INVALID_PATH;
|
||||
}
|
||||
|
||||
nsCString Attachments ;
|
||||
|
||||
// only 1 file is to be sent, no delim specified
|
||||
if (strDelimChars.IsEmpty())
|
||||
strDelimChars.AssignLiteral(";");
|
||||
|
||||
int32_t offset = 0 ;
|
||||
int32_t FilePathsLen = strFilePaths.Length() ;
|
||||
if (FilePathsLen)
|
||||
{
|
||||
nsAutoString Subject ;
|
||||
|
||||
// multiple files to be sent, delim specified
|
||||
nsCOMPtr <nsIFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pFile) ) return rv ;
|
||||
|
||||
char16_t * newFilePaths = (char16_t *) strFilePaths.get() ;
|
||||
while (offset != kNotFound)
|
||||
{
|
||||
//Temp Directory
|
||||
nsCOMPtr <nsIFile> pTempDir;
|
||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pTempDir));
|
||||
|
||||
// if not already existing, create another temp dir for mapi within Win temp dir
|
||||
// this is windows only so we can do "\\"
|
||||
pTempDir->AppendRelativePath (NS_LITERAL_STRING("moz_mapi"));
|
||||
pTempDir->Exists(&bExist) ;
|
||||
if (!bExist)
|
||||
{
|
||||
rv = pTempDir->Create(nsIFile::DIRECTORY_TYPE, 777) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
}
|
||||
|
||||
nsString RemainingPaths ;
|
||||
RemainingPaths.Assign(newFilePaths) ;
|
||||
offset = RemainingPaths.Find (strDelimChars) ;
|
||||
if (offset != kNotFound)
|
||||
{
|
||||
RemainingPaths.SetLength (offset) ;
|
||||
if ((offset + (int32_t)strDelimChars.Length()) < FilePathsLen)
|
||||
newFilePaths += offset + strDelimChars.Length() ;
|
||||
else
|
||||
offset = kNotFound;
|
||||
FilePathsLen -= offset + strDelimChars.Length();
|
||||
}
|
||||
|
||||
if (RemainingPaths[1] != ':' && RemainingPaths[1] != '\\')
|
||||
{
|
||||
char cwd[MAX_PATH];
|
||||
if (_getdcwd(_getdrive(), cwd, MAX_PATH))
|
||||
{
|
||||
nsAutoString cwdStr;
|
||||
CopyASCIItoUTF16(cwd, cwdStr);
|
||||
cwdStr.Append('\\');
|
||||
RemainingPaths.Insert(cwdStr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
pFile->InitWithPath (RemainingPaths) ;
|
||||
|
||||
rv = pFile->Exists(&bExist) ;
|
||||
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
|
||||
|
||||
// filename of the file attachment
|
||||
nsAutoString leafName ;
|
||||
pFile->GetLeafName (leafName) ;
|
||||
if(NS_FAILED(rv) || leafName.IsEmpty()) return rv ;
|
||||
|
||||
if (!Subject.IsEmpty())
|
||||
Subject.AppendLiteral(", ");
|
||||
Subject += leafName;
|
||||
|
||||
// create MsgCompose attachment object
|
||||
nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsDependentString fileNameNative(leafName.get());
|
||||
rv = pFile->CopyTo(pTempDir, fileNameNative);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// now turn pTempDir into a full file path to the temp file
|
||||
pTempDir->Append(fileNameNative);
|
||||
|
||||
// this one is a temp file so set the flag for MsgCompose
|
||||
attachment->SetTemporary(true);
|
||||
|
||||
// now set the attachment object
|
||||
nsAutoCString pURL;
|
||||
NS_GetURLSpecFromFile(pTempDir, pURL);
|
||||
attachment->SetUrl(pURL);
|
||||
|
||||
// set the file size
|
||||
int64_t fileSize;
|
||||
pFile->GetFileSize(&fileSize);
|
||||
attachment->SetSize(fileSize);
|
||||
|
||||
// add the attachment
|
||||
rv = aCompFields->AddAttachment (attachment);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = aCompFields->SetBody(Subject) ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// this used for Send with UI
|
||||
nsresult nsMapiHook::ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
// create a send listener to get back the send status
|
||||
nsCOMPtr <nsIMsgSendListener> sendListener ;
|
||||
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
|
||||
if (NS_FAILED(rv) || (!sendListener) ) return rv ;
|
||||
|
||||
// create the compose params object
|
||||
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
|
||||
|
||||
// If we found HTML, compose in HTML.
|
||||
bool forcePlainText;
|
||||
aCompFields->GetForcePlainText(&forcePlainText);
|
||||
pMsgComposeParams->SetFormat(forcePlainText ? nsIMsgCompFormat::Default : nsIMsgCompFormat::HTML);
|
||||
|
||||
// populate the compose params
|
||||
pMsgComposeParams->SetType(nsIMsgCompType::New);
|
||||
|
||||
// Never force to plain text, the default format will take care of that.
|
||||
// Undo the forcing that happened in PopulateCompFields/PopulateCompFieldsWithConversion.
|
||||
// See bug 1095629 and bug 1366196.
|
||||
aCompFields->SetForcePlainText(false);
|
||||
pMsgComposeParams->SetComposeFields(aCompFields);
|
||||
pMsgComposeParams->SetSendListener(sendListener);
|
||||
|
||||
/** get the nsIMsgComposeService object to open the compose window **/
|
||||
nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
|
||||
if (NS_FAILED(rv)|| (!compService) ) return rv ;
|
||||
|
||||
rv = compService->OpenComposeWindowWithParams(nullptr, pMsgComposeParams) ;
|
||||
if (NS_FAILED(rv)) return rv ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
33
mailnews/mapi/mapihook/src/msgMapiHook.h
Normal file
33
mailnews/mapi/mapihook/src/msgMapiHook.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MSG_MAPI_HOOK_H_
|
||||
#define MSG_MAPI_HOOK_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsMapiHook
|
||||
{
|
||||
public :
|
||||
|
||||
static bool DisplayLoginDialog(bool aLogin, char16_t **aUsername,
|
||||
char16_t **aPassword);
|
||||
static bool VerifyUserName(const nsString& aUsername, nsCString& aIdKey);
|
||||
|
||||
static bool IsBlindSendAllowed () ;
|
||||
static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFields(lpnsMapiMessage aMessage, nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
|
||||
nsIMsgCompFields * aCompFields) ;
|
||||
static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
|
||||
ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
|
||||
static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, int32_t aFileCount,
|
||||
lpnsMapiFileDesc aFiles, BOOL aIsUnicode) ;
|
||||
static void CleanUp();
|
||||
|
||||
static bool isMapiService;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_HOOK_H_
|
||||
878
mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal file
878
mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal file
|
|
@ -0,0 +1,878 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
#include "msgMapi.h"
|
||||
#include "msgMapiImp.h"
|
||||
#include "msgMapiFactory.h"
|
||||
#include "msgMapiMain.h"
|
||||
|
||||
#include "nsIMsgCompFields.h"
|
||||
#include "msgMapiHook.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsMsgCompCID.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "MailNewsTypes.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgImapMailFolder.h"
|
||||
#include <time.h>
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsMsgMessageFlags.h"
|
||||
#include "mozilla/mailnews/MimeHeaderParser.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
using namespace mozilla::mailnews;
|
||||
|
||||
PRLogModuleInfo *MAPI;
|
||||
|
||||
CMapiImp::CMapiImp()
|
||||
: m_cRef(1)
|
||||
{
|
||||
m_Lock = PR_NewLock();
|
||||
if (!MAPI)
|
||||
MAPI = PR_NewLogModule("MAPI");
|
||||
}
|
||||
|
||||
CMapiImp::~CMapiImp()
|
||||
{
|
||||
if (m_Lock)
|
||||
PR_DestroyLock(m_Lock);
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::QueryInterface(const IID& aIid, void** aPpv)
|
||||
{
|
||||
if (aIid == IID_IUnknown)
|
||||
{
|
||||
*aPpv = static_cast<nsIMapi*>(this);
|
||||
}
|
||||
else if (aIid == IID_nsIMapi)
|
||||
{
|
||||
*aPpv = static_cast<nsIMapi*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPpv = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiImp::AddRef()
|
||||
{
|
||||
return ++m_cRef;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CMapiImp::Release()
|
||||
{
|
||||
int32_t temp = --m_cRef;
|
||||
if (m_cRef == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::IsValid()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::IsValidSession(unsigned long aSession)
|
||||
{
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig && pConfig->IsSessionValid(aSession))
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::Initialize()
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if (!m_Lock)
|
||||
return E_FAIL;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
// Initialize MAPI Configuration
|
||||
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig != nullptr)
|
||||
hr = S_OK;
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin, LOGIN_PW_TYPE aPassWord,
|
||||
unsigned long aFlags, unsigned long *aSessionId)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
bool bNewSession = false;
|
||||
nsCString id_key;
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::Login using flags %d\n", aFlags));
|
||||
if (aFlags & MAPI_NEW_SESSION)
|
||||
bNewSession = true;
|
||||
|
||||
// Check For Profile Name
|
||||
if (aLogin != nullptr && aLogin[0] != '\0')
|
||||
{
|
||||
if (!nsMapiHook::VerifyUserName(nsString(aLogin), id_key))
|
||||
{
|
||||
*aSessionId = MAPI_E_LOGIN_FAILURE;
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::Login failed for username %s\n", aLogin));
|
||||
NS_ASSERTION(false, "failed verifying user name");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// get default account
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIMsgAccountManager> accountManager =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,MAPI_E_LOGIN_FAILURE);
|
||||
nsCOMPtr <nsIMsgAccount> account;
|
||||
nsCOMPtr <nsIMsgIdentity> identity;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(account));
|
||||
NS_ENSURE_SUCCESS(rv,MAPI_E_LOGIN_FAILURE);
|
||||
rv = account->GetDefaultIdentity(getter_AddRefs(identity));
|
||||
NS_ENSURE_SUCCESS(rv,MAPI_E_LOGIN_FAILURE);
|
||||
if (!identity)
|
||||
return MAPI_E_LOGIN_FAILURE;
|
||||
identity->GetKey(id_key);
|
||||
}
|
||||
|
||||
// finally register(create) the session.
|
||||
uint32_t nSession_Id;
|
||||
int16_t nResult = 0;
|
||||
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
if (pConfig != nullptr)
|
||||
nResult = pConfig->RegisterSession(aUIArg, wwc(aLogin), wwc(aPassWord),
|
||||
(aFlags & MAPI_FORCE_DOWNLOAD), bNewSession,
|
||||
&nSession_Id, id_key.get());
|
||||
switch (nResult)
|
||||
{
|
||||
case -1 :
|
||||
{
|
||||
*aSessionId = MAPI_E_TOO_MANY_SESSIONS;
|
||||
return hr;
|
||||
}
|
||||
case 0 :
|
||||
{
|
||||
*aSessionId = MAPI_E_INSUFFICIENT_MEMORY;
|
||||
return hr;
|
||||
}
|
||||
default :
|
||||
{
|
||||
*aSessionId = nSession_Id;
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::Login succeeded\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
|
||||
short aRecipCount, lpnsMapiRecipDesc aRecips , short aFileCount, lpnsMapiFileDesc aFiles ,
|
||||
unsigned long aFlags, unsigned long aReserved)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail using flags %d\n", aFlags));
|
||||
// Assign the pointers in the aMessage struct to the array of Recips and Files
|
||||
// received here from MS COM. These are used in BlindSendMail and ShowCompWin fns
|
||||
aMessage->lpRecips = aRecips ;
|
||||
aMessage->lpFiles = aFiles ;
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail flags=%x subject: %s sender: %s\n",
|
||||
aFlags, (char *) aMessage->lpszSubject, (aMessage->lpOriginator) ? aMessage->lpOriginator->lpszAddress : ""));
|
||||
|
||||
/** create nsIMsgCompFields obj and populate it **/
|
||||
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
|
||||
|
||||
if (aFlags & MAPI_UNICODE)
|
||||
rv = nsMapiHook::PopulateCompFields(aMessage, pCompFields) ;
|
||||
else
|
||||
rv = nsMapiHook::PopulateCompFieldsWithConversion(aMessage, pCompFields) ;
|
||||
|
||||
if (NS_SUCCEEDED (rv))
|
||||
{
|
||||
// see flag to see if UI needs to be brought up
|
||||
if (!(aFlags & MAPI_DIALOG))
|
||||
{
|
||||
rv = nsMapiHook::BlindSendMail(aSession, pCompFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
|
||||
}
|
||||
}
|
||||
|
||||
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMapiImp::SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
|
||||
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendDocument using flags %d\n", aFlags));
|
||||
/** create nsIMsgCompFields obj and populate it **/
|
||||
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
|
||||
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
|
||||
|
||||
if (aFilePaths)
|
||||
{
|
||||
rv = nsMapiHook::PopulateCompFieldsForSendDocs(pCompFields, aFlags, aDelimChar, aFilePaths) ;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED (rv))
|
||||
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
|
||||
else
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendDocument error rv = %lx, paths = %s names = %s\n", rv, aFilePaths, aFileNames));
|
||||
|
||||
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
|
||||
}
|
||||
|
||||
nsresult CMapiImp::GetDefaultInbox(nsIMsgFolder **inboxFolder)
|
||||
{
|
||||
// get default account
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsIMsgAccountManager> accountManager =
|
||||
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr <nsIMsgAccount> account;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(account));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// get incoming server
|
||||
nsCOMPtr <nsIMsgIncomingServer> server;
|
||||
rv = account->GetIncomingServer(getter_AddRefs(server));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCString type;
|
||||
rv = server->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// we only care about imap and pop3
|
||||
if (type.EqualsLiteral("imap") || type.EqualsLiteral("pop3"))
|
||||
{
|
||||
// imap and pop3 account should have an Inbox
|
||||
nsCOMPtr<nsIMsgFolder> rootMsgFolder;
|
||||
rv = server->GetRootMsgFolder(getter_AddRefs(rootMsgFolder));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (!rootMsgFolder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rootMsgFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, inboxFolder);
|
||||
if (!*inboxFolder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Encapsulate the XP DB stuff required to enumerate messages
|
||||
|
||||
class MsgMapiListContext
|
||||
{
|
||||
public:
|
||||
MsgMapiListContext () {}
|
||||
~MsgMapiListContext ();
|
||||
|
||||
nsresult OpenDatabase (nsIMsgFolder *folder);
|
||||
|
||||
nsMsgKey GetNext ();
|
||||
nsresult MarkRead (nsMsgKey key, bool read);
|
||||
|
||||
lpnsMapiMessage GetMessage (nsMsgKey, unsigned long flFlags);
|
||||
bool IsIMAPHost(void);
|
||||
bool DeleteMessage(nsMsgKey key);
|
||||
|
||||
protected:
|
||||
|
||||
char *ConvertDateToMapiFormat (time_t);
|
||||
char *ConvertBodyToMapiFormat (nsIMsgDBHdr *hdr);
|
||||
void ConvertRecipientsToMapiFormat(const nsCOMArray<msgIAddressObject> &ourRecips,
|
||||
lpnsMapiRecipDesc mapiRecips,
|
||||
int mapiRecipClass);
|
||||
|
||||
nsCOMPtr <nsIMsgFolder> m_folder;
|
||||
nsCOMPtr <nsIMsgDatabase> m_db;
|
||||
nsCOMPtr <nsISimpleEnumerator> m_msgEnumerator;
|
||||
};
|
||||
|
||||
|
||||
LONG CMapiImp::InitContext(unsigned long session, MsgMapiListContext **listContext)
|
||||
{
|
||||
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
|
||||
if (!pMapiConfig)
|
||||
return MAPI_E_FAILURE ; // get the singelton obj
|
||||
*listContext = (MsgMapiListContext *) pMapiConfig->GetMapiListContext(session);
|
||||
// This is the first message
|
||||
if (!*listContext)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolder> inboxFolder;
|
||||
nsresult rv = GetDefaultInbox(getter_AddRefs(inboxFolder));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ASSERTION(false, "in init context, no inbox");
|
||||
return(MAPI_E_NO_MESSAGES);
|
||||
}
|
||||
|
||||
*listContext = new MsgMapiListContext;
|
||||
if (!*listContext)
|
||||
return MAPI_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
rv = (*listContext)->OpenDatabase(inboxFolder);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
pMapiConfig->SetMapiListContext(session, NULL);
|
||||
delete *listContext;
|
||||
NS_ASSERTION(false, "in init context, unable to open db");
|
||||
return MAPI_E_NO_MESSAGES;
|
||||
}
|
||||
else
|
||||
pMapiConfig->SetMapiListContext(session, *listContext);
|
||||
}
|
||||
return SUCCESS_SUCCESS;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::FindNext(unsigned long aSession, unsigned long ulUIParam, LPTSTR lpszMessageType,
|
||||
LPTSTR lpszSeedMessageID, unsigned long flFlags, unsigned long ulReserved,
|
||||
unsigned char lpszMessageID[64])
|
||||
|
||||
{
|
||||
//
|
||||
// If this is true, then this is the first call to this FindNext function
|
||||
// and we should start the enumeration operation.
|
||||
//
|
||||
|
||||
*lpszMessageID = '\0';
|
||||
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
|
||||
if (!pMapiConfig)
|
||||
{
|
||||
NS_ASSERTION(false, "failed to get config in findnext");
|
||||
return MAPI_E_FAILURE ; // get the singelton obj
|
||||
}
|
||||
MsgMapiListContext *listContext;
|
||||
LONG ret = InitContext(aSession, &listContext);
|
||||
if (ret != SUCCESS_SUCCESS)
|
||||
{
|
||||
NS_ASSERTION(false, "init context failed");
|
||||
return ret;
|
||||
}
|
||||
NS_ASSERTION(listContext, "initContext returned null context");
|
||||
if (listContext)
|
||||
{
|
||||
// NS_ASSERTION(false, "find next init context succeeded");
|
||||
nsMsgKey nextKey = listContext->GetNext();
|
||||
if (nextKey == nsMsgKey_None)
|
||||
{
|
||||
pMapiConfig->SetMapiListContext(aSession, NULL);
|
||||
delete listContext;
|
||||
return(MAPI_E_NO_MESSAGES);
|
||||
}
|
||||
|
||||
// TRACE("MAPI: ProcessMAPIFindNext() Found message id = %d\n", nextKey);
|
||||
|
||||
sprintf((char *) lpszMessageID, "%d", nextKey);
|
||||
}
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::FindNext returning key %s\n", (char *) lpszMessageID));
|
||||
return(SUCCESS_SUCCESS);
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::ReadMail(unsigned long aSession, unsigned long ulUIParam, LPTSTR lpszMessageID,
|
||||
unsigned long flFlags, unsigned long ulReserved, lpnsMapiMessage *lppMessage)
|
||||
{
|
||||
nsresult irv;
|
||||
nsAutoCString keyString((char *) lpszMessageID);
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::ReadMail asking for key %s\n", (char *) lpszMessageID));
|
||||
nsMsgKey msgKey = keyString.ToInteger(&irv);
|
||||
if (NS_FAILED(irv))
|
||||
{
|
||||
NS_ASSERTION(false, "invalid lpszMessageID");
|
||||
return MAPI_E_INVALID_MESSAGE;
|
||||
}
|
||||
MsgMapiListContext *listContext;
|
||||
LONG ret = InitContext(aSession, &listContext);
|
||||
if (ret != SUCCESS_SUCCESS)
|
||||
{
|
||||
NS_ASSERTION(false, "init context failed in ReadMail");
|
||||
return ret;
|
||||
}
|
||||
*lppMessage = listContext->GetMessage (msgKey, flFlags);
|
||||
NS_ASSERTION(*lppMessage, "get message failed");
|
||||
|
||||
return (*lppMessage) ? SUCCESS_SUCCESS : E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMapiImp::DeleteMail(unsigned long aSession, unsigned long ulUIParam, LPTSTR lpszMessageID,
|
||||
unsigned long flFlags, unsigned long ulReserved)
|
||||
{
|
||||
nsresult irv;
|
||||
nsAutoCString keyString((char *) lpszMessageID);
|
||||
nsMsgKey msgKey = keyString.ToInteger(&irv);
|
||||
// XXX Why do we return success on failure?
|
||||
if (NS_FAILED(irv))
|
||||
return SUCCESS_SUCCESS;
|
||||
MsgMapiListContext *listContext;
|
||||
LONG ret = InitContext(aSession, &listContext);
|
||||
if (ret != SUCCESS_SUCCESS)
|
||||
return ret;
|
||||
return (listContext->DeleteMessage(msgKey)) ? SUCCESS_SUCCESS : MAPI_E_INVALID_MESSAGE;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::SaveMail(unsigned long aSession, unsigned long ulUIParam, lpnsMapiMessage lppMessage,
|
||||
unsigned long flFlags, unsigned long ulReserved, LPTSTR lpszMessageID)
|
||||
{
|
||||
MsgMapiListContext *listContext;
|
||||
LONG ret = InitContext(aSession, &listContext);
|
||||
if (ret != SUCCESS_SUCCESS)
|
||||
return ret;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMapiImp::Logoff (unsigned long aSession)
|
||||
{
|
||||
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
|
||||
|
||||
if (pConfig->UnRegisterSession((uint32_t)aSession))
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMapiImp::CleanUp()
|
||||
{
|
||||
nsMapiHook::CleanUp();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_NAME_LEN 256
|
||||
|
||||
|
||||
MsgMapiListContext::~MsgMapiListContext ()
|
||||
{
|
||||
if (m_db)
|
||||
m_db->Close(false);
|
||||
}
|
||||
|
||||
|
||||
nsresult MsgMapiListContext::OpenDatabase (nsIMsgFolder *folder)
|
||||
{
|
||||
nsresult dbErr = NS_ERROR_FAILURE;
|
||||
if (folder)
|
||||
{
|
||||
m_folder = folder;
|
||||
dbErr = folder->GetMsgDatabase(getter_AddRefs(m_db));
|
||||
if (m_db)
|
||||
dbErr = m_db->EnumerateMessages(getter_AddRefs(m_msgEnumerator));
|
||||
}
|
||||
return dbErr;
|
||||
}
|
||||
|
||||
bool
|
||||
MsgMapiListContext::IsIMAPHost(void)
|
||||
{
|
||||
if (!m_folder)
|
||||
return FALSE;
|
||||
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_folder);
|
||||
|
||||
return imapFolder != nullptr;
|
||||
}
|
||||
|
||||
nsMsgKey MsgMapiListContext::GetNext ()
|
||||
{
|
||||
nsMsgKey key = nsMsgKey_None;
|
||||
bool keepTrying = TRUE;
|
||||
|
||||
// NS_ASSERTION (m_msgEnumerator && m_db, "need enumerator and db");
|
||||
if (m_msgEnumerator && m_db)
|
||||
{
|
||||
|
||||
do
|
||||
{
|
||||
keepTrying = FALSE;
|
||||
nsCOMPtr <nsISupports> hdrISupports;
|
||||
nsCOMPtr <nsIMsgDBHdr> msgHdr;
|
||||
if (NS_SUCCEEDED(m_msgEnumerator->GetNext(getter_AddRefs(hdrISupports))) && hdrISupports)
|
||||
{
|
||||
msgHdr = do_QueryInterface(hdrISupports);
|
||||
msgHdr->GetMessageKey(&key);
|
||||
|
||||
// Check here for IMAP message...if not, just return...
|
||||
if (!IsIMAPHost())
|
||||
return key;
|
||||
|
||||
// If this is an IMAP message, we have to make sure we have a valid
|
||||
// body to work with.
|
||||
uint32_t flags = 0;
|
||||
|
||||
(void) msgHdr->GetFlags(&flags);
|
||||
if (flags & nsMsgMessageFlags::Offline)
|
||||
return key;
|
||||
|
||||
// Ok, if we get here, we have an IMAP message without a body!
|
||||
// We need to keep trying by calling the GetNext member recursively...
|
||||
keepTrying = TRUE;
|
||||
}
|
||||
} while (keepTrying);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
nsresult MsgMapiListContext::MarkRead (nsMsgKey key, bool read)
|
||||
{
|
||||
nsresult err = NS_ERROR_FAILURE;
|
||||
NS_ASSERTION(m_db, "no db");
|
||||
if (m_db)
|
||||
err = m_db->MarkRead (key, read, nullptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
lpnsMapiMessage MsgMapiListContext::GetMessage (nsMsgKey key, unsigned long flFlags)
|
||||
{
|
||||
lpnsMapiMessage message = (lpnsMapiMessage) CoTaskMemAlloc (sizeof(nsMapiMessage));
|
||||
memset(message, 0, sizeof(nsMapiMessage));
|
||||
if (message)
|
||||
{
|
||||
nsCString subject;
|
||||
nsCString author;
|
||||
nsCOMPtr <nsIMsgDBHdr> msgHdr;
|
||||
|
||||
nsresult rv = m_db->GetMsgHdrForKey (key, getter_AddRefs(msgHdr));
|
||||
if (msgHdr)
|
||||
{
|
||||
msgHdr->GetSubject (getter_Copies(subject));
|
||||
message->lpszSubject = (char *) CoTaskMemAlloc(subject.Length() + 1);
|
||||
strcpy((char *) message->lpszSubject, subject.get());
|
||||
uint32_t date;
|
||||
(void) msgHdr->GetDateInSeconds(&date);
|
||||
message->lpszDateReceived = ConvertDateToMapiFormat (date);
|
||||
|
||||
// Pull out the flags info
|
||||
// anything to do with MAPI_SENT? Since we're only reading the Inbox, I guess not
|
||||
uint32_t ourFlags;
|
||||
(void) msgHdr->GetFlags(&ourFlags);
|
||||
if (!(ourFlags & nsMsgMessageFlags::Read))
|
||||
message->flFlags |= MAPI_UNREAD;
|
||||
if (ourFlags & (nsMsgMessageFlags::MDNReportNeeded | nsMsgMessageFlags::MDNReportSent))
|
||||
message->flFlags |= MAPI_RECEIPT_REQUESTED;
|
||||
|
||||
// Pull out the author/originator info
|
||||
message->lpOriginator = (lpnsMapiRecipDesc) CoTaskMemAlloc (sizeof(nsMapiRecipDesc));
|
||||
memset(message->lpOriginator, 0, sizeof(nsMapiRecipDesc));
|
||||
if (message->lpOriginator)
|
||||
{
|
||||
msgHdr->GetAuthor (getter_Copies(author));
|
||||
ConvertRecipientsToMapiFormat(EncodedHeader(author),
|
||||
message->lpOriginator, MAPI_ORIG);
|
||||
}
|
||||
// Pull out the To/CC info
|
||||
nsCString recipients, ccList;
|
||||
msgHdr->GetRecipients(getter_Copies(recipients));
|
||||
msgHdr->GetCcList(getter_Copies(ccList));
|
||||
|
||||
nsCOMArray<msgIAddressObject> parsedToRecips = EncodedHeader(recipients);
|
||||
nsCOMArray<msgIAddressObject> parsedCCRecips = EncodedHeader(ccList);
|
||||
uint32_t numToRecips = parsedToRecips.Length();
|
||||
uint32_t numCCRecips = parsedCCRecips.Length();
|
||||
|
||||
message->lpRecips = (lpnsMapiRecipDesc) CoTaskMemAlloc ((numToRecips + numCCRecips) * sizeof(MapiRecipDesc));
|
||||
memset(message->lpRecips, 0, (numToRecips + numCCRecips) * sizeof(MapiRecipDesc));
|
||||
if (message->lpRecips)
|
||||
{
|
||||
ConvertRecipientsToMapiFormat(parsedToRecips, message->lpRecips,
|
||||
MAPI_TO);
|
||||
ConvertRecipientsToMapiFormat(parsedCCRecips,
|
||||
&message->lpRecips[numToRecips], MAPI_CC);
|
||||
}
|
||||
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("MsgMapiListContext::GetMessage flags=%x subject %s date %s sender %s\n",
|
||||
flFlags, (char *) message->lpszSubject,(char *) message->lpszDateReceived, author.get()) );
|
||||
|
||||
// Convert any body text that we have locally
|
||||
if (!(flFlags & MAPI_ENVELOPE_ONLY))
|
||||
message->lpszNoteText = (char *) ConvertBodyToMapiFormat (msgHdr);
|
||||
|
||||
}
|
||||
if (! (flFlags & (MAPI_PEEK | MAPI_ENVELOPE_ONLY)))
|
||||
m_db->MarkRead(key, true, nullptr);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
char *MsgMapiListContext::ConvertDateToMapiFormat (time_t ourTime)
|
||||
{
|
||||
char *date = (char*) CoTaskMemAlloc(32);
|
||||
if (date)
|
||||
{
|
||||
// MAPI time format is YYYY/MM/DD HH:MM
|
||||
// Note that we're not using XP_StrfTime because that localizes the time format,
|
||||
// and the way I read the MAPI spec is that their format is canonical, not localized.
|
||||
struct tm *local = localtime (&ourTime);
|
||||
if (local)
|
||||
strftime (date, 32, "%Y/%m/%d %I:%M", local); //use %H if hours should be 24 hour format
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
void MsgMapiListContext::ConvertRecipientsToMapiFormat(
|
||||
const nsCOMArray<msgIAddressObject> &recipients,
|
||||
lpnsMapiRecipDesc mapiRecips, int mapiRecipClass)
|
||||
{
|
||||
nsTArray<nsCString> names, addresses;
|
||||
ExtractAllAddresses(recipients, UTF16ArrayAdapter<>(names),
|
||||
UTF16ArrayAdapter<>(addresses));
|
||||
|
||||
size_t numAddresses = names.Length();
|
||||
for (size_t i = 0; i < numAddresses; i++)
|
||||
{
|
||||
if (!names[i].IsEmpty())
|
||||
{
|
||||
mapiRecips[i].lpszName = (char *) CoTaskMemAlloc(names[i].Length() + 1);
|
||||
if (mapiRecips[i].lpszName)
|
||||
strcpy((char *)mapiRecips[i].lpszName, names[i].get());
|
||||
}
|
||||
if (!addresses[i].IsEmpty())
|
||||
{
|
||||
mapiRecips[i].lpszName = (char *) CoTaskMemAlloc(addresses[i].Length() + 1);
|
||||
if (mapiRecips[i].lpszName)
|
||||
strcpy((char *)mapiRecips[i].lpszName, addresses[i].get());
|
||||
}
|
||||
mapiRecips[i].ulRecipClass = mapiRecipClass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *MsgMapiListContext::ConvertBodyToMapiFormat (nsIMsgDBHdr *hdr)
|
||||
{
|
||||
const int kBufLen = 64000; // I guess we only return the first 64K of a message.
|
||||
#define EMPTY_MESSAGE_LINE(buf) (buf[0] == '\r' || buf[0] == '\n' || buf[0] == '\0')
|
||||
|
||||
nsCOMPtr <nsIMsgFolder> folder;
|
||||
hdr->GetFolder(getter_AddRefs(folder));
|
||||
if (!folder)
|
||||
return nullptr;
|
||||
|
||||
nsCOMPtr <nsIInputStream> inputStream;
|
||||
nsCOMPtr <nsIFile> localFile;
|
||||
folder->GetFilePath(getter_AddRefs(localFile));
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFileInputStream> fileStream = do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
rv = fileStream->Init(localFile, PR_RDONLY, 0664, false); //just have to read the messages
|
||||
inputStream = do_QueryInterface(fileStream);
|
||||
|
||||
if (inputStream)
|
||||
{
|
||||
nsCOMPtr <nsILineInputStream> fileLineStream = do_QueryInterface(inputStream);
|
||||
if (!fileLineStream)
|
||||
return nullptr;
|
||||
// ### really want to skip past headers...
|
||||
uint64_t messageOffset;
|
||||
uint32_t lineCount;
|
||||
hdr->GetMessageOffset(&messageOffset);
|
||||
hdr->GetLineCount(&lineCount);
|
||||
nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(inputStream);
|
||||
seekableStream->Seek(PR_SEEK_SET, messageOffset);
|
||||
bool hasMore = true;
|
||||
nsAutoCString curLine;
|
||||
nsresult rv = NS_OK;
|
||||
while (hasMore) // advance past message headers
|
||||
{
|
||||
nsresult rv = fileLineStream->ReadLine(curLine, &hasMore);
|
||||
if (NS_FAILED(rv) || EMPTY_MESSAGE_LINE(curLine))
|
||||
break;
|
||||
}
|
||||
uint32_t msgSize;
|
||||
hdr->GetMessageSize(&msgSize);
|
||||
if (msgSize > kBufLen)
|
||||
msgSize = kBufLen - 1;
|
||||
// this is too big, since it includes the msg hdr size...oh well
|
||||
char *body = (char*) CoTaskMemAlloc (msgSize + 1);
|
||||
|
||||
if (!body)
|
||||
return nullptr;
|
||||
int32_t bytesCopied = 0;
|
||||
for (hasMore = TRUE; lineCount > 0 && hasMore && NS_SUCCEEDED(rv); lineCount--)
|
||||
{
|
||||
rv = fileLineStream->ReadLine(curLine, &hasMore);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
curLine.Append(CRLF);
|
||||
// make sure we have room left
|
||||
if (bytesCopied + curLine.Length() < msgSize)
|
||||
{
|
||||
strcpy(body + bytesCopied, curLine.get());
|
||||
bytesCopied += curLine.Length();
|
||||
}
|
||||
}
|
||||
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("ConvertBodyToMapiFormat size=%x allocated size %x body = %100.100s\n",
|
||||
bytesCopied, msgSize + 1, (char *) body) );
|
||||
body[bytesCopied] = '\0'; // rhp - fix last line garbage...
|
||||
return body;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
// MSGMAPI API implementation
|
||||
|
||||
|
||||
|
||||
static void msg_FreeMAPIFile(lpMapiFileDesc f)
|
||||
{
|
||||
if (f)
|
||||
{
|
||||
CoTaskMemFree(f->lpszPathName);
|
||||
CoTaskMemFree(f->lpszFileName);
|
||||
}
|
||||
}
|
||||
|
||||
static void msg_FreeMAPIRecipient(lpMapiRecipDesc rd)
|
||||
{
|
||||
if (rd)
|
||||
{
|
||||
if (rd->lpszName)
|
||||
CoTaskMemFree(rd->lpszName);
|
||||
if (rd->lpszAddress)
|
||||
CoTaskMemFree(rd->lpszAddress);
|
||||
// CoTaskMemFree(rd->lpEntryID);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void MSG_FreeMapiMessage (lpMapiMessage msg)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (msg)
|
||||
{
|
||||
CoTaskMemFree(msg->lpszSubject);
|
||||
CoTaskMemFree(msg->lpszNoteText);
|
||||
CoTaskMemFree(msg->lpszMessageType);
|
||||
CoTaskMemFree(msg->lpszDateReceived);
|
||||
CoTaskMemFree(msg->lpszConversationID);
|
||||
|
||||
if (msg->lpOriginator)
|
||||
msg_FreeMAPIRecipient(msg->lpOriginator);
|
||||
|
||||
for (i=0; i<msg->nRecipCount; i++)
|
||||
if (&(msg->lpRecips[i]) != nullptr)
|
||||
msg_FreeMAPIRecipient(&(msg->lpRecips[i]));
|
||||
|
||||
CoTaskMemFree(msg->lpRecips);
|
||||
|
||||
for (i=0; i<msg->nFileCount; i++)
|
||||
if (&(msg->lpFiles[i]) != nullptr)
|
||||
msg_FreeMAPIFile(&(msg->lpFiles[i]));
|
||||
|
||||
CoTaskMemFree(msg->lpFiles);
|
||||
|
||||
CoTaskMemFree(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" bool MsgMarkMapiMessageRead (nsIMsgFolder *folder, nsMsgKey key, bool read)
|
||||
{
|
||||
bool success = FALSE;
|
||||
MsgMapiListContext *context = new MsgMapiListContext();
|
||||
if (context)
|
||||
{
|
||||
if (NS_SUCCEEDED(context->OpenDatabase(folder)))
|
||||
{
|
||||
if (NS_SUCCEEDED(context->MarkRead (key, read)))
|
||||
success = TRUE;
|
||||
}
|
||||
delete context;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
MsgMapiListContext::DeleteMessage(nsMsgKey key)
|
||||
{
|
||||
if (!m_db)
|
||||
return FALSE;
|
||||
|
||||
if ( !IsIMAPHost() )
|
||||
{
|
||||
return NS_SUCCEEDED((m_db->DeleteMessages(1, &key, nullptr)));
|
||||
}
|
||||
#if 0
|
||||
else if ( m_folder->GetIMAPFolderInfoMail() )
|
||||
{
|
||||
AutoTArray<nsMsgKey, 1> messageKeys;
|
||||
messageKeys.AppendElement(key);
|
||||
|
||||
(m_folder->GetIMAPFolderInfoMail())->DeleteSpecifiedMessages(pane, messageKeys, nsMsgKey_None);
|
||||
m_db->DeleteMessage(key, nullptr, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return TRUE on success, FALSE on failure */
|
||||
extern "C" bool MSG_DeleteMapiMessage(nsIMsgFolder *folder, nsMsgKey key)
|
||||
{
|
||||
bool success = FALSE;
|
||||
MsgMapiListContext *context = new MsgMapiListContext();
|
||||
if (context)
|
||||
{
|
||||
if (NS_SUCCEEDED(context->OpenDatabase(folder)))
|
||||
{
|
||||
success = context->DeleteMessage(key);
|
||||
}
|
||||
|
||||
delete context;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
77
mailnews/mapi/mapihook/src/msgMapiImp.h
Normal file
77
mailnews/mapi/mapihook/src/msgMapiImp.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MSG_MAPI_IMP_H
|
||||
#define MSG_MAPI_IMP_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <mapi.h>
|
||||
#include "msgMapi.h"
|
||||
#include "nspr.h"
|
||||
#include "nscore.h"
|
||||
#include "nsISupportsImpl.h" // ThreadSafeAutoRefCnt
|
||||
|
||||
class nsIMsgFolder;
|
||||
class MsgMapiListContext;
|
||||
|
||||
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5, {0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
|
||||
|
||||
// this class implements the MS COM interface nsIMapi that provides the methods
|
||||
// called by mapi32.dll to perform the mail operations as specified by MAPI.
|
||||
// These class methods in turn use the Mozilla Mail XPCOM interfaces to do so.
|
||||
class CMapiImp : public nsIMapi
|
||||
{
|
||||
|
||||
public :
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP QueryInterface(const IID& aIid, void** aPpv);
|
||||
STDMETHODIMP_(ULONG) AddRef();
|
||||
STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// Interface INsMapi
|
||||
|
||||
STDMETHODIMP Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
|
||||
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
|
||||
unsigned long *aSessionId);
|
||||
|
||||
STDMETHODIMP SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
|
||||
short aRecipCount, lpnsMapiRecipDesc aRecips ,
|
||||
short aFileCount, lpnsMapiFileDesc aFiles ,
|
||||
unsigned long aFlags, unsigned long aReserved) ;
|
||||
|
||||
STDMETHODIMP SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
|
||||
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags);
|
||||
|
||||
STDMETHODIMP FindNext( unsigned long aSession, unsigned long ulUIParam, LPTSTR lpszMessageType,
|
||||
LPTSTR lpszSeedMessageID, unsigned long flFlags, unsigned long ulReserved,
|
||||
unsigned char lpszMessageID[64] );
|
||||
|
||||
STDMETHODIMP ReadMail(unsigned long lhSession, unsigned long ulUIParam, LPTSTR lpszMessageID,
|
||||
unsigned long flFlags, unsigned long ulReserved, lpnsMapiMessage *lppMessage);
|
||||
STDMETHODIMP DeleteMail(unsigned long lhSession, unsigned long ulUIParam, LPTSTR lpszMessageID,
|
||||
unsigned long flFlags, unsigned long ulReserved);
|
||||
STDMETHODIMP SaveMail(unsigned long lhSession, unsigned long ulUIParam, lpnsMapiMessage lppMessage,
|
||||
unsigned long flFlags, unsigned long ulReserved, LPTSTR lpszMessageID);
|
||||
|
||||
STDMETHODIMP Initialize();
|
||||
STDMETHODIMP IsValid();
|
||||
STDMETHODIMP IsValidSession(unsigned long aSession);
|
||||
|
||||
STDMETHODIMP Logoff (unsigned long aSession);
|
||||
STDMETHODIMP CleanUp();
|
||||
|
||||
CMapiImp();
|
||||
~CMapiImp();
|
||||
|
||||
LONG InitContext(unsigned long session, MsgMapiListContext **listContext);
|
||||
nsresult GetDefaultInbox(nsIMsgFolder **inboxFolder);
|
||||
|
||||
private :
|
||||
PRLock *m_Lock;
|
||||
mozilla::ThreadSafeAutoRefCnt m_cRef;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_IMP_H
|
||||
306
mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal file
306
mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapi.h>
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsComposeStrings.h"
|
||||
#include "msgMapiMain.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
nsMAPIConfiguration *nsMAPIConfiguration::m_pSelfRef = nullptr;
|
||||
uint32_t nsMAPIConfiguration::session_generator = 0;
|
||||
uint32_t nsMAPIConfiguration::sessionCount = 0;
|
||||
|
||||
nsMAPIConfiguration *nsMAPIConfiguration::GetMAPIConfiguration()
|
||||
{
|
||||
if (m_pSelfRef == nullptr)
|
||||
m_pSelfRef = new nsMAPIConfiguration();
|
||||
|
||||
return m_pSelfRef;
|
||||
}
|
||||
|
||||
nsMAPIConfiguration::nsMAPIConfiguration()
|
||||
: m_nMaxSessions(MAX_SESSIONS)
|
||||
{
|
||||
m_Lock = PR_NewLock();
|
||||
}
|
||||
|
||||
nsMAPIConfiguration::~nsMAPIConfiguration()
|
||||
{
|
||||
if (m_Lock)
|
||||
PR_DestroyLock(m_Lock);
|
||||
}
|
||||
|
||||
void nsMAPIConfiguration::OpenConfiguration()
|
||||
{
|
||||
// No. of max. sessions is set to MAX_SESSIONS. In future
|
||||
// if it is decided to have configuration (registry)
|
||||
// parameter, this function can be used to set the
|
||||
// max sessions;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t nsMAPIConfiguration::RegisterSession(uint32_t aHwnd,
|
||||
const char16_t *aUserName, const char16_t *aPassword,
|
||||
bool aForceDownLoad, bool aNewSession,
|
||||
uint32_t *aSession, const char *aIdKey)
|
||||
{
|
||||
int16_t nResult = 0;
|
||||
uint32_t n_SessionId = 0;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
// Check whether max sessions is exceeded
|
||||
|
||||
if (sessionCount >= m_nMaxSessions)
|
||||
{
|
||||
PR_Unlock(m_Lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aUserName != nullptr && aUserName[0] != '\0')
|
||||
m_ProfileMap.Get(nsDependentString(aUserName), &n_SessionId);
|
||||
|
||||
// try to share a session; if not create a session
|
||||
if (n_SessionId > 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(n_SessionId, &pTemp);
|
||||
if (pTemp != nullptr)
|
||||
{
|
||||
pTemp->IncrementSession();
|
||||
*aSession = n_SessionId;
|
||||
nResult = 1;
|
||||
}
|
||||
}
|
||||
else if (aNewSession || n_SessionId == 0) // checking for n_SessionId is a concession
|
||||
{
|
||||
// create a new session; if new session is specified OR there is no session
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
pTemp = new nsMAPISession(aHwnd, aUserName,
|
||||
aPassword, aForceDownLoad, aIdKey);
|
||||
|
||||
if (pTemp != nullptr)
|
||||
{
|
||||
session_generator++;
|
||||
|
||||
// I don't think there will be (2 power 32) sessions alive
|
||||
// in a cycle. This is an assumption
|
||||
|
||||
if (session_generator == 0)
|
||||
session_generator++;
|
||||
m_SessionMap.Put(session_generator, pTemp);
|
||||
if (aUserName != nullptr && aUserName[0] != '\0')
|
||||
m_ProfileMap.Put(nsDependentString(aUserName), session_generator);
|
||||
*aSession = session_generator;
|
||||
sessionCount++;
|
||||
nResult = 1;
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return nResult;
|
||||
}
|
||||
|
||||
bool nsMAPIConfiguration::UnRegisterSession(uint32_t aSessionID)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(aSessionID, &pTemp);
|
||||
|
||||
if (pTemp != nullptr)
|
||||
{
|
||||
if (pTemp->DecrementSession() == 0)
|
||||
{
|
||||
if (pTemp->m_pProfileName.get() != nullptr)
|
||||
m_ProfileMap.Remove(pTemp->m_pProfileName);
|
||||
m_SessionMap.Remove(aSessionID);
|
||||
sessionCount--;
|
||||
bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool nsMAPIConfiguration::IsSessionValid(uint32_t aSessionID)
|
||||
{
|
||||
if (aSessionID == 0)
|
||||
return false;
|
||||
bool retValue = false;
|
||||
PR_Lock(m_Lock);
|
||||
retValue = m_SessionMap.Get(aSessionID, NULL);
|
||||
PR_Unlock(m_Lock);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
char16_t *nsMAPIConfiguration::GetPassword(uint32_t aSessionID)
|
||||
{
|
||||
char16_t *pResult = nullptr;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(aSessionID, &pTemp);
|
||||
|
||||
if (pTemp)
|
||||
pResult = pTemp->GetPassword();
|
||||
}
|
||||
PR_Unlock(m_Lock);
|
||||
return pResult;
|
||||
}
|
||||
|
||||
void *nsMAPIConfiguration::GetMapiListContext(uint32_t aSessionID)
|
||||
{
|
||||
void *pResult = nullptr;
|
||||
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(aSessionID, &pTemp);
|
||||
if (pTemp)
|
||||
pResult = pTemp->GetMapiListContext();
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
return pResult;
|
||||
}
|
||||
|
||||
void nsMAPIConfiguration::SetMapiListContext(uint32_t aSessionID, void *mapiListContext)
|
||||
{
|
||||
PR_Lock(m_Lock);
|
||||
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(aSessionID, &pTemp);
|
||||
if (pTemp)
|
||||
pTemp->SetMapiListContext(mapiListContext);
|
||||
}
|
||||
|
||||
PR_Unlock(m_Lock);
|
||||
}
|
||||
|
||||
void nsMAPIConfiguration::GetIdKey(uint32_t aSessionID, nsCString& aKey)
|
||||
{
|
||||
PR_Lock(m_Lock);
|
||||
if (aSessionID != 0)
|
||||
{
|
||||
nsMAPISession *pTemp = nullptr;
|
||||
m_SessionMap.Get(aSessionID, &pTemp);
|
||||
if (pTemp)
|
||||
pTemp->GetIdKey(aKey);
|
||||
}
|
||||
PR_Unlock(m_Lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// util func
|
||||
HRESULT nsMAPIConfiguration::GetMAPIErrorFromNSError (nsresult res)
|
||||
{
|
||||
HRESULT hr = SUCCESS_SUCCESS;
|
||||
|
||||
if (NS_SUCCEEDED (res)) return hr;
|
||||
|
||||
// if failure return the related MAPI failure code
|
||||
switch (res)
|
||||
{
|
||||
case NS_MSG_NO_RECIPIENTS :
|
||||
hr = MAPI_E_BAD_RECIPTYPE;
|
||||
break;
|
||||
case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS :
|
||||
hr = MAPI_E_INVALID_RECIPS;
|
||||
break;
|
||||
case NS_ERROR_SMTP_AUTH_FAILURE :
|
||||
case NS_ERROR_SMTP_AUTH_GSSAPI :
|
||||
case NS_ERROR_SMTP_AUTH_MECH_NOT_SUPPORTED :
|
||||
case NS_ERROR_SMTP_AUTH_NOT_SUPPORTED :
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_NO_SSL :
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_ENCRYPT_TO_PLAIN_SSL :
|
||||
case NS_ERROR_SMTP_AUTH_CHANGE_PLAIN_TO_ENCRYPT :
|
||||
hr = MAPI_E_LOGIN_FAILURE;
|
||||
break;
|
||||
case NS_MSG_UNABLE_TO_OPEN_FILE :
|
||||
case NS_MSG_UNABLE_TO_OPEN_TMP_FILE :
|
||||
case NS_MSG_COULDNT_OPEN_FCC_FOLDER :
|
||||
case NS_ERROR_FILE_INVALID_PATH :
|
||||
hr = MAPI_E_ATTACHMENT_OPEN_FAILURE;
|
||||
break;
|
||||
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST :
|
||||
hr = MAPI_E_ATTACHMENT_NOT_FOUND;
|
||||
break;
|
||||
case NS_MSG_CANCELLING :
|
||||
hr = MAPI_E_USER_ABORT;
|
||||
break;
|
||||
case NS_MSG_ERROR_WRITING_FILE :
|
||||
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE :
|
||||
case NS_MSG_UNABLE_TO_SAVE_DRAFT :
|
||||
hr = MAPI_E_ATTACHMENT_WRITE_FAILURE;
|
||||
break;
|
||||
default:
|
||||
hr = MAPI_E_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
nsMAPISession::nsMAPISession(uint32_t aHwnd, const char16_t *aUserName,
|
||||
const char16_t *aPassword,
|
||||
bool aForceDownLoad, const char *aKey)
|
||||
: m_bIsForcedDownLoad(aForceDownLoad),
|
||||
m_hAppHandle(aHwnd),
|
||||
m_nShared(1),
|
||||
m_pIdKey(aKey)
|
||||
{
|
||||
m_listContext = NULL;
|
||||
m_pProfileName.Assign(aUserName);
|
||||
m_pPassword.Assign(aPassword);
|
||||
}
|
||||
|
||||
nsMAPISession::~nsMAPISession()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t nsMAPISession::IncrementSession()
|
||||
{
|
||||
return ++m_nShared;
|
||||
}
|
||||
|
||||
uint32_t nsMAPISession::DecrementSession()
|
||||
{
|
||||
return --m_nShared;
|
||||
}
|
||||
|
||||
uint32_t nsMAPISession::GetSessionCount()
|
||||
{
|
||||
return m_nShared;
|
||||
}
|
||||
|
||||
char16_t *nsMAPISession::GetPassword()
|
||||
{
|
||||
return (char16_t *)m_pPassword.get();
|
||||
}
|
||||
|
||||
void nsMAPISession::GetIdKey(nsCString& aKey)
|
||||
{
|
||||
aKey = m_pIdKey;
|
||||
return;
|
||||
}
|
||||
86
mailnews/mapi/mapihook/src/msgMapiMain.h
Normal file
86
mailnews/mapi/mapihook/src/msgMapiMain.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MSG_MAPI_MAIN_H_
|
||||
#define NSG_MAPI_MAIN_H_
|
||||
|
||||
#define MAX_NAME_LEN 256
|
||||
#define MAX_PW_LEN 256
|
||||
#define MAX_SESSIONS 50
|
||||
#define MAPI_SENDCOMPLETE_EVENT "SendCompletionEvent"
|
||||
|
||||
#define MAPI_PROPERTIES_CHROME "chrome://messenger-mapi/locale/mapi.properties"
|
||||
#define PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND "mapi.blind-send.warn"
|
||||
#define PREF_MAPI_BLIND_SEND_ENABLED "mapi.blind-send.enabled"
|
||||
|
||||
#include "nspr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsMAPISession;
|
||||
|
||||
class nsMAPIConfiguration
|
||||
{
|
||||
private :
|
||||
|
||||
static uint32_t session_generator;
|
||||
static uint32_t sessionCount;
|
||||
static nsMAPIConfiguration *m_pSelfRef;
|
||||
PRLock *m_Lock;
|
||||
uint32_t m_nMaxSessions;
|
||||
|
||||
nsDataHashtable<nsStringHashKey, uint32_t> m_ProfileMap;
|
||||
nsClassHashtable<nsUint32HashKey, nsMAPISession> m_SessionMap;
|
||||
nsMAPIConfiguration();
|
||||
~nsMAPIConfiguration();
|
||||
|
||||
public :
|
||||
static nsMAPIConfiguration *GetMAPIConfiguration();
|
||||
void OpenConfiguration();
|
||||
int16_t RegisterSession(uint32_t aHwnd, const char16_t *aUserName, \
|
||||
const char16_t *aPassword, bool aForceDownLoad, \
|
||||
bool aNewSession, uint32_t *aSession, const char *aIdKey);
|
||||
bool IsSessionValid(uint32_t aSessionID);
|
||||
bool UnRegisterSession(uint32_t aSessionID);
|
||||
char16_t *GetPassword(uint32_t aSessionID);
|
||||
void GetIdKey(uint32_t aSessionID, nsCString& aKey);
|
||||
void *GetMapiListContext(uint32_t aSessionID);
|
||||
void SetMapiListContext(uint32_t aSessionID, void *mapiListContext);
|
||||
|
||||
// a util func
|
||||
static HRESULT GetMAPIErrorFromNSError (nsresult res) ;
|
||||
};
|
||||
|
||||
class nsMAPISession
|
||||
{
|
||||
friend class nsMAPIConfiguration;
|
||||
|
||||
private :
|
||||
bool m_bIsForcedDownLoad;
|
||||
bool m_bApp_or_Service;
|
||||
uint32_t m_hAppHandle;
|
||||
uint32_t m_nShared;
|
||||
nsCString m_pIdKey;
|
||||
nsString m_pProfileName;
|
||||
nsString m_pPassword;
|
||||
int32_t m_messageIndex;
|
||||
void *m_listContext; // used by findNext
|
||||
|
||||
public :
|
||||
nsMAPISession(uint32_t aHwnd, const char16_t *aUserName, \
|
||||
const char16_t *aPassword, \
|
||||
bool aForceDownLoad, const char *aKey);
|
||||
uint32_t IncrementSession();
|
||||
uint32_t DecrementSession();
|
||||
uint32_t GetSessionCount();
|
||||
char16_t *nsMAPISession::GetPassword();
|
||||
void GetIdKey(nsCString& aKey);
|
||||
~nsMAPISession();
|
||||
// For enumerating Messages...
|
||||
void SetMapiListContext( void *listContext) { m_listContext = listContext; }
|
||||
void *GetMapiListContext( ) { return m_listContext; }
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_MAIN_H_
|
||||
151
mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal file
151
mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "nsCOMPtr.h"
|
||||
#include "objbase.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIAppStartupNotifier.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "Registry.h"
|
||||
#include "msgMapiSupport.h"
|
||||
|
||||
#include "msgMapiImp.h"
|
||||
|
||||
/** Implementation of the nsIMapiSupport interface.
|
||||
* Use standard implementation of nsISupports stuff.
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMapiSupport, nsIMapiSupport, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
|
||||
{
|
||||
nsresult rv = NS_OK ;
|
||||
|
||||
if (!strcmp(aTopic, "profile-after-change"))
|
||||
return InitializeMAPISupport();
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
|
||||
return ShutdownMAPISupport();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = observerService->AddObserver(this,"profile-after-change", false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsMapiSupport::nsMapiSupport()
|
||||
: m_dwRegister(0),
|
||||
m_nsMapiFactory(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
nsMapiSupport::~nsMapiSupport()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::InitializeMAPISupport()
|
||||
{
|
||||
::OleInitialize(nullptr) ;
|
||||
|
||||
if (m_nsMapiFactory == nullptr) // No Registering if already done. Sanity Check!!
|
||||
{
|
||||
m_nsMapiFactory = new CMapiFactory();
|
||||
|
||||
if (m_nsMapiFactory != nullptr)
|
||||
{
|
||||
HRESULT hr = ::CoRegisterClassObject(CLSID_CMapiImp, \
|
||||
m_nsMapiFactory, \
|
||||
CLSCTX_LOCAL_SERVER, \
|
||||
REGCLS_MULTIPLEUSE, \
|
||||
&m_dwRegister);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
m_nsMapiFactory->Release() ;
|
||||
m_nsMapiFactory = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::ShutdownMAPISupport()
|
||||
{
|
||||
if (m_dwRegister != 0)
|
||||
::CoRevokeClassObject(m_dwRegister);
|
||||
|
||||
if (m_nsMapiFactory != nullptr)
|
||||
{
|
||||
m_nsMapiFactory->Release();
|
||||
m_nsMapiFactory = nullptr;
|
||||
}
|
||||
|
||||
::OleUninitialize();
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::RegisterServer()
|
||||
{
|
||||
// TODO: Figure out what kind of error propogation to pass back
|
||||
::RegisterServer(CLSID_CMapiImp, "Mozilla MAPI", "MozillaMapi", "MozillaMapi.1");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMapiSupport::UnRegisterServer()
|
||||
{
|
||||
// TODO: Figure out what kind of error propogation to pass back
|
||||
::UnregisterServer(CLSID_CMapiImp, "MozillaMapi", "MozillaMapi.1");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_IMAPISUPPORT_CID);
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiSupport)
|
||||
|
||||
static const mozilla::Module::CategoryEntry kMAPICategories[] = {
|
||||
{ APPSTARTUP_CATEGORY, "Mapi Support", "service," NS_IMAPISUPPORT_CONTRACTID, },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const mozilla::Module::CIDEntry kMAPICIDs[] = {
|
||||
{ &kNS_IMAPISUPPORT_CID, false, NULL, nsMapiSupportConstructor },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const mozilla::Module::ContractIDEntry kMAPIContracts[] = {
|
||||
{ NS_IMAPISUPPORT_CONTRACTID, &kNS_IMAPISUPPORT_CID },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const mozilla::Module kMAPIModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kMAPICIDs,
|
||||
kMAPIContracts,
|
||||
kMAPICategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(msgMapiModule) = &kMAPIModule;
|
||||
|
||||
|
||||
34
mailnews/mapi/mapihook/src/msgMapiSupport.h
Normal file
34
mailnews/mapi/mapihook/src/msgMapiSupport.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MSG_MAPI_SUPPORT_H_
|
||||
#define MSG_MAPI_SUPPORT_H_
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIMapiSupport.h"
|
||||
#include "msgMapiFactory.h"
|
||||
|
||||
#define NS_IMAPISUPPORT_CID \
|
||||
{0x8967fed2, 0xc8bb, 0x11d5, \
|
||||
{ 0xa3, 0xe9, 0x00, 0xb0, 0xd0, 0xf3, 0xba, 0xa7 }}
|
||||
|
||||
class nsMapiSupport : public nsIMapiSupport,
|
||||
public nsIObserver
|
||||
{
|
||||
public :
|
||||
nsMapiSupport();
|
||||
|
||||
// Declare all interface methods we must implement.
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIMAPISUPPORT
|
||||
|
||||
private :
|
||||
~nsMapiSupport();
|
||||
|
||||
DWORD m_dwRegister;
|
||||
CMapiFactory *m_nsMapiFactory;
|
||||
};
|
||||
|
||||
#endif // MSG_MAPI_SUPPORT_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue