Figure 3   New OLE DB 2.5 Cotypes

// New cotypes:

// Binder objects:

    CoType TBinder {
      [mandatory]   interface IBindResource;
      [mandatory]   interface ICreateRow;
      [mandatory]   interface IDBBinderProperties;
      [optional]    interface IRegisterProvider;   // Root binder only
      [optional]    interface ISupportErrorInfo;
   }

// Row objects:

    CoType TRow {
      [mandatory]   interface IColumnsInfo;
      [mandatory]   interface IConvertType;
      [mandatory]   interface IGetSession;
      [mandatory]   interface IRow;
      [optional]    interface IColumnsInfo2;
      [optional]    interface IConnectionPointContainer;
      [optional]    interface ICreateRow;
      [optional]    interface IDBAsynchStatus;
      [optional]    interface IDBCreateCommand;
      [optional]    interface IDBInitialize;
      [optional]    interface IRowChange;
      [optional]    interface IRowSchemaChange;
      [optional]    interface IScopedOperations;
      [optional]    interface ISupportErrorInfo;
   }

// Stream objects:

    CoType TStream {
      [mandatory]   interface ISequentialStream;
      [optional]    interface IConnectionPointContainer;
      [optional]    interface IDBAsynchStatus;
      [optional]    interface IDBInitialize;
      [optional]    interface IGetSourceRow;
      [optional]    interface ISupportErrorInfo;
      [optional]    interface IStream;
}

// New interfaces on existing objects:

// New interfaces on Session objects:

      [optional] interface IBindResource; 
      [optional] interface ICreateRow; 

// New interfaces on Rowset objects:

      [optional] interface IColumnsInfo2; 
      [optional] interface IGetRow;

Figure 5   Getting a Row Object


HRESULT GetSam2(IOpenRowset *pSession,
                IRow **ppRow)
{
    // call OpenRowset passing URL for table name
    // and asking for a rowset
    DBID idTable;
    idTable.eKind = DBKIND_NAME;
    idTable.uName.pwszName = L"http://bob.com/sam.htm";
    CComPtr<IRowset> pRowset;

    // Error checking deleted for clarity.
    pSession->OpenRowset(NULL, &idTable, NULL, IID_IRowset, 0, NULL,
                         (IUnknown **)&pRowset;

    // get a ROW HANDLE for the first row
    enum { ROWSTOGET  = 1 };
    ULONG   ulRows;
    HROW    rghRows[ROWSTOGET];

    pRowset->GetNextRows(NULL, 0, ROWSTOGET, &ulRows, rghRows);
        CComPtr<IGetRow> pGetRow;
        pRowset->QueryInterface(IID_IGetRow,
                                (void**)&pGetRow);

    // use the ROW handle to get a Row object
    return pGetRow->GetRowFromHROW(NULL, rghRows[0], IID_IRow, 
                                   (IUnknown **)ppRow);

Figure 6   DBCOLUMNACCESS Structure


typedef struct tagDBCOLUMNACCESS {
void *     pData;       // ptr to buffer for the data
DBID       columnid;    // column ID
ULONG      cbDataLen;   // returned data length
DBSTATUS   dwStatus;    // status field 
ULONG      cbMaxLen;    // maximum length of the buffer
DWORD      dwReserved;  // MBZ
DBTYPE     wType;       // data type
BYTE       bPrecision;  // numeric precision
BYTE       bScale;      // numeric scale
} DBCOLUMNACCESS;

Figure 7   ColumnAccess


void createColumnAccess
(
    ULONG nCols,                        // [in]
    DBCOLUMNINFO* pColInfo,             // [in]
    OLECHAR*   pColumnStrings,          // [in]
    DBCOLUMNACCESS** ppDBColAcc,        // [out]
    void** ppColData                    // [out]
)

{
    ULONG   i;
    DBCOLUMNACCESS* pDBColAcc;
    pDBColAcc = new DBCOLUMNACCESS[nCols];
    ppColumnData = new void*[nCols];

    for (i = 0; i < nCols; i++)
    {
    // need to add character for trailing null
    // if this is a string column binding
        ppColData[i] = new char[pColInfo[i].ulColumnSize];
        pDBColAcc[i].pData = ppColData[i];
        pDBColAcc[i].columnid =pColInfo[i].columnid;
        pDBColAcc[i].cbDataLen = pColInfo[i].ulColumnSize;
        pDBColAcc[i].cbMaxLen = pColInfo[i].ulColumnSize;
        pDBColAcc[i].wType = pColInfo[i].wType;
        pDBColAcc[i].bPrecision = pColInfo[i].bPrecision;
        pDBColAcc[i].bScale = pColInfo[i].bScale;
    }

    *ppDBColAcc = pDBColAcc;
    return;
}

Figure 8   Adding a Column

HRESULT AddAColumn(IRow *pr)
{
    HRESULT hr;
    hr = pr->QueryInterface(IID_IRowSchemaChange,(void **)&prsc);

    if (SUCCEEDED(hr))
    {
    DBCOLUMNINFO dbColInfo[1] = {0};
    DBCOLUMNACCESS *pdbColAcc = NULL;
    DBID idCol;

    idCol.eKind = DBKIND_NAME;
    idCol.uName.pwszName = L"MyNewColumn";

    dbColInfo[0].dwFlags = DBCOLUMNFLAGS_ISNULLABLE;
    dbColInfo[0].ulColumnSize = 255;
    dbColInfo[0].wType = DBTYPE_STR;
    dbColInfo[0].columnid = idCol;

    hr = prsc->AddColumns(1, dbColInfo, pdbColAcc);
    }

    return hr;
}


Figure 9   DBBINDURLFLAGs

Flag
Meaning
DBBINDURLFLAG_READ
Open object for reading only. At least one of DBBINDURLFLAG_READ and DBBINDURLFLAG_WRITE must be set, either by setting the appropriate bits on dwBindURLFlags or by setting the corresponding bits of DBPROP_INIT_MODE.
DBBINDURLFLAG_WRITE
Open object for writing only. See DBBINDURLFLAG_READ.
DBBINDURLFLAG_READWRITE
Open object for reading and writing. See DBBINDURLFLAG_READ.
DBBINDURLFLAG_SHARE_DENY_READ
Deny others read access. Not all providers support all types of DENY semantics. If the provider does not support this type of DENY semantics, the bind will succeed but return DB_S_ERRORSOCCURRED and a status of DBBINDURLSTATUS_S_ DENYTYPENOTSUPPORTED. If the provider does not support any type of DENY semantics, the bind will succeed but return DB_S_ERRORSOCCURRED and a status of DBBINDURLSTATUS_S_DENYNOTSUPPORTED.
DBBINDURLFLAG_SHARE_DENY_WRITE
Deny others write access. See the notes for SHARE_DENY_READ for information about the behavior of providers that do not support this type of DENY semantics.
DBBINDURLFLAG_SHARE_EXCLUSIVE
Deny others read and write access. See the notes for SHARE_DENY_READ for information about the behavior of providers that do not support this type of DENY semantics.
DBBINDURLFLAG_SHARE_DENY_NONE
Do not deny others read or write access (equivalent to the omission of SHARE_DENY_READ and SHARE_DENY_WRITE).
DBBINDURLFLAG_RECURSIVE
Modifies DBBINDURLFLAG_SHARE_XXX. Propagate sharing restrictions to all objects in the subtree. Has no effect when binding to leaf nodes. Specifying this flag with only DBBINDURLFLAG_SHARE_DENY_NONE (or equivalently, with no SHARE_DENY flags) will result in E_INVALIDARG.
DBBINDURLFLAG_OUTPUT
Bind to the resource's executed output rather than its source. (For example, this will retrieve the HTML generated by an ASP file rather than its source.) This flag is ignored on binds to collections.
DBBINDURLFLAG_ASYNCHRONOUS
Return immediately and perform the binding on a separate thread. If DBBIND­URLFLAG_WAITFORINIT is not specified, this flag affects the behavior of the IBindResource::Bind or ICreateRow::CreateRow call. If DBBINDURL­FLAG_ WAITFORINIT is specified, this flag affects the behavior of the IDBInitialize::Initialize call.
DBBINDURLFLAG_WAITFORINIT
Return an interface supported on an uninitialized object, but do not initiate the bind. Used in the following cases: the object supports IDBInitialize and the caller must use IDBInitialize::Initialize to initiate the bind; or the caller intends to register callback interfaces by querying from the returned interface to IConnectionPointContainer. To poll for status or cancel an operation, the caller requests an IDBAsynchStatus interface. The consumer may only ask for interfaces supported on uninitialized objects. The provider returns E_NOINTERFACE if any other interface is requested. When IBindResource is implemented on an object other than a Binder (for example, when it is implemented on a Session or Row object as IScopedOperations, which is derived from IBindResource), this flag is disallowed because the data source object is already initialized.
DBBINDURLFLAG_DELAYFETCHSTREAM
On a bind to a row, this overrides the consumer's intent to immediately open the default stream. Absence of this flag is a hint to the provider to instantiate the default stream object and prefetch its contents.
DBBINDURLFLAG_DELAYFETCHCOLUMNS
On a bind to a row, this overrides the consumer's intent to immediately access the row's columns. Absence of this flag is a hint to the provider to download or prefetch the row's columns.


Figure 10   CreateARow

HRESULT CreateARow(WCHAR *pwszName, bool bCollection)
{
    HRESULT hr;
    CComPtr<ICreateRow> pcr;
    hr = CoCreateInstance(CLSID_ROOT_BINDER, NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ICreateRow, (void**)&pcr);

    if (SUCCEEDED(hr))
    {
        DBBINDURLFLAG bf;
        if (bCollection == true)
            bf = DBBINDURLFLAG_COLLECTION |
                 DBBINDURLFLAG_READWRITE;
        else
            bf = DBBINDURLFLAG_READWRITE;
 
        CComPtr<IRow> pr;
        LPOLESTR *ppwszNewURL = NULL;
  
        hr = pcr->CreateRow(NULL, pwszName, bf,
                            DBGUID_ROW,
                            IID_IRow, NULL, NULL, NULL,
                            ppwszNewURL, (IUnknown **)&pr);
        }

        return hr;
}

Figure 12   Resource Rowset Columns

Column Name
Column ID
Description
RESOURCE_PARSENAME
DBROWCOL_PARSENAME
Read-only URL of the resource. This name is usually a relative URL, although it can be an absolute URL. If the resource is the root of a tree, its parse name is defined to be an empty string.
RESOURCE_PARENTNAME
DBROWCOL_PARENTNAME
Read-only URL of the parent resource. The string always contains an absolute URL. If the resource is the root of tree, its parent name is defined to be an empty string.
RESOURCE_ABSOLUTEPARSENAME
DBROWCOL_ABSOLUTEPARSENAME
Read-only URL of the resource. This name is always an absolute URL, and for nonroot resources is the concatenation of its parent name and its parse name.
RESOURCE_ISHIDDEN
DBROWCOL_ISHIDDEN
VARIANT_TRUE means the resource is hidden. Therefore, no row will be returned in rowsets for it unless the command that created the rowset explicitly selected rows where RESOURCE_ISHIDDEN is VARIANT_TRUE.
RESOURCE_ISREAD ONLY
DBROWCOL_ISREADONLY
VARIANT_TRUE means the resource is read-only. Attempts to open this resource with DBBINDURLFLAG_WRITE return DB_E_READONLY. This property can be edited even when the resource has been opened only for reading.
RESOURCE_CONTENT TYPE
DBROWCOL_CONTENTTYPE
The MIME type of the document (for example, text/html).
RESOURCE_CONTENTCLASS
DBROWCOL_CONTENTCLASS
The likely use of the document. This might correspond to the Microsoft Office template used to create the document.
RESOURCE_CONTENTLANGUAGE
DBROWCOL_CONTENTLANGUAGE
The language in which the content is written (for example, U.S. English).
RESOURCE_CREATIONTIME
DBROWCOL_CREATIONTIME
Read-only, specifying a FILETIME structure containing the time the resource was created. The time is reported Coordinated Universal Time (UTC) format.
RESOURCE_LASTACCESSTIME
DBROWCOL_LASTACCESSTIME
Read-only, specifying a FILETIME structure containing the time that the resource was last accessed. The time is in UTC format. The FILETIME members are zero if provider does not support this time member.
RESOURCE_LASTWRITE TIME
DBROWCOL_LASTWRITETIME
Read-only time when the resource was last modified. The time is stored in a FILETIME structure in UTC format. If the provider does not support the time member, the remaining FILETIME members are set to zero.
RESOURCE_STREAMSIZE
DBROWCOL_STREAMSIZE
Read-only size of the resource’s default stream, in bytes.
RESOURCE_ISCOLLECTION
DBROWCOL_ISCOLLECTION
Read-only. VARIANT_TRUE means the resource is a collection. VARIANT_FALSE means the resource is atomic.
RESOURCE_ISSTRUCTURED DOCUMENT
DBROWCOL_ISSTRUCTURED DOCUMENT
VARIANT_TRUE means the resource is a structured document. VARIANT_FALSE means the resource is not a structured document. It could be a collection or an atomic resource.
DEFAULT_DOCUMENT
DBROWCOL_DEFAULT DOCUMENT
Read-only. This resource contains a URL to the default simple document of a folder or a structured document. This is used when the default IStream is requested from a resource. This property is blank for atomic resources.
CHAPTERED_CHILDREN
CHAPTERED_CHILDREN
Read-only, specifying the chapter of the rowset containing the children of the resource. (Optional)
RESOURCE_DISPLAYNAME
DBROWCOL_DISPLAYNAME
Read-only, displaying name of txhe resource.
RESOURCE_ISROOT
DBROWCOL_ISROOT
Read-only. VARIANT_TRUE means the resource is a root of a collection. Can be used with RESOURCE_IS­COL­LECTION


Figure 13   dwMoveFlags Values

Flag Value Description
DBMOVE_ALLOW_EMULATION
If the attempt to move the row fails because the destination URL is on a different server or serviced by a different provider than the source, the provider is requested to attempt to simulate the move using download, upload, and delete operations. When moving resources between providers, this may cause increased latency or data loss due to different provider capabilities.
DBMOVE_ASYNC
The move operation is performed asynchronously. Progress and notifications are available via IDBAsynchStatus and IDBAsynchNotify callbacks. Implementations that do not support asynchronous behavior should block and return a warning.
DBMOVE_ATOMIC
Either all sources are moved successfully or no sources are moved. Whether all parts of an atomic operation are attempted if one part fails is provider-specific.
DBMOVE_DONT_UPDATE_LINKS
Request the server not to update links contained in an object on a move. If this flag is not specified, the default behavior is to do what the server specifies. By default, IScopedOperations:: Move will update links if the server is capable and if the option is turned on. If the server does not have the ability to fix up links or if the option is turned off, this call will still return S_OK.
DBMOVE_REPLACE_EXISTING
The move operation succeeds, even if a target object exists. Without this value, the move will fail if the target object already exists.


Figure 15   Record.Open Output

RESOURCE_PARSENAME = mypage.htm
RESOURCE_PARENTNAME = http://bob.com/
RESOURCE_ABSOLUTEPARSENAME = http://bob.com/sam.htm
RESOURCE_ISHIDDEN =
RESOURCE_ISREADONLY =
RESOURCE_CONTENTTYPE =
RESOURCE_CONTENTCLASS =
RESOURCE_CONTENTLANGUAGE =
RESOURCE_CREATIONTIME = 5/10/99 12:14:49 AM
RESOURCE_LASTACCESSTIME =
RESOURCE_LASTWRITETIME = 5/10/99 12:14:49 AM
RESOURCE_STREAMSIZE = 2
RESOURCE_ISCOLLECTION = False
RESOURCE_ISSTRUCTUREDDOCUMENT =
DEFAULT_DOCUMENT =
RESOURCE_DISPLAYNAME = mypage.htm
RESOURCE_ISROOT = False
RESOURCE_ISMARKEDFOROFFLINE = False

Figure 16   ADO Scoped Operations


Dim strURL As String
Dim rec As ADODB.Record
Dim rec2 As ADODB.Record

'StrURL points to a file
strURL = "http://bob.com/sam.htm"

'open a record representing the file
Set rec = New ADODB.Record
rec.Open strURL, , Access_DenyWrite

'copy it
rec.CopyRecord strURL, & _
    "http://bob.com/ steve.htm"

'move it
rec.MoveRecord strURL & _
    "http://bob.com/george.htm"

'delete it
Set rec2 = New ADODB.Record
rec2.Open "http://bob.com/george.htm"
rec2.DeleteRecord "http://bob.com/george.htm",
     False