Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What is the format of an Access OLE Object Field

29 views
Skip to first unread message

Andrew A. Andrews

unread,
Oct 13, 1997, 3:00:00 AM10/13/97
to

Brian,

CLongBinary is only the data taken from the object's
implementation of IPersist[Storage,Stream,...]. To
see how MFC does this, see 'operator << CArchive' in
olevar.cpp.

You can QueryInterface on the object to get other things
like IPrint for example.

Hope this leads you somewhere...

Brian Martel

unread,
Oct 15, 1997, 3:00:00 AM10/15/97
to

Andrew A. Andrews <and...@netwand.com> wrote in article
<01bcd86a$2c9c3920$971c9acf@netwand>...

>
> CLongBinary is only the data taken from the object's
> implementation of IPersist[Storage,Stream

Thanks,
But it seems there is a lot more being written than the CLSID. If I just
take the CLongBinary and write the entire thing to a file there is 3K of
extra information before the actual Blob of data that came from a file
embedded into the field. Some of this could be coming from the IPersist? of
the object but I don't think it all is.

I am trying to find what the minimum information Access needs in one of
these fields to have it be able to activate the correct server when the
content is edited.


Brian Martel

unread,
Oct 15, 1997, 3:00:00 AM10/15/97
to

>
> I am trying to find what the minimum information Access needs in one of
> these fields to have it be able to activate the correct server when the
> content is edited.
>
I received an email from someone with the following information. I know I
saw at least one other message from another person that was looking for
this, so here is what I got.

*********************
The following text is a article from 1993 that is no longer in the
knowledgebase. It describes the Access 1.0 ole object format that can
still be used with current access versions. Mind that ole streams means
a OLE1STREAM.


OLE objects are stored in long binary columns in
Access databases. The objects are stored as a
stream of binary data that only OLE knows how to
decode, with a wrapper around them that Access
uses to identify the binary data as an OLE object.

The object storage format is:
Object Header, Binary Stream, Object Trailer

The Object Header is defined as follows:

struct OBJECTHEADER {
WORD typ; // Type signiture (0x1c15)
WORD cbHdr;
// Size of header (sizeof(struct
OBJECTHEADER) + cchName + cchClass)
LONG lobjTyp;
// OLE Object type code (OT_STATIC,
OT_LINKED, OT_EMBEDDED)
WORD cchName; // Count of characters in
object name (CchSz(szName) + 1)
WORD cchClass; // Count of characters in
class name (CchSz(szClass) + 1)
WORD ibName; // Offset of object name
in structure (sizeof(OBJECTHEADER))
WORD ibClass; // Offset of class name in
structure (ibName + cchName)
PT ptSize; // Original size of
object (see code below for value)
CHAR rgch[]; // Name and Class of object,
stored as szName\0szClass\0
};

{
if (OleQueryBounds(lpoleobject, (LPRECT)&rc)
!= OLE_OK) goto OLEErr;

ptSize.x = rc.xRight - rc.xLeft;
ptSize.y = rc.yTop - rc.yBot;
}

Immediately following the last byte of rgch,
OLE is allowed to write out its stream of binary
data invoked by OleSaveToSteam.

Immediately following the stream of binary data
a DWORD value is written as a stream of bytes.
This DWORD consists of a one byte checksum of
the binary data that was written by OLE (See
ComputeObjchecksum below for computing the
checksum), binary OR'ed with the
CHECKSUMSIGNITURE (0xFE05AD00L).

{
DWORD dw = CHECKSUMSIGNITURE | bChecksum
Write(&dw, sizeof(dw))
}

When Access is loading this object, if the header
doesn't contain expected data (type information,
cbHdr == (sizeof(structOBJECTHEADER) + cchName +
cchClass) and other validation with cchName,
cchClass, ibName, ibClass) then the object will
not be loaded. If the checksum or CHECKSUMSIGNITURE
at the end of the object doesn't compute correctly,
the object will fail to load also.

The entire saved object could be expressed in the
following data structure:

struct IMAGE {
struct OBJECTHEADER objhdr;
BYTE rgb[];
DWORD dwChecksum;
};


/*===============================================
ComputeObjChecksum
Compute the Checksum of an OLE object to verify
its integrity.
================================================*/

API VOID ComputeObjChecksum
(
LPBYTE lpb, // far pointer to the checksum byte
BYTE _huge * hpb, // huge pointer to saved OLE object
LONG lcbbuf // Number of bytes in saved OLE object
)
{
BYTE bChecksum = *lpb

while (lcbbuf-- > 0L)
bChecksum ^= *hpb++;
// save the value
*lpb = bChecksum;
}


Brian Martel

unread,
Oct 20, 1997, 3:00:00 AM10/20/97
to

>
> The following text is a article from 1993 that is no longer in the
> knowledgebase. It describes the Access 1.0 ole object format that can
> still be used with current access versions.
>
This infomation was good but I am having trouble mapping it to what the
current versions of Access are doing. There seems to be some additional
header information and some embedded compound document structure added
before the object is asked to write out it's blob.

Does anyone have up to date information on the format of an Access Ole
object field?

My objective is to be able to write out information into an ole object
field so that when the database is opened by Access it will be in a format
it understands and is able to invoke the correct server to edit the data if
needed. If the data is just written as a blob the field title just shows up
as "Long binary data" instead of "Microsoft Word Document" (or whatever the
type of object it is).


0 new messages