Hi,Correctly uncompressing RTF text
-
Hi, I have some code which uses CDO to retrieve a mail item from outlook I know that the body is stored in RTF and have read this from CDO. My problem is that the RTF is in compressed format - now doing some google research I have have found an API call to uncompress the RTF. I just cant get the code to call the API correctly. Can you have a look at the code and tell me where I am being dumb please
Public Const MAPI_MODIFY As UInteger = &H1 Public Const STORE_UNCOMPRESSED_RTF As UInteger = &H8000 Public Declare Function WrapCompressedRTFStream Lib "mapi32.dll" ( ByRef lpCompressedRTFStream As IStream, ByVal uFlags As UInt32, ByRef lpUncompressedStream As IStream) As Integer Function getRTFfromCDO(ByVal sEntryId As String) Dim objCDO As MAPI.Session Dim objMail As MAPI.Message ' Dim strmOut As MemoryStream Dim lpsource As ADODB.Stream = New ADODB.Stream ' Microsoft ADODB Com object reference Dim lptarget As ADODB.Stream = New ADODB.Stream Const CdoPR_RTF_COMPRESSED = &H10090102 objCDO = CreateObject("MAPI.Session") objCDO.Logon("", "", False, False) objMail = objCDO.GetMessage(sEntryId) Try lpsource.Type = StreamTypeEnum.adTypeText lptarget.Type = StreamTypeEnum.adTypeText lpsource.Open() lpsource.WriteText(objMail.Fields(CdoPR_RTF_COMPRESSED).Value) WrapCompressedRTFStream(lpsource, STORE_UNCOMPRESSED_RTF, lptarget) Catch ex As Exception MsgBox(ex.Message) End Try 'Return objMail.Fields(CdoPR_RTF_COMPRESSED).Value objCDO.Logoff() End Function
thanks Martinlife is a bowl of cherries go on take a byte
-
Hi, I have some code which uses CDO to retrieve a mail item from outlook I know that the body is stored in RTF and have read this from CDO. My problem is that the RTF is in compressed format - now doing some google research I have have found an API call to uncompress the RTF. I just cant get the code to call the API correctly. Can you have a look at the code and tell me where I am being dumb please
Public Const MAPI_MODIFY As UInteger = &H1 Public Const STORE_UNCOMPRESSED_RTF As UInteger = &H8000 Public Declare Function WrapCompressedRTFStream Lib "mapi32.dll" ( ByRef lpCompressedRTFStream As IStream, ByVal uFlags As UInt32, ByRef lpUncompressedStream As IStream) As Integer Function getRTFfromCDO(ByVal sEntryId As String) Dim objCDO As MAPI.Session Dim objMail As MAPI.Message ' Dim strmOut As MemoryStream Dim lpsource As ADODB.Stream = New ADODB.Stream ' Microsoft ADODB Com object reference Dim lptarget As ADODB.Stream = New ADODB.Stream Const CdoPR_RTF_COMPRESSED = &H10090102 objCDO = CreateObject("MAPI.Session") objCDO.Logon("", "", False, False) objMail = objCDO.GetMessage(sEntryId) Try lpsource.Type = StreamTypeEnum.adTypeText lptarget.Type = StreamTypeEnum.adTypeText lpsource.Open() lpsource.WriteText(objMail.Fields(CdoPR_RTF_COMPRESSED).Value) WrapCompressedRTFStream(lpsource, STORE_UNCOMPRESSED_RTF, lptarget) Catch ex As Exception MsgBox(ex.Message) End Try 'Return objMail.Fields(CdoPR_RTF_COMPRESSED).Value objCDO.Logoff() End Function
thanks Martinlife is a bowl of cherries go on take a byte
You've got several problems. The lack of anyone using this API with C# or VB.NET is one of them, so documentation and support is lacking. First, I think your declaration has to look more like:
Private Declare Auto Function WrapCompressedRTFStream Lib "mapi32.dll" ( _
<MarshalAs(UnmanagedType.Interface)> ByVal lpCompressedRTFStream As ComTypes.IStream, _
ByVal ulFlags As UInt32, _
<MarshalAs(UnmanagedType.Interface)> ByVal lpUncompressedRTFStream As ComTypes.IStream) _
As IntegerI have no way of testing this! Second. You create an lpSource stream, but you never associate that stream with the incomming data. It's a stream that points to nothing. Some thing with your lpTarget. It also points to God knows what. You haven't told either of these object where the source and destination streams are actually supposed to get/write their data.
' OK...You've created a couple of Streams. What are they looking at?? Nothing!
Dim lpsource As ADODB.Stream = New ADODB.Stream ' Microsoft ADODB Com object reference
Dim lptarget As ADODB.Stream = New ADODB.Stream
...
Try
' Great! You set the stream types, but you still haven't told the source stream
' where to get it's data from!
lpsource.Type = StreamTypeEnum.adTypeText
lptarget.Type = StreamTypeEnum.adTypeText' Open what stream??
lpsource.Open()' I have no idea what this line is doing, nor why it's even here.
lpsource.WriteText(objMail.Fields(CdoPR_RTF_COMPRESSED).Value)WrapCompressedRTFStream(lpsource, STORE_UNCOMPRESSED_RTF, lptarget)
' OK. Now you've got the source stream wrapped. But you don't read anything and
' you don't write anything to any stream. All you did was wrap the source for
' decompression!
??????From what I've seen in the docs for WrapCompressed... the stream you should be reading to get the uncompressed RTF is the lptarget stream. I can't tell you exactly how to fix these problems. I have nothing to test any code with that will supply a compressed RTF in an email.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007 -
You've got several problems. The lack of anyone using this API with C# or VB.NET is one of them, so documentation and support is lacking. First, I think your declaration has to look more like:
Private Declare Auto Function WrapCompressedRTFStream Lib "mapi32.dll" ( _
<MarshalAs(UnmanagedType.Interface)> ByVal lpCompressedRTFStream As ComTypes.IStream, _
ByVal ulFlags As UInt32, _
<MarshalAs(UnmanagedType.Interface)> ByVal lpUncompressedRTFStream As ComTypes.IStream) _
As IntegerI have no way of testing this! Second. You create an lpSource stream, but you never associate that stream with the incomming data. It's a stream that points to nothing. Some thing with your lpTarget. It also points to God knows what. You haven't told either of these object where the source and destination streams are actually supposed to get/write their data.
' OK...You've created a couple of Streams. What are they looking at?? Nothing!
Dim lpsource As ADODB.Stream = New ADODB.Stream ' Microsoft ADODB Com object reference
Dim lptarget As ADODB.Stream = New ADODB.Stream
...
Try
' Great! You set the stream types, but you still haven't told the source stream
' where to get it's data from!
lpsource.Type = StreamTypeEnum.adTypeText
lptarget.Type = StreamTypeEnum.adTypeText' Open what stream??
lpsource.Open()' I have no idea what this line is doing, nor why it's even here.
lpsource.WriteText(objMail.Fields(CdoPR_RTF_COMPRESSED).Value)WrapCompressedRTFStream(lpsource, STORE_UNCOMPRESSED_RTF, lptarget)
' OK. Now you've got the source stream wrapped. But you don't read anything and
' you don't write anything to any stream. All you did was wrap the source for
' decompression!
??????From what I've seen in the docs for WrapCompressed... the stream you should be reading to get the uncompressed RTF is the lptarget stream. I can't tell you exactly how to fix these problems. I have nothing to test any code with that will supply a compressed RTF in an email.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007Hello, The lpsource stream I am populating with the string defined by objMail.Fields(CdoPR_RTF_COMPRESSED).Value which is the compressed RTF stream of the Mail item as extracted by CDO - hence the Open and writeText Its values in my example is "C9020000750400004C5A46759FA2E86903000A0072637067313235163200F80B606E0E103033334F01F702A403E3020063680AC073F0657430200713028300501066187072710E5010D85461689B037102807D0A8008C8203B096FED0E3035028014322A09B009F00490D4617405B1520DE068098001D00020352E35302E3939922E01D0303902805C760890A4776B0B8064340C606300503D0B036312020BC50F0201D035370F0AA20A811A2011516E79206F6E7417A005C01730700DE0042079A10860206775790420770070FB05400B80630A4001000B311B831B739B139017A0200AC005406F661D50526F047020620AC062059075F90B80673F20F01E8A1A131B7703C17C31381AD30F4205D01F910B8020CA4B09F0640510636B033000A05122D136284C022064022029030C4022B42020782038361E311B561A9F21670B036C6933DE36014012B01C5005907411F42500FC205F2A6F2B7F2C280AE30A8229740729410B132976692D3134343D27416922F018900CC12F4362205A4603613A03300C9262115043F1036075742C24101C302D3630701B066002303A30F626014A756CCB1C301881373370353A18A0322774546F32F75308902080032053187570700911322875626A8B29A132F74116D164612002107F05C00780113020C11C4003A0309069653890793227496D3682007063C26532F74869676827EC2D CF1F29A229040BB538451E8A2A2050E3036037822055703890299010B0D33FF50800616400C07033F418819323003FF64D4D3FE641751D60967305400460761F7028410540386C65614451031003206B6EDA6F07E07717A003A04A457245307620097041F02036601CA11CA068ED04002036800B807425903FF523B1F524902D07B34310F00F201F7119505F13900790054029613B2064087065EF1E8A1C1F1D2F1E3320211B31E02317FF212B25E331E1317324B52620252626307E380E404FA025B30C011E99142100015440" {String} The lptarget stream I assumed was going to be populated by the uncompressed version of the text. I read somewhere the ADODB.Stream was in effect a derived istream and could be used like that. Is that true? with your changes added , the API complained about an unopen lptarget stream so I added an lptarget.open now when I run it I get no error number but the lptarget.size is 0 any ideas?? Thanks Martin
life is a bowl of cherries go on take a byte