IDataSource Interface

IDataSource Interface

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release. The IDataSource interface defines methods and properties used to provide access to content in other objects or in the Exchange store.

CLSID

CD000029-8B95-11D1-82DB-00C04FB1625D

Extends

IDispatch

Type Library

Microsoft CDO for Exchange 2000 Library

DLL Implemented In

CDOEX.DLL

Member Summary

The following table lists the properties of the IDataSource interface.

Name Description
ActiveConnection Returns the currently active Microsoft® ActiveX® Data Objects (ADO) Connection object.
IsDirty Specifies whether or not the local data has been altered since the last save to the currently bound data source.
Source The reference to the currently bound object.
SourceClass The name of the interface used to bind the currently bound object.
SourceURL The URL of the currently bound item within Microsoft Active Directory® or the Exchange store.

The following table lists the methods of the IDataSource interface.

Name Description
Open Binds to and opens data from the existing item specified by the URL.
OpenObject Binds to and opens data from the specified object.
Save Saves data into the currently bound data source.
SaveTo Binds to and saves data into the item with the specified URL.
SaveToContainer Binds to and saves data into a new item in the folder/container specified by URL. The item name is a generated globally unique identifier (GUID).
SaveToObject Binds to and saves data into the specified object.

Remarks

Objects expose implementations of the IDataSource interface to facilitate easy access to content (data) in other Collaboration Data Objects (CDO), ADO and Active Directory objects, and items in the Exchange store. For example, the Message object exposes an implementation of the IDataSource interface.

There are two aspects associated with using the IDataSource interface on objects:

  • Binding. Certain methods create an association, or linkage between the target item or object and the binding object. For example, when you use the Open method, you bind to a resource in the Exchange store or Active Directory. This binding (association) remains active until the object is subsequently rebound, unbound, or destroyed. While bound, various operations such as Save or IsDirty act on (or in relation to) the currently bound resource or object.
  • Directional Transfer of Data. Methods on the IDataSource are verbs that imply a direction of data flow. After binding to an object, these operations are then carried out. For example, the OpenObject method first binds the specified object, and then retrieves the serialized content contained within the bound object into the opening object. The process is analogous for the Open method. The SaveToObject, SaveTo, and SaveToContainer methods first bind to the specified object or resource, and then transfer local content into the target.

Opening other objects and resources is completely analogous to using Microsoft? Word to open its .doc files: when you "Open" a .doc file, the file is "bound" and the contents copied into the opening application. Subsequent "Save" commands overwrite the file contents with the local copy of data. When another file is opened or the user chooses Save As, the application rebinds to the new file and the appropriate data transfer occurs, either to or from the acting application. Save commands now act on the newly bound file. When a user closes the application, local data changes may not have been saved into the currently bound file. A dialog appears, "Do you wish to save the changes you have made to file?" Changes will be lost if they are not saved.

This reference only lists the loose semantic definition and Component Object Model (COM) interface binary signature required for an implementation of the IDataSource interface. For specific information about a particular implementation, see the corresponding COM class reference page.

Examples

[Visual Basic]

' Reference to Microsoft CDO for Exchange 2000 Library

' Reference to Microsoft ActiveX Data Objects 2.5 Library

' Note: It is recommended that all input parameters be validated when they are ' first obtained from the user or user interface. Function MoveItems(folderUrl1 As String, folderUrl2 As String)

' Items must be in same store for this routine to work.
Dim Item As New CDO.Item
Dim Fldr As New CDO.Folder
Dim Msg As New CDO.message
Dim CalMsg As New CDO.CalendarMessage
Dim iAppt  As New CDO.Appointment
Dim Per As New CDO.Person

Dim Rec As New ADODB.Record
Dim Rec2 As New ADODB.Record
Dim Rs  As New ADODB.Recordset
Dim Conn As New ADODB.Connection

Conn.Provider = "ExOLEDb.DataSource"
Conn.Open folderUrl1

Rec.Open folderUrl1, Conn
' Error check here

' This is very expensive for very large folders!
Set Rs = Rec.GetChildren
While Not Rs.EOF
    Rec2.Open Rs, Conn, adModeReadWrite, adFailIfNotExists
    Select Case Rec2.Fields("DAV:contentclass")
        Case "urn:content-classes:message":
            Debug.Print "Message"
            Msg.DataSource.OpenObject Rec2, "_Record"
            Debug.Print "To: " & Msg.To
            Debug.Print "From:: " & Msg.From
            Debug.Print "Subject: " & Msg.Subject
            Debug.Print vbCrLf & Msg.TextBody
            Debug.Print vbCrLf & Msg.Attachments.Count & " Attachments"
            Msg.DataSource.SaveToContainer folderUrl2, Conn, adModeReadWrite, adCreateNonCollection
            Rec2.DeleteRecord
            Rec2.Close

        Case "urn:content-classes:document":
            Debug.Print "Document"
            Item.DataSource.OpenObject Rec2, "_Record"
            Debug.Print Item.DisplayName
            Debug.Print Item.CreationDate
            Debug.Print Item.ContentClass

            ' This step MIME-encodes the document in the new location.
            ' Item.DataSource.SaveToContainer folderUrl2, Conn, adModeReadWrite, adCreateNonCollection
            Item.DataSource.SaveTo folderUrl2 & "/" & Item.DisplayName, Conn, adModeReadWrite, adCreateNonCollection
            Rec2.DeleteRecord
            Rec2.Close

        Case "urn:content-classes:folder":
            Debug.Print "Folder"
            Fldr.DataSource.OpenObject Rec2, "_Record"
            Debug.Print Fldr.DisplayName
            Debug.Print Fldr.ContentClass
            Debug.Print "Email address: " & Fldr.EmailAddress

            ' Must recurse here
            Dim strOrigFolder As String
            strOrigFolder = Fldr.DataSource.SourceURL
            Fldr.DataSource.SaveTo folderUrl2 & "/" & Fldr.DisplayName, Conn, adModeReadWrite, adCreateCollection
            MoveItems strOrigFolder, Fldr.DataSource.SourceURL
            Rec2.DeleteRecord
            Rec2.Close

        Case "urn:content-classes:calendarmessage":
            Debug.Print "CalendarMessage"
            CalMsg.DataSource.OpenObject Rec2, "_Record"
            Debug.Print "To: " & CalMsg.message.To
            Debug.Print "From:: " & CalMsg.message.From
            Debug.Print "Subject: " & CalMsg.message.Subject
            Debug.Print vbCrLf & CalMsg.message.TextBody
            Debug.Print vbCrLf & CalMsg.CalendarParts.Count & " Calendar-related body parts."
            Debug.Print vbCrLf & CalMsg.message.Attachments.Count & " Attachments."
            CalMsg.DataSource.SaveToContainer folderUrl2, Conn, adModeReadWrite, adCreateNonCollection
            Rec2.DeleteRecord
            Rec2.Close

        Case "urn:content-classes:person":
            Debug.Print "Contact Item"
            Per.DataSource.OpenObject Rec2, "_Record"
            Debug.Print Per.FirstName
            Debug.Print Per.LastName
            Debug.Print Per.Company
            Debug.Print Per.Email
            Per.DataSource.SaveToContainer folderUrl2, Conn, adModeReadWrite, adCreateNonCollection
            Rec2.DeleteRecord
            Rec2.Close

    End Select

    If Rec2.State = adStateOpen Then
        Rec2.Close
    End If
    Rs.MoveNext
Wend

' Clean up. Conn.Close Rec.Close Rec2.Close Rs.Close

Set Conn = Nothing Set Rec = Nothing Set Rec2 = Nothing Set Rs = Nothing

End Function

[C++,IDL]

// You must have the following paths in your // INCLUDE path. // %CommonProgramFiles%\system\ado // %CommonProgramFiles%\microsoft shared\cdo

#ifndef _CORE_EXAMPLE_HEADERS_INCLUDED #define _CORE_EXAMPLE_HEADERS_INCLUDED #import <msado15.dll> no_namespace #import <cdoex.dll> no_namespace #include <iostream.h> #endif

#define BUFLEN 40

// Note: It is recommended that all input parameters be validated when they are // first obtained from the user or user interface. void SaveEmbeddedPartsToFolder( IMessagePtr pMsgIn, bstr_t folderURL ) {

if(pMsgIn == NULL) throw _com_error(E_INVALIDARG);

IDataSourcePtr iDsrc; IDataSourcePtr iDsrcItem; IItemPtr iItem(__uuidof(Item)); IBodyPartPtr pBp; IBodyPartPtr pBp2; IBodyPartsPtr pBps; _ConnectionPtr pConn(__uuidof(Connection)); _StreamPtr pStm; _StreamPtr pStm2; _RecordPtr pRec; FieldsPtr pFlds; FieldPtr pFld; long i = 0; long nbp = 0;

// For optional parameters _variant_t varOpt(DISP_E_PARAMNOTFOUND,VT_ERROR);

// Use this object to extract embedded messages.

pConn->Provider = "ExOLEDB.DataSource"; try { pConn->Open(folderURL,bstr_t(),bstr_t(),-1); } catch(_com_error e) { throw e; }

IMessagePtr Msg(__uuidof(Message)); iDsrc = Msg; pBp = pMsgIn;

// Fetch all bodyparts below the message to scan for // application/octet-stream and embedded messages message/rfc822 // (won't find "related" parts in MHTML formatted messages)

pBps = pBp->BodyParts; nbp = pBps->Count; for(i=1;i<=nbp;i++) {

  pBp = pBps-&gt;Item[i];
  bstr_t MediaType;

  MediaType = pBp-&gt;ContentMediaType;
  if(MediaType == _bstr_t("message/rfc822")){

     cout &lt;&lt; "Found an embedded message...saving" &lt;&lt; endl;

     //  Extract Embedded Message
     //  (clears out the previous message)
     try {
        iDsrc-&gt;OpenObject(pBp,_bstr_t("IBodyPart"));
     }
     catch(_com_error e) {
        cerr &lt;&lt; "Error opening message/rfc822 body part" &lt;&lt; endl;
        throw e;
     }

     try {
        iDsrc-&gt;SaveToContainer(
                 folderURL,
                 pConn,
                 adModeReadWrite,
                 adCreateNonCollection,
                 (RecordOpenOptionsEnum) NULL,
                 bstr_t(),
                 bstr_t()
                 );
     }
     catch(_com_error e) {
        cerr &lt;&lt; "Error saving item to container" &lt;&lt; endl;
        throw e;
     }

     pConn = iDsrc-&gt;ActiveConnection;

     bstr_t srcURL;
     srcURL = iDsrc-&gt;SourceURL;
     cout &lt;&lt; "Saved embedded message at " &lt;&lt; _bstr_t(srcURL) &lt;&lt; endl;
  }
  else if(MediaType == _bstr_t("application/msword")) {
     cout &lt;&lt; "Found an application/msword body part" &lt;&lt; endl;


     // Can't use SaveToContainer here.
     // The file will get MIME encoded.
     // Use SaveTo instead.

     GUID g;
     if(FAILED(CoCreateGuid(&amp;g))) {
        cerr &lt;&lt; "Error creating GUID" &lt;&lt; endl;
        throw _com_error(E_FAIL);
     }
     wchar_t buf[BUFLEN];
     memset((void*)(wchar_t*)buf,0,BUFLEN);
     if( StringFromGUID2(g,(wchar_t*)buf,BUFLEN) == 0 ) {
        cerr &lt;&lt; "Error getting string from GUID?" &lt;&lt; endl;
        throw _com_error(E_UNEXPECTED);
     }
     cout &lt;&lt; "Word file name: " &lt;&lt; bstr_t(buf) &lt;&lt; ".doc " &lt;&lt; endl;
     try {
        iDsrcItem = iItem;
        iItem-&gt;Fields-&gt;Item["DAV:contentclass"]-&gt;Value = variant_t("urn:content-classes:document");
        iItem-&gt;Fields-&gt;Update();
        iDsrcItem-&gt;SaveTo(
                    folderURL + bstr_t(buf) + bstr_t(".doc"),
                    _variant_t((IDispatch*)pConn, true),
                    adModeReadWrite,
                    adCreateNonCollection,
                    adOpenSource,
                    bstr_t(),
                    bstr_t()
                    );
        pStm = iItem-&gt;GetStream();
        pStm2 = pBp-&gt;GetDecodedContentStream();
        pStm2-&gt;CopyTo(pStm,-1);
        pStm-&gt;Flush();

        // Must call save here for item. Stream is not committed to the
        // store until Save() is called.
        iDsrcItem-&gt;Save();

    // clean up.
    pConn-&gt;Close();
    pStm-&gt;Close();
    pStm2-&gt;Close();
    pRec-&gt;Close();

     }
     catch(_com_error e) {
        cerr &lt;&lt; "Error saving word file to folder " &lt;&lt; folderURL &lt;&lt; endl;
        throw e;
     }
  }

} }

[VBScript]

' Type information must have been imported into the script engine,

' for example: ' <reference object="adodb.record"/> ' <reference object="cdo.message"/> ' elements in ' a Windows Script Host (.wsf) file.

Sub SaveEmbeddedPartsToFolder(iMsg, URL)

Dim iMsgB
Set iMsgB = CreateObject("CDO.Message")
Dim iDsrcB
Dim iFldr
Dim iDsrcFldr
Dim Conn
Dim iBp
Dim iBps
Dim ContType

Set Conn = CreateObject("ADODB.Connection")
Conn.Provider = "ExOLEDB.DataSource"
Conn.Open URL

Set iDsrcFldr = iFldr
iDsrcFldr.Open URL, Conn

Set iDsrcB = iMsgB.DataSource

Set iBp = iMsg.BodyPart
Set iBps = iBp.BodyParts

For Each iBp In iBps
    ContType = iBp.ContentMediaType
    If ContType = "message/rfc822" Then

        iDsrcB.OpenObject iBp, "IBodyPart"
        iDsrcB.SaveToContainer FolderURL, Conn, adModeReadWrite, adCreateOverwrite

    ElseIf ContType = "application/octet-stream" Then

        Dim Rec
        Set Rec = CreateObject("ADODB.Record")
        Dim Flds
        Dim Fld
        Dim Stm1
        Dim Stm2

        ' Get some unique name based on message ID, etc.
        Rec.Open FolderURL &amp; "uniquename.x", Conn, adModeReadWrite, adCreateOverwrite
        Set Flds = Rec.Fields
        ' Get Stream for resource which is accessed using -1 in Fields collection.
        Set Fld = Flds.Item(-1)
        Set Stm1 = Fld.Value

        ' Get Decoded BodyPart stream.
        Set Stm2 = iBp.GetDecodedContentStream
        ' Copy bodypart stream to resource stream
        Stm2.CopyTo Stm1

        ' Commit
        Stm1.Flush
        Stm1.Close
        Rec.Close
    Stm2.Close

    Stm1 = Nothing
    Stm2 = Nothing
    Rec = Nothing

    End If
Next

Conn.Close
Set Conn = Nothing

End Sub

Send us your feedback about the Microsoft Exchange Server 2003 SDK.

Build: June 2007 (2007.618.1)

© 2003-2006 Microsoft Corporation. All rights reserved. Terms of use.