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->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 Next Conn.Close Set Conn = Nothing End Sub