Как избежать срабатываний системы безопасности при работе программ для Microsoft® Outlook® на Visual Basic
Работа с MAPI из Visual Basic без третьесторонних библиотек
Несмотря на широкораспространенное мнение, что из Visual Basic никак нельзя работать с MAPI, мы рискнем его опровергнуть. Конечно, до всех сокровищ MAPI из Visual Basic добраться практически невозможно, но задача получения свойств объекта не должна представлять большой сложности для опытного программиста труда.
В MAPI есть следующая функция:
HrGetOneProp(
LPMAPIPROP pmp,
ULONG ulPropTag,
LPSPropValue FAR * ppprop
);
Которая принимает указатель на интерфейс объекта (хранящийся в MAPIOBJECT), тэг, и возвращает указатель на значение. Самое сложное здесь – это работа с возвращаемым значением. В MAPI SDK оно описано следующим образом:
typedef struct _SPropValue
{
ULONG ulPropTag;
ULONG dwAlignPad;
union _PV Value;
} SPropValue, FAR *LPSPropValue;
В ulPropTag сохраняется тэг запрошенного значения если вызов произошел без ошибок, а объединение Value описано в MAPIDEFS.H следующим образом:
typedef union _PV
{
short int i; /* case PT_I2 */
LONG l; /* case PT_LONG */
ULONG ul; /* alias for PT_LONG */
float flt; /* case PT_R4 */
double dbl; /* case PT_DOUBLE */
unsigned short int b; /* case PT_BOOLEAN */
CURRENCY cur; /* case PT_CURRENCY */
double at; /* case PT_APPTIME */
FILETIME ft; /* case PT_SYSTIME */
LPSTR lpszA; /* case PT_STRING8 */
SBinary bin; /* case PT_BINARY */
LPWSTR lpszW; /* case PT_UNICODE */
LPGUID lpguid; /* case PT_CLSID */
LARGE_INTEGER li; /* case PT_I8 */
SShortArray MVi; /* case PT_MV_I2 */
SLongArray MVl; /* case PT_MV_LONG */
SRealArray MVflt; /* case PT_MV_R4 */
SDoubleArray MVdbl; /* case PT_MV_DOUBLE */
SCurrencyArray MVcur; /* case PT_MV_CURRENCY */
SAppTimeArray MVat; /* case PT_MV_APPTIME */
SDateTimeArray MVft; /* case PT_MV_SYSTIME */
SBinaryArray MVbin; /* case PT_MV_BINARY */
SLPSTRArray MVszA; /* case PT_MV_STRING8 */
SWStringArray MVszW; /* case PT_MV_UNICODE */
SGuidArray MVguid; /* case PT_MV_CLSID */
SLargeIntegerArray MVli; /* case PT_MV_I8 */
SCODE err; /* case PT_ERROR */
LONG x; /* case PT_NULL,
PT_OBJECT (no usable value) */
} __UPV;
Приведенный ниже пример писался и отлаживался на Visual Basic 6, и чтобы сократить пример, мы описали эту структуру попроще:
Private Type SPropValue
ulPropTag As Long
dwAlignPad As Long
val1 As Long
val2 As Long
val3 As Long
End Type
Итак, вызов HrGetOneProp создает эту структуру и возвращает нам указатель на нее. После окончания работы со структурой мы должны уничтожить ее, передав полученный указатель функции MAPIFreeBuffer:
Private Declare Function HrGetOneProp Lib "mapi32" _
Alias "HrGetOneProp@12" ( _
ByVal lpMapiProp As IUnknown, _
ByVal ulPropTag As Long, _
ByRef lppProp As Long) As Long
Private Declare Function MAPIFreeBuffer Lib "mapi32" ( _
ByVal lppProp As Long) As Long
Надо обратить также внимание, что если запрашиваемые строковые свойства возвращаются как ANSI-строки, и для их использования в Visual Basic нужно преобразовать из в Unicode. Нижеследующий код был заимствован из шестой главы книги “Win32 API Programming with Visual Basic” написанной Steven Roman:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function lstrlenA Lib "kernel32.dll" ( _
ByVal lpString As Long) As Long
Private Function LPSTRtoBSTR(ByVal lpsz As Long) As String
Dim cChars As Long
cChars = lstrlenA(lpsz)
LPSTRtoBSTR = String$(cChars, 0)
CopyMemory ByVal StrPtr(LPSTRtoBSTR), ByVal lpsz, cChars
LPSTRtoBSTR = Trim(StrConv(LPSTRtoBSTR, vbUnicode))
End Function
Итак, теперь у нас есть все необходимое, чтобы получить значение полюбившегося нам тэга PR_SENDER_EMAIL_ADDRESS:
Private Sub PrintEmail()
Dim objSesson As Object
Dim objItem As Object
Set objSession = CreateObject("MAPI.Session")
objSession.Logon
Set objItem = objSession.Inbox.Messages.GetFirst
Dim ptrSProp As Long
ptrSProp = 0
If HrGetOneProp(objItem.MAPIOBJECT, &H0C1F001E, ptrSProp) = 0 Then
Dim sprop As SPropValue
CopyMemory sprop, ByVal ptrSProp, 20
MsgBox LPSTRtoBSTR(sprop.val1)
MAPIFreeBuffer ptrSProp
End If
Set objItem = Nothing
Set objSession = Nothing
End Sub
Процедура PrintEmail делает следующее:
- Создает сессию CDO
- Вызовом Logon осуществляет инициализацию MAPI (если Вы используете не CDO, а OOM, вам может потребоваться сделать это вызовом функции MAPIInitialize)
- Получает в objItem первое письмо в папке Inbox в Outlook
- Вызовом HrGetOneProp получает указатель на структуру SPropValue в переменную ptrSProp
- Копирует данные из этой структуры в переменную spprop, после чего указатель на строку-результат (в формате ANSI) появляется в spprop.val1
- Переводит вызовом LPSTRtoBSTR строку в формат Visual Basic и выводит ее на экран вызовом MsgBox
- Вызовом MAPIFreeBuffer освобождает память, выделенную под структуру вызовом HrGetOneProp
- Освобождает объект и закрывает сессию CDO
Итак, поздравляем! У нас получилось обойти систему безопасности без использования сторонних библиотек и компонентов. А что могут предложить нам компоненты?
|
|