OLItem.MAPIOBJECT with Outlook Object Modell

G

Gabi Fruhner

Hi,

in my App I get some props with

....HrGetOneProp(CDOMessage.MAPIOBJECT, ...

to avoid OL Security warning and with CDO it works fine.

But CDO pushes memory up to 12 MB and so I tried to access props with
OLItem.MAPIOBJECT.

I initialize with MAPIInitialize(0) before but with OOM I get no result.
What's wrong ?

Thanks

Gabi
 
G

Gabi Fruhner

Hi Dmitry,

lResult = 6

and I want to use HrGetOneProp in a Standalone Prog (not a OL AddIn)

Can I return all values which I get with CDOMessage.Fields(Prop).value with
HrGetOneProp too ?


Thanks

Gabi
 
D

Dmitry Streblechenko \(MVP\)

Are you sure? HrGetOneProp *only* resurns S_OK (0) or an error ( < 0). It
does not return non-critical errors (>0).
Did you mean LPSPropValue out parameter in HrGetOneProp?
Does the property that you are trying to retrieve exist on that particular
message? Did you check with MdbView or OutlookSpy?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
G

Gabi Fruhner

Yes I am.
Here's some code

Option Explicit

Private Declare Function MAPIInitialize Lib "mapi32.dll" (ByVal lpMapiInit
As Long) As Long
Private Declare Function MAPIFreeBuffer Lib "mapi32" (ByVal lppProp As Long)
As Long

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 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 Type PropValue
ulPropTag As Long
dwAlignPad As Long
val1 As Long
val2 As Long
val3 As Long
End Type


Private Const Prop_Sender As Long = &HC1A001E


Public Sub CheckForMAPIProp(ByVal objItem As Object)
Dim vValue As Variant, lResult As Long

Call MAPIInitialize(0)

vValue = MAPIProp(objItem.MAPIOBJECT, Prop_Sender, lResult)
MsgBox vValue, , CStr(lResult)

' RETURNS: vValue = ""; lResult = 6


Dim objSession As MAPI.Session, objMessage As MAPI.Message

Set objSession = New MAPI.Session
objSession.Logon "", "", False, False

Set objMessage = objSession.GetMessage(objItem.EntryID)
vValue = MAPIProp(objMessage.MAPIOBJECT, Prop_Sender, lResult)
MsgBox vValue, , CStr(lResult)

' RETURNS: vValue = "SenderName"; lResult = 0

....
....

End Sub


Private Function MAPIProp(ByVal objMAPIObject As IUnknown, PropID As Long,
lResult As Long) As Variant
Dim Prop As PropValue, ptrProp As Long, lLen As Long, lPos As Long, sRes As
String

lResult = HrGetOneProp(objMAPIObject, PropID, ptrProp)

If lResult = 0 Then

CopyMemory Prop, ByVal ptrProp, 20
....
....

End If

End Function


Works fine with CDO but not with OOM (ErrCode really 6)

Gabi
 
D

Dmitry Streblechenko \(MVP\)

PropValue declaration is completely wrong - it is a union struct with a
bunch of fields for different prop types (Value.lpszA for PT_STRING8,
Values.lpszW for PT_UNICODE, Value.l for PT_LONG, etc).
You are essentially casting a pointer to LPSPropValue to PChar using a
variable declared as Long when you are trying to retrieve a pointer to a
string.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
D

Dmitry Streblechenko \(MVP\)

You are still casting lResult to CStr - lResult is a long (returned by
HrGetOneProp), not a string.
What is the complete source code for the MAPIProp function?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
G

Gabi Fruhner

Here is the complete source code for the MAPIProp function


Private Function MAPIProp(objMAPIObject As IUnknown, PropID As Long, lResult
As Long) As Variant
Dim Prop As PropValue, ptrProp As Long, lLen As Long, lPos As Long, sRes As
String

lResult = HrGetOneProp(objMAPIObject, PropID, ptrProp)

If lResult = 0 Then

CopyMemory Prop, ByVal ptrProp, 20

lLen = lstrlenA(Prop.val1)
sRes = String$(lLen, 0)
CopyMemory ByVal StrPtr(sRes), ByVal Prop.val1, lLen
MAPIProp = StrConv(sRes, vbUnicode)

MAPIFreeBuffer ptrProp

End If

End Function


and with this code I can read all STRING values if objMAPIObject is a
CDOMessage.MAPIOBJECT (tested) but if objMAPIObject is a OLItem.MAPIOBJECT
then lResult = 6

lResult = MAPIInitialize(0) in Sub CheckForMAPIProp returns 0

Gabi
 
D

Dmitry Streblechenko \(MVP\)

Hmmm... I can only think of MailItem.MAPIOBJECT in OOM returning IUnknown
instead of IMessage. You can then explicitly QI the returned value for
IMessage or IMAPIProp, otherwise all hell breaks loose. HrGetOneProp expects
IMAPIProp (or IMessage which is derived from IMAPIProp), not IUnknown.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
G

Gabi Fruhner

OK, last try, then I'll use CDO)

Code works with OLItem.MAPIOBJECT too, if code runs in a VBA Project.

Typename(OLItem.MAPIOBJECT) and Typename(CDOMESSAGE.MAPIOBJECT) return
always 'Unknown' when code runs as VBA and when code runs as Standalone
Prog.

I have tested all possibilities of Struct MAPInit_0 and MAPIInitialize
returned always 0 but HRGetOneProp returned always 6 if code runs as
Standalone Prog.

Thank you very much

Gabi
 
M

Michael Tissington

I read some place that the MAPI object that MAPIOBJECT returns is not a real
MAPI object but just some hack that was designed to work with CDO.

I know I have ran into problems when I tried to treat it like a real MAPI
object and I ended up needing to do an OpenEntry to get a real MAPI object.
 
D

Dmitry Streblechenko \(MVP\)

TypeName only works for the objects derived from IDispatch *if* they
implement IDispatch::GetTypeInfo
All Extended MAPI objects are derived from IUnknown, not IDispatch, so
TypeName() will always return "Unknown".

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
D

Dmitry Streblechenko \(MVP\)

That makes sense now: since your app is an external application,
MailItem.MAPIOBJECT always returns IUnknown. I know that because you can
access it from an external app without calling MAPIInitialize. You do get an
error however when you QI for IMessage wihout calling MAPIInitialize first.
If you run inside of the outlook.exe process space, MAPIOBJECT returns
IMessage.
The reason it works in CDO is because CDO 1.21 is always inproc, Outlook OOM
is only inproc if your code runs inside of outlook.exe, i.e. if it is a COM
addin or a script inside of the VBA editor.
To work around that, create a type library for a dummy object
(DummyMessage?) with the same GUID as IMessage derived from IUnknown. The
GUID is {00020307-0000-0000-C000-000000000046}.You don't need to provide any
method definitions.
Then in your code dim the value you get from MAPIOBJECT as that object:

dim MyDummyMessage As DummyMessage
....
set MyDummyMessage = objMessage.MAPIOBJECT
lResult = HrGetOneProp(MyDummyMessage, ...)

This way the compiler will automatically quiery for the required interface
(IMessage) upon the MyDummyMessage assignment.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
G

Gabi Fruhner

Hi Dmitry,

thank you very much for your help.
It sounds good but I can not tell you if it works because I have never
created a TypeLib before and after a while googling around (found only
example for constants declaration) I think I will need a little time to
check it (idl, odl ???).

Thanks

Gabi


Dmitry Streblechenko (MVP) said:
That makes sense now: since your app is an external application,
MailItem.MAPIOBJECT always returns IUnknown. I know that because you can
access it from an external app without calling MAPIInitialize. You do get an
error however when you QI for IMessage wihout calling MAPIInitialize first.
If you run inside of the outlook.exe process space, MAPIOBJECT returns
IMessage.
The reason it works in CDO is because CDO 1.21 is always inproc, Outlook OOM
is only inproc if your code runs inside of outlook.exe, i.e. if it is a COM
addin or a script inside of the VBA editor.
To work around that, create a type library for a dummy object
(DummyMessage?) with the same GUID as IMessage derived from IUnknown. The
GUID is {00020307-0000-0000-C000-000000000046}.You don't need to provide any
method definitions.
Then in your code dim the value you get from MAPIOBJECT as that object:

dim MyDummyMessage As DummyMessage
...
set MyDummyMessage = objMessage.MAPIOBJECT
lResult = HrGetOneProp(MyDummyMessage, ...)

This way the compiler will automatically quiery for the required interface
(IMessage) upon the MyDummyMessage assignment.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Gabi Fruhner said:
OK, last try, then I'll use CDO)

Code works with OLItem.MAPIOBJECT too, if code runs in a VBA Project.

Typename(OLItem.MAPIOBJECT) and Typename(CDOMESSAGE.MAPIOBJECT) return
always 'Unknown' when code runs as VBA and when code runs as Standalone
Prog.

I have tested all possibilities of Struct MAPInit_0 and MAPIInitialize
returned always 0 but HRGetOneProp returned always 6 if code runs as
Standalone Prog.

Thank you very much

Gabi
(returned
by
HrGetOneProp), not a string.
What is the complete source code for the MAPIProp function?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Hi Dmitry,

it's like example on
http://www.mapilab.com/articles/vb_outlook_security_4.html and it
works
fine
(only for strings) with CDO

Gabi

Newsbeitrag
PropValue declaration is completely wrong - it is a union struct
with
a
bunch of fields for different prop types (Value.lpszA for
PT_STRING8,
Values.lpszW for PT_UNICODE, Value.l for PT_LONG, etc).
You are essentially casting a pointer to LPSPropValue to PChar using
a
variable declared as Long when you are trying to retrieve a pointer
to
a
string.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Yes I am.
Here's some code

Option Explicit

Private Declare Function MAPIInitialize Lib "mapi32.dll" (ByVal
lpMapiInit
As Long) As Long
Private Declare Function MAPIFreeBuffer Lib "mapi32" (ByVal
lppProp
As
Long)
As Long

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 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 Type PropValue
ulPropTag As Long
dwAlignPad As Long
val1 As Long
val2 As Long
val3 As Long
End Type


Private Const Prop_Sender As Long = &HC1A001E


Public Sub CheckForMAPIProp(ByVal objItem As Object)
Dim vValue As Variant, lResult As Long

Call MAPIInitialize(0)

vValue = MAPIProp(objItem.MAPIOBJECT, Prop_Sender, lResult)
MsgBox vValue, , CStr(lResult)

' RETURNS: vValue = ""; lResult = 6


Dim objSession As MAPI.Session, objMessage As MAPI.Message

Set objSession = New MAPI.Session
objSession.Logon "", "", False, False

Set objMessage = objSession.GetMessage(objItem.EntryID)
vValue = MAPIProp(objMessage.MAPIOBJECT, Prop_Sender, lResult)
MsgBox vValue, , CStr(lResult)

' RETURNS: vValue = "SenderName"; lResult = 0

...
...

End Sub


Private Function MAPIProp(ByVal objMAPIObject As IUnknown, PropID
As
Long,
lResult As Long) As Variant
Dim Prop As PropValue, ptrProp As Long, lLen As Long, lPos As
Long,
sRes
As
String

lResult = HrGetOneProp(objMAPIObject, PropID, ptrProp)

If lResult = 0 Then

CopyMemory Prop, ByVal ptrProp, 20
....
....

End If

End Function


Works fine with CDO but not with OOM (ErrCode really 6)

Gabi


Newsbeitrag
Are you sure? HrGetOneProp *only* resurns S_OK (0) or an error
( <
0).
It
does not return non-critical errors (>0).
Did you mean LPSPropValue out parameter in HrGetOneProp?
Does the property that you are trying to retrieve exist on that
particular
message? Did you check with MdbView or OutlookSpy?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Hi Dmitry,

lResult = 6

and I want to use HrGetOneProp in a Standalone Prog (not
a
OL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top