IDataSource Interface
Topic Last Modified: 2006-06-29
The IDataSource interface defines methods and properties that are 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 |
---|---|
Returns the currently active Microsoft® ActiveX® Data Objects (ADO) Connection object. |
|
Specifies whether or not the local data has been altered since the last save to the currently bound data source. |
|
The reference to the currently bound object. |
|
The name of the interface used to bind the currently bound object. |
|
The URL of the currently bound item within the Active Directory® directory service or the Exchange store. |
The following table lists the methods of the IDataSource interface.
Name | Description |
---|---|
Binds to and opens data from the existing item specified by the URL. |
|
Binds to and opens data from the specified object. |
|
Saves data into the currently bound data source. |
|
Binds to and saves data into the item with the specified URL. |
|
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). |
|
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.
Two aspects are 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->Item[i];
bstr_t MediaType;
MediaType = pBp->ContentMediaType;
if(MediaType == _bstr_t("message/rfc822")){
cout << "Found an embedded message...saving" << endl;
// Extract Embedded Message
// (clears out the previous message)
try {
iDsrc->OpenObject(pBp,_bstr_t("IBodyPart"));
}
catch(_com_error e) {
cerr << "Error opening message/rfc822 body part" << endl;
throw e;
}
try {
iDsrc->SaveToContainer(
folderURL,
pConn,
adModeReadWrite,
adCreateNonCollection,
(RecordOpenOptionsEnum) NULL,
bstr_t(),
bstr_t()
);
}
catch(_com_error e) {
cerr << "Error saving item to container" << endl;
throw e;
}
pConn = iDsrc->ActiveConnection;
bstr_t srcURL;
srcURL = iDsrc->SourceURL;
cout << "Saved embedded message at " << _bstr_t(srcURL) << endl;
}
else if(MediaType == _bstr_t("application/msword")) {
cout << "Found an application/msword body part" << endl;
// Can't use SaveToContainer here.
// The file will get MIME encoded.
// Use SaveTo instead.
GUID g;
if(FAILED(CoCreateGuid(&g))) {
cerr << "Error creating GUID" << 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 << "Error getting string from GUID?" << endl;
throw _com_error(E_UNEXPECTED);
}
cout << "Word file name: " << bstr_t(buf) << ".doc " << endl;
try {
iDsrcItem = iItem;
iItem->Fields->Item["DAV:contentclass"]->Value = variant_t("urn:content-classes:document");
iItem->Fields->Update();
iDsrcItem->SaveTo(
folderURL + bstr_t(buf) + bstr_t(".doc"),
_variant_t((IDispatch*)pConn, true),
adModeReadWrite,
adCreateNonCollection,
adOpenSource,
bstr_t(),
bstr_t()
);
pStm = iItem->GetStream();
pStm2 = pBp->GetDecodedContentStream();
pStm2->CopyTo(pStm,-1);
pStm->Flush();
// Must call save here for item. Stream is not committed to the
// store until Save() is called.
iDsrcItem->Save();
// clean up.
pConn->Close();
pStm->Close();
pStm2->Close();
pRec->Close();
}
catch(_com_error e) {
cerr << "Error saving word file to folder " << folderURL << 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 & "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
Conn.Close
Set Conn = Nothing
End Sub