Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1542 lines
44 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: expprop.cxx
//
// Contents: Exposed property implementation
//
// History: 14-Oct-92 DrewB Created
//
//----------------------------------------------------------------------------
#include <exphead.cxx>
#pragma hdrstop
#include <memalloc.h>
#include <pbstream.hxx>
#include "props.hxx"
#include "expdf.hxx"
#include "expst.hxx"
#include "exppiter.hxx"
#include "logfile.hxx"
//+---------------------------------------------------------------------------
//
// Method: CExposedDocFile::ValidatePropSpecs, private
//
// Synopsis: Checks an array of PROPSPEC for validity
//
// Arguments: [cpspec] - Count
// [rgpspec] - Specs
//
// Returns: Appropriate status code
//
// History: 11-May-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CExposedDocFile::ValidatePropSpecs(ULONG cpspec, PROPSPEC rgpspec[])
{
ULONG i;
SCODE sc;
olDebugOut((DEB_ITRACE, "In ValidatePropSpecs(%lu, %p)\n",
cpspec, rgpspec));
olChk(ValidateBuffer(rgpspec, sizeof(PROPSPEC)*cpspec));
for (i = 0; i < cpspec; i++)
{
olChk(ValidatePropSpecKind(rgpspec[i].ulKind));
switch(rgpspec[i].ulKind)
{
case PRSPEC_LPWSTR:
olChk(CheckPropertyName(rgpspec[i].lpwstr));
break;
case PRSPEC_DISPID:
if (rgpspec[i].dispid < 0 || rgpspec[i].dispid > DISPID_MAX_FIXED)
{
olErr(EH_Err, STG_E_INVALIDNAME);
}
break;
case PRSPEC_PROPID:
break;
default:
olAssert(!aMsg("ValidatePropSpecs default hit"));
break;
}
}
olDebugOut((DEB_ITRACE, "Out ValidatePropSpecs\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::SpecToDfName, private
//
// Synopsis: Creates a CDfName for a PROPSPEC
//
// Returns: Appropriate status code
//
// Arguments: [ppspec] - Spec
// [pdfn] - DfName
//
// History: 11-May-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CExposedDocFile::SpecToDfName(PROPSPEC *ppspec, CDfName *pdfn)
{
olDebugOut((DEB_ITRACE, "In SpecToDfName(%p, %p)\n", ppspec, pdfn));
switch(ppspec->ulKind)
{
case PRSPEC_DISPID:
pdfn->IdName(ppspec->dispid);
break;
case PRSPEC_PROPID:
if (ppspec->propid >= INITIAL_PROPID)
{
LPWSTR lpwstr;
// Mapped name
lpwstr = _nim.NameFromId(ppspec->propid);
if (lpwstr == NULL)
return STG_E_FILENOTFOUND;
pdfn->PropName(lpwstr);
}
else
{
pdfn->IdName((DISPID)ppspec->propid);
}
break;
case PRSPEC_LPWSTR:
pdfn->PropName(ppspec->lpwstr);
break;
default:
olAssert(!aMsg("SpecToDfName default hit"));
break;
}
olDebugOut((DEB_ITRACE, "Out SpecToDfName\n"));
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::GetSpecId, public
//
// Synopsis: Gets the propid for a PROPSPEC
//
// Arguments: [ppspec] - PROPSPEC
// [ppropid] - Propid return
// [fAlloc] - Allocate new ids
//
// Returns: Appropriate status code
//
// Modifies: [ppropid]
//
// History: 12-May-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CExposedDocFile::GetSpecId(PROPSPEC *ppspec,
PROPID *ppropid,
BOOL fAlloc)
{
SCODE sc = S_OK;
olDebugOut((DEB_ITRACE, "In CExposedDocFile::GetSpecId:%p(%p, %p, %d)\n",
this, ppspec, ppropid, fAlloc));
switch(ppspec->ulKind)
{
case PRSPEC_DISPID:
*ppropid = (PROPID)ppspec->dispid;
break;
case PRSPEC_PROPID:
*ppropid = ppspec->propid;
break;
case PRSPEC_LPWSTR:
if ((*ppropid = _nim.IdFromName(ppspec->lpwstr)) == PROPID_UNKNOWN)
{
if (fAlloc)
{
*ppropid = _propid;
if (_nim.Add(ppspec->lpwstr, *ppropid) == NULL)
sc = STG_E_INSUFFICIENTMEMORY;
else
_propid++;
}
else
sc = STG_E_FILENOTFOUND;
}
break;
default:
olAssert(!aMsg("GetSpecId default hit"));
break;
}
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::GetSpecId\n"));
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::BufferToPropValue, private
//
// Synopsis: Fills in a property value from a buffer
//
// Arguments: [ppb] - Buffer start in, buffer end out
// [pdpv] - Property value
//
// Returns: Appropriate status code
//
// Modifies: [ppb]
//
// History: 14-Oct-92 DrewB Created
//
//----------------------------------------------------------------------------
#define GET_SIMPLE_VAL(type) \
memcpy(&pdpv->iVal, pb, sizeof(type)); \
pb += sizeof(type)
#define GET_SIMPLE_VECTOR(type) \
if (pdpv->cai.pElems = (short *)TaskMemAlloc(sizeof(type)*ulCnt)) \
{ \
memcpy(pdpv->cai.pElems, pb, sizeof(type)*ulCnt); \
pb += sizeof(type)*ulCnt; \
} \
else \
{ \
sc = STG_E_INSUFFICIENTMEMORY; \
}
SCODE CExposedDocFile::BufferToPropValue(BYTE **ppb,
DFPROPVAL *pdpv)
{
SCODE sc = S_OK;
ULONG i, ulCnt, cb;
BYTE *pb;
olDebugOut((DEB_ITRACE, "In CExposedDocFile::BufferToPropValue:%p("
"%p, %p)\n", this, ppb, pdpv));
pb = *ppb;
if (pdpv->vt & VT_VECTOR)
{
ulCnt = *(ULONG UNALIGNED *)pb;
pb += sizeof(ULONG);
pdpv->cai.cElems = ulCnt;
}
switch(pdpv->vt)
{
case VT_EMPTY:
break;
case VT_I2:
GET_SIMPLE_VAL(short);
break;
case VT_I2 | VT_VECTOR:
GET_SIMPLE_VECTOR(short);
break;
case VT_I4:
GET_SIMPLE_VAL(long);
break;
case VT_I4 | VT_VECTOR:
GET_SIMPLE_VECTOR(long);
break;
case VT_R4:
GET_SIMPLE_VAL(float);
break;
case VT_R4 | VT_VECTOR:
GET_SIMPLE_VECTOR(float);
break;
case VT_R8:
GET_SIMPLE_VAL(double);
break;
case VT_R8 | VT_VECTOR:
GET_SIMPLE_VECTOR(double);
break;
case VT_CY:
GET_SIMPLE_VAL(CY);
break;
case VT_CY | VT_VECTOR:
GET_SIMPLE_VECTOR(CY);
break;
case VT_DATE:
GET_SIMPLE_VAL(DATE);
break;
case VT_DATE | VT_VECTOR:
GET_SIMPLE_VECTOR(DATE);
break;
case VT_BSTR:
pb += BSTR_LLEN;
ulCnt = BSTR_TLEN(pb);
olMem(pdpv->bstrVal = (BSTR)TaskMemAlloc(ulCnt));
memcpy(pdpv->bstrVal, BSTR_PTR(pb), ulCnt);
pdpv->bstrVal = (BSTR)((BYTE *)pdpv->bstrVal+BSTR_LLEN);
pb += ulCnt-BSTR_LLEN;
break;
case VT_BSTR | VT_VECTOR:
olMem(pdpv->cabstr.pElems =
(BSTR *)TaskMemAlloc(sizeof(BSTR)*ulCnt));
for (i = 0; i < ulCnt; i++)
{
pb += BSTR_LLEN;
cb = BSTR_TLEN(pb);
pdpv->cabstr.pElems[i] = (BSTR)TaskMemAlloc(cb);
if (pdpv->cabstr.pElems[i] == NULL)
break;
memcpy(pdpv->cabstr.pElems[i], BSTR_PTR(pb), cb);
pdpv->cabstr.pElems[i] =
(BSTR)((BYTE *)pdpv->cabstr.pElems[i]+BSTR_LLEN);
pb += cb-BSTR_LLEN;
}
if (i != ulCnt)
{
while (i > 0)
{
i--;
TaskMemFree(pdpv->cabstr.pElems[i]);
}
TaskMemFree(pdpv->cabstr.pElems);
sc = STG_E_INSUFFICIENTMEMORY;
}
break;
#ifdef OLDPROPS
case VT_WBSTR:
pb += WBSTR_LLEN;
ulCnt = WBSTR_TLEN(pb);
pdpv->wbstrVal = (WBSTR)TaskMemAlloc(ulCnt);
memcpy(pdpv->wbstrVal, WBSTR_PTR(pb), ulCnt);
pdpv->wbstrVal = (WBSTR)((BYTE *)pdpv->wbstrVal+WBSTR_LLEN);
pb += ulCnt-WBSTR_LLEN;
break;
case VT_WBSTR | VT_VECTOR:
olMem(pdpv->cawbstr.pElems =
(WBSTR *)TaskMemAlloc(sizeof(WBSTR)*ulCnt));
for (i = 0; i < ulCnt; i++)
{
pb += WBSTR_LLEN;
cb = WBSTR_TLEN(pb);
pdpv->cawbstr.pElems[i] = (WBSTR)TaskMemAlloc(cb);
if (pdpv->cawbstr.pElems[i] == NULL)
break;
memcpy(pdpv->cawbstr.pElems[i], WBSTR_PTR(pb), cb);
pdpv->cawbstr.pElems[i] =
(WBSTR)((BYTE *)pdpv->cawbstr.pElems[i]+WBSTR_LLEN);
pb += cb-WBSTR_LLEN;
}
if (i != ulCnt)
{
while (i > 0)
{
i--;
TaskMemFree(pdpv->cawbstr.pElems[i]);
}
TaskMemFree(pdpv->cawbstr.pElems);
sc = STG_E_INSUFFICIENTMEMORY;
}
break;
#endif
case VT_LPSTR:
ulCnt = strlen((char *)pb)+1;
olMem(pdpv->pszVal = (char *)TaskMemAlloc(ulCnt));
memcpy(pdpv->pszVal, pb, ulCnt);
pb += ulCnt;
break;
case VT_LPSTR | VT_VECTOR:
olMem(pdpv->calpstr.pElems =
(LPSTR *)TaskMemAlloc(sizeof(LPSTR)*ulCnt));
for (i = 0; i < ulCnt; i++)
{
cb = strlen((char *)pb)+1;
pdpv->calpstr.pElems[i] = (LPSTR)TaskMemAlloc(cb);
if (pdpv->calpstr.pElems[i] == NULL)
break;
memcpy(pdpv->calpstr.pElems[i], pb, cb);
pb += cb;
}
if (i != ulCnt)
{
while (i > 0)
{
i--;
TaskMemFree(pdpv->calpstr.pElems[i]);
}
TaskMemFree(pdpv->calpstr.pElems);
sc = STG_E_INSUFFICIENTMEMORY;
}
break;
case VT_BOOL:
GET_SIMPLE_VAL(VARIANT_BOOL);
break;
case VT_BOOL | VT_VECTOR:
GET_SIMPLE_VECTOR(VARIANT_BOOL);
break;
case VT_I8:
GET_SIMPLE_VAL(LARGE_INTEGER);
break;
case VT_I8 | VT_VECTOR:
GET_SIMPLE_VECTOR(LARGE_INTEGER);
break;
case VT_BLOB:
case VT_BLOB_OBJECT:
ulCnt = *(ULONG UNALIGNED *)pb;
pb += sizeof(ULONG);
olMem(pdpv->blob.pBlobData = (BYTE *)TaskMemAlloc(ulCnt));
pdpv->blob.cbSize = ulCnt;
memcpy(pdpv->blob.pBlobData, pb, ulCnt);
pb += ulCnt;
break;
case VT_LPWSTR:
ulCnt = (wcslen((WCHAR *)pb)+1)*sizeof(WCHAR);
olMem(pdpv->pwszVal = (WCHAR *)TaskMemAlloc(ulCnt));
memcpy(pdpv->pwszVal, pb, ulCnt);
pb += ulCnt;
break;
case VT_LPWSTR | VT_VECTOR:
olMem(pdpv->calpwstr.pElems =
(LPWSTR *)TaskMemAlloc(sizeof(LPWSTR)*ulCnt));
for (i = 0; i < ulCnt; i++)
{
cb = (wcslen((WCHAR *)pb)+1)*sizeof(WCHAR);
pdpv->calpwstr.pElems[i] = (LPWSTR)TaskMemAlloc(cb);
if (pdpv->calpwstr.pElems[i] == NULL)
break;
memcpy(pdpv->calpwstr.pElems[i], pb, cb);
pb += cb;
}
if (i != ulCnt)
{
while (i > 0)
{
i--;
TaskMemFree(pdpv->calpwstr.pElems[i]);
}
TaskMemFree(pdpv->calpwstr.pElems);
sc = STG_E_INSUFFICIENTMEMORY;
}
break;
case VT_FILETIME:
GET_SIMPLE_VAL(FILETIME);
break;
case VT_FILETIME | VT_VECTOR:
GET_SIMPLE_VECTOR(FILETIME);
break;
case VT_UUID:
olMem(pdpv->puuid = (GUID *)TaskMemAlloc(sizeof(GUID)));
memcpy(pdpv->puuid, pb, sizeof(GUID));
pb += sizeof(GUID);
break;
case VT_UUID | VT_VECTOR:
GET_SIMPLE_VECTOR(GUID);
break;
case VT_VARIANT:
olMem(pdpv->pvarVal = (DFPROPVAL *)TaskMemAlloc(sizeof(DFPROPVAL)));
VariantInit(pdpv->pvarVal);
pdpv->pvarVal->vt = *(VARTYPE UNALIGNED *)pb;
pb += sizeof(VARTYPE);
if (FAILED(sc = BufferToPropValue(&pb, pdpv->pvarVal)))
{
TaskMemFree(pdpv->pvarVal);
}
break;
case VT_VARIANT | VT_VECTOR:
olMem(pdpv->cavar.pElems =
(DFPROPVAL *)TaskMemAlloc(sizeof(DFPROPVAL)*ulCnt));
for (i = 0; i < ulCnt; i++)
{
VariantInit(pdpv->cavar.pElems+i);
pdpv->cavar.pElems[i].vt = *(VARTYPE UNALIGNED *)pb;
pb += sizeof(VARTYPE);
if (FAILED(sc = BufferToPropValue(&pb, pdpv->cavar.pElems+i)))
{
if (i > 0)
olHVerSucc(FreeVariantArray(i, pdpv->cavar.pElems));
TaskMemFree(pdpv->cavar.pElems);
break;
}
}
break;
case VT_CF:
ulCnt = *(ULONG UNALIGNED *)pb;
pb += sizeof(ULONG);
olMem(pdpv->pClipData = (CLIPDATA *)TaskMemAlloc(sizeof(CLIPDATA)));
if (pdpv->pClipData->pClipData = (BYTE *)TaskMemAlloc(ulCnt))
{
pdpv->pClipData->cbSize = ulCnt+sizeof(ULONG);
pdpv->pClipData->ulClipFmt = *(ULONG UNALIGNED *)pb;
pb += sizeof(ULONG);
memcpy(pdpv->pClipData->pClipData, pb, ulCnt);
pb += ulCnt;
}
else
{
TaskMemFree(pdpv->pClipData);
sc = STG_E_INSUFFICIENTMEMORY;
}
break;
default:
olAssert(!aMsg("Unknown property type in BufferToPropValue"));
sc = STG_E_INVALIDFUNCTION;
break;
}
*ppb = pb;
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::BufferToPropValue\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::PropValueToBuffer, private
//
// Synopsis: Puts a property value into a buffer
//
// Arguments: [pdpv] - Property value
// [pcb] - Size return
// [pb] - Buffer to serialize into or NULL
//
//
// Returns: Appropriate status code
//
// Modifies: [pcb]
//
// History: 14-Oct-92 DrewB Created
//
// Notes: Responsible for checking validity of data before use
// If [pb] is NULL then only the size is computed
//
//----------------------------------------------------------------------------
#define SET_SIMPLE_VAL(type) \
*pcb = sizeof(type); \
if (pb) \
memcpy(pb, &pdpv->iVal, sizeof(type))
#define SET_SIMPLE_VECTOR(type) \
*pcb = sizeof(type)*pdpv->cai.cElems; \
if (pb) \
{ \
olChk(ValidateBuffer(pdpv->cai.pElems, *pcb)); \
*(ULONG UNALIGNED *)pb = pdpv->cai.cElems; \
pb += sizeof(ULONG); \
memcpy(pb, pdpv->cai.pElems, *pcb); \
} \
*pcb += sizeof(ULONG)
SCODE CExposedDocFile::PropValueToBuffer(DFPROPVAL *pdpv,
ULONG *pcb,
BYTE *pb)
{
SCODE sc = S_OK;
char **plpstr, *pch;
BSTR *pbstr;
#ifdef OLPROPS
WBSTR *pwbstr;
#endif
WCHAR **plpwstr, *pwch;
ULONG i;
ULONG ulCnt = 0;
ULONG cbRecurse;
DFPROPVAL *pdpvA;
olDebugOut((DEB_ITRACE, "In CExposedDocFile::PropValueToBuffer:%p("
"%p, %p, %p)\n", this, pdpv, pcb, pb));
olChk(ValidatePropType(pdpv->vt));
// Make zero-length arrays illegal
if ((pdpv->vt & VT_VECTOR) && pdpv->cai.cElems == 0)
olErr(EH_Err, STG_E_INVALIDPARAMETER);
switch(pdpv->vt)
{
case VT_EMPTY:
*pcb = 0;
break;
case VT_I2:
SET_SIMPLE_VAL(short);
break;
case VT_I2 | VT_VECTOR:
SET_SIMPLE_VECTOR(short);
break;
case VT_I4:
SET_SIMPLE_VAL(long);
break;
case VT_I4 | VT_VECTOR:
SET_SIMPLE_VECTOR(long);
break;
case VT_R4:
SET_SIMPLE_VAL(float);
break;
case VT_R4 | VT_VECTOR:
SET_SIMPLE_VECTOR(float);
break;
case VT_R8:
SET_SIMPLE_VAL(double);
break;
case VT_R8 | VT_VECTOR:
SET_SIMPLE_VECTOR(double);
break;
case VT_CY:
SET_SIMPLE_VAL(CY);
break;
case VT_CY | VT_VECTOR:
SET_SIMPLE_VECTOR(CY);
break;
case VT_DATE:
SET_SIMPLE_VAL(DATE);
break;
case VT_DATE | VT_VECTOR:
SET_SIMPLE_VECTOR(DATE);
break;
case VT_BSTR:
olChk(ValidateBuffer(BSTR_PTR(pdpv->bstrVal), BSTR_LLEN));
*pcb = BSTR_TLEN(pdpv->bstrVal);
if (pb)
{
olChk(ValidateBuffer(BSTR_PTR(pdpv->bstrVal), *pcb));
memcpy(pb, BSTR_PTR(pdpv->bstrVal), *pcb);
}
break;
case VT_BSTR | VT_VECTOR:
ulCnt = pdpv->cabstr.cElems;
*pcb = sizeof(ULONG);
pbstr = pdpv->cabstr.pElems;
olChk(ValidateBuffer(pbstr, ulCnt*sizeof(BSTR)));
for (i = 0; i < ulCnt; i++)
{
ULONG cb;
olChk(ValidateBuffer(BSTR_PTR(*pbstr), BSTR_LLEN));
cb = BSTR_TLEN(*pbstr);
*pcb += cb;
pbstr++;
}
if (pb)
{
*(ULONG UNALIGNED *)pb = ulCnt;
pb += sizeof(ULONG);
pbstr = pdpv->cabstr.pElems;
for (i = 0; i < ulCnt; i++)
{
olChk(ValidateBuffer(*pbstr, BSTR_BLEN(*pbstr)));
memcpy(pb, BSTR_PTR(*pbstr), BSTR_TLEN(*pbstr));
pb += BSTR_TLEN(*pbstr);
pbstr++;
}
}
break;
#ifdef OLDPROPS
case VT_WBSTR:
olChk(ValidateBuffer(WBSTR_PTR(pdpv->wbstrVal), WBSTR_LLEN));
*pcb = WBSTR_TLEN(pdpv->wbstrVal);
if (pb)
{
olChk(ValidateBuffer(WBSTR_PTR(pdpv->wbstrVal), *pcb));
memcpy(pb, WBSTR_PTR(pdpv->wbstrVal), *pcb);
}
break;
case VT_WBSTR | VT_VECTOR:
ulCnt = pdpv->cawbstr.cElems;
*pcb = sizeof(ULONG);
pwbstr = pdpv->cawbstr.pElems;
olChk(ValidateBuffer(pwbstr, ulCnt*sizeof(WBSTR)));
for (i = 0; i < ulCnt; i++)
{
ULONG cb;
olChk(ValidateBuffer(WBSTR_PTR(*pwbstr), WBSTR_LLEN));
cb = WBSTR_TLEN(*pwbstr);
*pcb += cb;
pwbstr++;
}
if (pb)
{
*(ULONG UNALIGNED *)pb = ulCnt;
pb += sizeof(ULONG);
pwbstr = pdpv->cawbstr.pElems;
for (i = 0; i < ulCnt; i++)
{
olChk(ValidateBuffer(*pwbstr, WBSTR_BLEN(*pwbstr)));
memcpy(pb, WBSTR_PTR(*pwbstr), WBSTR_TLEN(*pwbstr));
pb += WBSTR_TLEN(*pwbstr);
pwbstr++;
}
}
break;
#endif
case VT_LPSTR:
olChk(ValidateSz(pdpv->pszVal, 0xffffffff));
*pcb = strlen(pdpv->pszVal)+1;
if (pb)
memcpy(pb, pdpv->pszVal, *pcb);
break;
case VT_LPSTR | VT_VECTOR:
ulCnt = pdpv->calpstr.cElems;
*pcb = sizeof(ULONG);
plpstr = pdpv->calpstr.pElems;
olChk(ValidateBuffer(plpstr, ulCnt*sizeof(LPSTR)));
for (i = 0; i < ulCnt; i++)
{
ULONG cb;
olChk(ValidateSz(*plpstr, 0xffffffff));
cb = strlen(*plpstr)+1;
*pcb += cb;
plpstr++;
}
if (pb)
{
*(ULONG UNALIGNED *)pb = ulCnt;
pb += sizeof(ULONG);
pch = (char *)pb;
plpstr = pdpv->calpstr.pElems;
for (i = 0; i < ulCnt; i++)
{
strcpy(pch, *plpstr);
pch += strlen(*plpstr)+1;
plpstr++;
}
}
break;
case VT_BOOL:
SET_SIMPLE_VAL(VARIANT_BOOL);
break;
case VT_BOOL | VT_VECTOR:
SET_SIMPLE_VECTOR(VARIANT_BOOL);
break;
case VT_I8:
SET_SIMPLE_VAL(LARGE_INTEGER);
break;
case VT_I8 | VT_VECTOR:
SET_SIMPLE_VECTOR(LARGE_INTEGER);
break;
case VT_BLOB:
case VT_BLOB_OBJECT:
*pcb = pdpv->blob.cbSize+sizeof(ULONG);
if (pb)
{
*(ULONG UNALIGNED *)pb = pdpv->blob.cbSize;
pb += sizeof(ULONG);
memcpy(pb, pdpv->blob.pBlobData, pdpv->blob.cbSize);
}
break;
case VT_LPWSTR:
olChk(ValidateWcs(pdpv->pwszVal, 0xffffffff));
*pcb = (wcslen(pdpv->pwszVal)+1)*sizeof(WCHAR);
if (pb)
memcpy(pb, pdpv->pwszVal, *pcb);
break;
case VT_LPWSTR | VT_VECTOR:
ulCnt = pdpv->calpwstr.cElems;
*pcb = sizeof(ULONG);
plpwstr = pdpv->calpwstr.pElems;
olChk(ValidateBuffer(plpwstr, ulCnt*sizeof(LPWSTR)));
for (i = 0; i < ulCnt; i++)
{
ULONG cb;
olChk(ValidateWcs(*plpwstr, 0xffffffff));
cb = (wcslen(*plpwstr)+1)*sizeof(WCHAR);
*pcb += cb;
plpwstr++;
}
if (pb)
{
*(ULONG UNALIGNED *)pb = ulCnt;
pb += sizeof(ULONG);
pwch = (WCHAR *)pb;
plpwstr = pdpv->calpwstr.pElems;
for (i = 0; i < ulCnt; i++)
{
wcscpy(pwch, *plpwstr);
pwch += wcslen(*plpwstr)+1;
plpwstr++;
}
}
break;
case VT_FILETIME:
SET_SIMPLE_VAL(FILETIME);
break;
case VT_FILETIME | VT_VECTOR:
SET_SIMPLE_VECTOR(FILETIME);
break;
case VT_UUID:
*pcb = sizeof(GUID);
if (pb)
{
olChk(ValidateBuffer(pdpv->puuid, sizeof(GUID)));
memcpy(pb, pdpv->puuid, sizeof(GUID));
}
break;
case VT_UUID | VT_VECTOR:
SET_SIMPLE_VECTOR(GUID);
break;
case VT_VARIANT:
olChk(ValidateBuffer(pdpv->pvarVal, sizeof(DFPROPVAL)));
if (pb)
{
*(VARTYPE UNALIGNED *)pb = pdpv->pvarVal->vt;
pb += sizeof(VARTYPE);
}
olChk(PropValueToBuffer(pdpv->pvarVal, &cbRecurse, pb));
*pcb = sizeof(VARTYPE)+cbRecurse;
break;
case VT_VARIANT | VT_VECTOR:
ulCnt = pdpv->cavar.cElems;
*pcb = sizeof(ULONG);
pdpvA = pdpv->cavar.pElems;
olChk(ValidateBuffer(pdpvA, ulCnt*sizeof(DFPROPVAL)));
if (pb)
{
*(ULONG UNALIGNED *)pb = ulCnt;
pb += sizeof(ULONG);
}
for (i = 0; i<ulCnt; i++)
{
if (pb)
{
*(VARTYPE UNALIGNED *)pb = pdpvA->vt;
pb += sizeof(VARTYPE);
}
olChk(PropValueToBuffer(pdpvA, &cbRecurse, pb));
*pcb += sizeof(VARTYPE)+cbRecurse;
if (pb)
pb += cbRecurse;
pdpvA++;
}
break;
case VT_CF:
olChk(ValidateBuffer(pdpv->pClipData, sizeof(CLIPDATA)));
*pcb = pdpv->pClipData->cbSize+sizeof(ULONG);
if (pb)
{
olChk(ValidateBuffer(pdpv->pClipData->pClipData,
pdpv->pClipData->cbSize-sizeof(ULONG)));
*(ULONG UNALIGNED *)pb = pdpv->pClipData->cbSize-sizeof(ULONG);
pb += sizeof(ULONG);
*(ULONG UNALIGNED *)pb = pdpv->pClipData->ulClipFmt;
pb += sizeof(ULONG);
memcpy(pb, pdpv->pClipData->pClipData,
pdpv->pClipData->cbSize-sizeof(ULONG));
}
break;
default:
olAssert(!aMsg("Unknown property type in PropValueToBuffer"));
sc = STG_E_INVALIDFUNCTION;
break;
}
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::PropValueToBuffer\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::CreateProp, private
//
// Synopsis: Creates a property entry
//
// Arguments: [pdfn] - Name
// [grfMode] - Access mode
// [dpt] - Property type
// [riid] - Type of desired object
// [ppv] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppv]
//
// History: 12-Jan-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CExposedDocFile::CreateProp(CDfName const *pdfn,
DWORD grfMode,
DFPROPTYPE dpt,
REFIID riid,
void **ppv)
{
SCODE sc;
CExposedDocFile *pedf;
CExposedStream *pest;
olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateProp:%p("
"%p, %lX, %X, riid, %p)\n", this, pdfn, grfMode,
dpt, ppv));
if (IsEqualIID(riid, IID_IStorage))
{
olChk(CreateEntry(pdfn, STGTY_STORAGE | STGTY_PROPFLAG,
grfMode, (void **)&pedf));
olChkTo(EH_pedf,
pedf->GetPub()->SetPropType(dpt));
olChkTo(EH_pedf, pedf->GetPub()->Commit(0));
*ppv = pedf;
}
else if (IsEqualIID(riid, IID_IStream))
{
olChk(CreateEntry(pdfn, STGTY_STREAM | STGTY_PROPFLAG,
grfMode, (void **)&pest));
olChkTo(EH_pest,
pest->GetPub()->SetPropType(dpt));
*ppv = pest;
}
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateProp\n"));
EH_Err:
return sc;
EH_pedf:
pedf->Release();
olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
goto EH_Err;
EH_pest:
pest->Release();
olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
goto EH_Err;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::OpenProp, private
//
// Synopsis: Opens a property entry
//
// Arguments: [pdfn] - Name
// [grfMode] - Access mode
// [dpt] - Property type
// [riid] - Type of desired object
// [ppv] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppv]
//
// History: 12-Jan-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CExposedDocFile::OpenProp(CDfName const *pdfn,
DWORD grfMode,
DFPROPTYPE dpt,
REFIID riid,
void **ppv)
{
SCODE sc;
CExposedDocFile *pedf;
CExposedStream *pest;
DFPROPTYPE dptEnt;
olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenProp:%p("
"%p, %lX, %X, riid, %p)\n", this, pdfn, grfMode,
dpt, ppv));
if (IsEqualIID(riid, IID_IStorage))
{
olChk(OpenEntry(pdfn, STGTY_STORAGE | STGTY_PROPFLAG,
grfMode, (void **)&pedf));
olChkTo(EH_pedf, pedf->GetPub()->GetPropType(&dptEnt));
if (dptEnt != dpt)
olErr(EH_pedf, STG_E_FILENOTFOUND);
*ppv = pedf;
}
else if (IsEqualIID(riid, IID_IStream))
{
olChk(OpenEntry(pdfn, STGTY_STREAM | STGTY_PROPFLAG,
grfMode, (void **)&pest));
olChkTo(EH_pest, pest->GetPub()->GetPropType(&dptEnt));
if (dptEnt != dpt)
olErr(EH_pest, STG_E_FILENOTFOUND);
*ppv = pest;
}
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenProp\n"));
EH_Err:
return sc;
EH_pedf:
pedf->Release();
goto EH_Err;
EH_pest:
pest->Release();
goto EH_Err;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::ReadMultiple, public
//
// Synopsis: Gets property values
//
// Arguments: [cpspec] - Count of properties
// [rgpspec] - Property names
// [pftmModified] - Modify time or NULL
// [rgpropid] - Id return or NULL
// [rgdpv] - Value array to fill in
//
// Returns: Appropriate status code
//
// Modifies: [rgpropid]
//
// History: 13-Oct-92 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CExposedDocFile::ReadMultiple(ULONG cpspec,
PROPSPEC rgpspec[],
FILETIME *pftmModified,
PROPID rgpropid[],
DFPROPVAL rgdpv[])
{
SCODE sc = S_OK;
SAFE_SEM;
SAFE_ACCESS;
ULONG cb;
CDfName dfn;
DFPROPVAL *pdpv;
DWORD grfMode;
ULONG i;
BYTE *pb;
olLog(("%p::In CExposedDocFile::ReadMultiple(%lu, %p, %p, %p, %p)\n",
this, cpspec, rgpspec, pftmModified, rgpropid, rgdpv));
olDebugOut((DEB_TRACE, "In CExposedDocFile::ReadMultiple:%p("
"%lu, %p, %p, %p, %p)\n", this, cpspec, rgpspec,
pftmModified, rgpropid, rgdpv));
if (pftmModified)
{
olChk(ValidateOutBuffer(pftmModified, sizeof(FILETIME)));
memset(pftmModified, 0, sizeof(FILETIME));
}
if (rgpropid)
{
olChk(ValidateOutBuffer(rgpropid, sizeof(PROPID)*cpspec));
memset(rgpropid, 0, sizeof(PROPID)*cpspec);
}
olChk(ValidateOutBuffer(rgdpv, sizeof(DFPROPVAL)*cpspec));
for (i = 0; i < cpspec; i++)
{
// BUGBUG - VariantClear doesn't handle all of the supported
// property types
// olChk(VariantClear(&rgdpv[i]));
VariantInit(&rgdpv[i]);
}
olChk(ValidatePropSpecs(cpspec, rgpspec));
olChk(Validate());
olChk(_pdf->CheckReverted());
olChk(TakeSafeSem());
SafeReadAccess();
if (pftmModified)
{
FILETIME ft;
// Retrieve modification time
olChk(_pdf->GetDF()->GetTime(WT_MODIFICATION, &ft));
*pftmModified = ft;
}
// Compute child activation mode from propset mode
grfMode = (DFlagsToMode(_pdf->GetDFlags()) &
(STGM_READ | STGM_WRITE | STGM_READWRITE |
STGM_TRANSACTED)) | STGM_SHARE_EXCLUSIVE;
pdpv = rgdpv;
for (i = 0; i < cpspec; i++)
{
// The docfile can't take advantage of this optimization
// so just skip indeterminate requests
if (rgpspec[i].ulKind == PRSPEC_PROPID &&
rgpspec[i].propid == PROPID_UNKNOWN)
{
if (rgpropid)
rgpropid[i] = PROPID_UNKNOWN;
pdpv++;
continue;
}
olChkTo(EH_Next, SpecToDfName(&rgpspec[i], &dfn));
olChkTo(EH_Next, _sp.Get(&dfn, pdpv, &cb, &pb));
switch(pdpv->vt)
{
case VT_STREAM:
case VT_STREAMED_OBJECT:
olChkTo(EH_Next,
OpenProp(&dfn, grfMode & ~STGM_TRANSACTED, pdpv->vt,
IID_IStream, (void **)&pdpv->pIStream));
break;
case VT_STORAGE:
case VT_STORED_OBJECT:
olChkTo(EH_Next,
OpenProp(&dfn, grfMode, pdpv->vt, IID_IStorage,
(void **)&pdpv->pIStorage));
break;
default:
if (pb != NULL)
{
BYTE *pbTmp = pb;
sc = BufferToPropValue(&pbTmp, pdpv);
TaskMemFree(pb);
olChkTo(EH_Next, sc);
}
break;
}
if (rgpropid)
sc = GetSpecId(&rgpspec[i], &rgpropid[i], TRUE);
EH_Next:
if (FAILED(sc))
{
if (sc == STG_E_FILENOTFOUND)
{
pdpv->vt = VT_ILLEGAL;
if (rgpropid)
rgpropid[i] = PROPID_UNKNOWN;
}
else
olErr(EH_Clear, sc);
}
pdpv++;
}
sc = S_OK;
olDebugOut((DEB_TRACE, "Out CExposedDocFile::ReadMultiple\n"));
EH_Err:
olLog(("%p::Out CExposedDocFile::ReadMultiple(). sc == %lX\n",
this, sc));
return ResultFromScode(sc);
EH_Clear:
if (i > 0)
olHVerSucc(FreeVariantArray(i, rgdpv));
if (rgpropid)
memset(rgpropid, 0, sizeof(PROPID)*cpspec);
goto EH_Err;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::WriteMultiple, public
//
// Synopsis: Sets property values
//
// Arguments: [cpspec] - Count of properties
// [rgpspec] - Property names
// [rgpropid] - Property id return
// [rgdpv] - Value array
//
// Returns: Appropriate status code
//
// Modifies: [rgpropid]
//
// History: 13-Oct-92 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CExposedDocFile::WriteMultiple(ULONG cpspec,
PROPSPEC rgpspec[],
PROPID rgpropid[],
DFPROPVAL rgdpv[])
{
SCODE sc = S_OK;
CDfName dfn;
SAFE_SEM;
ULONG cb;
BYTE *pb;
ULONG i;
DFPROPVAL *pdpv;
olLog(("%p::In CExposedDocFile::WriteMultiple(%lu, %p, %p, %p)\n",
this, cpspec, rgpspec, rgpropid, rgdpv));
olDebugOut((DEB_TRACE, "In CExposedDocFile::WriteMultiple:%p("
"%lu, %p, %p, %p)\n", this, cpspec, rgpspec, rgpropid, rgdpv));
olChk(ValidatePropSpecs(cpspec, rgpspec));
if (rgpropid)
{
olChk(ValidateBuffer(rgpropid, sizeof(PROPID)*cpspec));
memset(rgpropid, 0, sizeof(PROPID)*cpspec);
}
olChk(ValidateBuffer(rgdpv, sizeof(DFPROPVAL)*cpspec));
olChk(Validate());
olChk(_pdf->CheckReverted());
olChk(TakeSafeSem());
SetWriteAccess();
pdpv = rgdpv;
for (i = 0; i < cpspec; i++)
{
olChkTo(EH_Clear, SpecToDfName(&rgpspec[i], &dfn));
switch(pdpv->vt)
{
case VT_STREAM:
case VT_STREAMED_OBJECT:
CExposedStream *pest;
ULARGE_INTEGER cbCopy;
LARGE_INTEGER liZero;
olChkTo(EH_Clear,
ValidateInterface(pdpv->pIStream, IID_IStream));
olChkTo(EH_Clear,
CreateProp(&dfn, STGM_WRITE | STGM_CREATE |
STGM_SHARE_EXCLUSIVE, pdpv->vt,
IID_IStream, (void **)&pest));
ULISet32(cbCopy, 0xffffffff);
ClearWriteAccess();
LISet32(liZero, 0);
sc = pdpv->pIStream->Seek(liZero, STREAM_SEEK_SET, NULL);
if (SUCCEEDED(sc))
sc = pdpv->pIStream->CopyTo(pest, cbCopy, NULL, NULL);
pest->Release();
olChkTo(EH_Clear, sc);
SetWriteAccess();
break;
case VT_STORAGE:
case VT_STORED_OBJECT:
CExposedDocFile *pedf;
olChkTo(EH_Clear, ValidateInterface(pdpv->pIStorage,
IID_IStorage));
olChkTo(EH_Clear,
CreateProp(&dfn, STGM_WRITE | STGM_CREATE |
STGM_SHARE_EXCLUSIVE, pdpv->vt,
IID_IStorage, (void **)&pedf));
ClearWriteAccess();
sc = pdpv->pIStorage->CopyTo(0, NULL, NULL, pedf);
pedf->Release();
olChkTo(EH_Clear, sc);
SetWriteAccess();
break;
default:
olChkTo(EH_Clear, PropValueToBuffer(pdpv, &cb, NULL));
if (cb > 0)
{
olMemTo(EH_Clear, pb = (BYTE *)TaskMemAlloc(cb));
olChkTo(EH_pb, PropValueToBuffer(pdpv, &cb, pb));
}
else
pb = NULL;
sc = _sp.Set(&dfn, pdpv, cb, pb);
if (pb)
TaskMemFree(pb);
olChkTo(EH_Clear, sc);
break;
}
if (rgpropid)
olChkTo(EH_Clear, GetSpecId(&rgpspec[i], &rgpropid[i], TRUE));
pdpv++;
}
olDebugOut((DEB_TRACE, "Out CExposedDocFile::WriteMultiple\n"));
EH_Err:
ClearWriteAccess();
olLog(("%p::Out CExposedDocFile::WriteMultiple(). sc == %lX\n",
this, sc));
return ResultFromScode(sc);
EH_pb:
TaskMemFree(pb);
EH_Clear:
if (rgpropid)
memset(rgpropid, 0, sizeof(PROPID)*cpspec);
goto EH_Err;
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::GetIDsOfNames, public
//
// Synopsis: Maps property names to ids
//
// Arguments: [clpwstr] - Count of names
// [rglpwstr] - Names
// [rgpropid] - Id return
//
// Returns: Appropriate status code
//
// Modifies: [rgpropid]
//
// History: 12-May-93 DrewB Created
//
//----------------------------------------------------------------------------
#ifdef GET_IDS_OF_NAMES
SCODE CExposedDocFile::GetIDsOfNames(ULONG clpwstr,
LPWSTR rglpwstr[],
PROPID rgpropid[])
{
ULONG i;
SCODE sc, scSem = STG_E_INUSE, scSingle;
CDfName dfn;
olLog(("%p::In CExposedDocFile::GetIDsOfNames(%lu, %p, %p)\n",
this, clpwstr, rglpwstr, rgpropid));
olDebugOut((DEB_TRACE, "In CExposedDocFile::GetIDsOfNames:%p("
"%lu, %p, %p)\n", this, clpwstr, rglpwstr, rgpropid));
TRY
{
olChk(ValidateBuffer(rglpwstr, sizeof(WCHAR *)*clpwstr));
for (i = 0; i < clpwstr; i++)
olChk(CheckPropertyName(rglpwstr[i]));
olChk(ValidateOutBuffer(rgpropid, sizeof(PROPID)*clpwstr));
memset(rgpropid, 0, sizeof(PROPID)*clpwstr);
olChk(Validate());
PROPSPEC pspec;
olChk(scSem = SetReadAccess());
pspec.fPropid = FALSE;
sc = S_OK;
for (i = 0; i < clpwstr; i++)
{
pspec.lpwstrName = rglpwstr[i];
// Can't fail for names
olVerSucc(SpecToDfName(&pspec, &dfn));
// Does any such property exist?
scSingle = _sp.Exists(&dfn);
if (scSingle == STG_E_FILENOTFOUND)
rgpropid[i] = PROPID_UNKNOWN;
else if (FAILED(sc))
sc = scSingle;
else
{
// It exists, so there's either a mapping for it or
// we should make one
scSingle = GetSpecId(&pspec, &rgpropid[i], TRUE);
if (FAILED(scSingle))
sc = scSingle;
}
}
}
CATCH(CException, e)
{
sc = e.GetErrorCode();
}
END_CATCH
olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetIDsOfNames\n"));
EH_Err:
ClearReadAccess(scSem);
olLog(("%p::Out CExposedDocFile::GetIDsOfNames(). sc == %lX\n",
this, sc));
return ResultFromScode(sc);
}
#endif
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::DeleteMultiple, public
//
// Synopsis: Deletes properties
//
// Arguments: [cpspec] - Count of names
// [rgpspec] - Names
//
// Returns: Appropriate status code
//
// History: 13-Oct-92 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CExposedDocFile::DeleteMultiple(ULONG cpspec,
PROPSPEC rgpspec[])
{
SCODE scFinal = S_OK, sc;
SAFE_SEM;
SAFE_ACCESS;
CDfName dfn;
ULONG i;
olLog(("%p::In CExposedDocFile::DeleteMultiple(%lu, %p)\n",
this, cpspec, rgpspec));
olDebugOut((DEB_TRACE, "In CExposedDocFile::DeleteMultiple:%p("
"%lu, %p)\n", this, cpspec, rgpspec));
olChk(ValidatePropSpecs(cpspec, rgpspec));
olChk(Validate());
olChk(_pdf->CheckReverted());
olChk(TakeSafeSem());
SafeWriteAccess();
for (i = 0; i < cpspec; i++)
{
sc = SpecToDfName(&rgpspec[i], &dfn);
if (SUCCEEDED(sc))
sc = _pdf->DestroyEntry(&dfn, FALSE);
if (FAILED(sc) && sc != STG_E_FILENOTFOUND)
scFinal = sc;
}
sc = scFinal;
olDebugOut((DEB_TRACE, "Out CExposedDocFile::DeleteMultiple\n"));
EH_Err:
olLog(("%p::Out CExposedDocFile::DeleteMultiple(). sc == %lX\n",
this, sc));
return ResultFromScode(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::Enum, public
//
// Synopsis: Create a property enumerator
//
// Arguments: [ppenm] - Enumerator return
//
// Returns: Appropriate status code
//
// Modifies: [ppenm]
//
// History: 17-Dec-92 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CExposedDocFile::Enum(IEnumSTATPROPSTG **ppenm)
{
SCODE sc;
SAFE_SEM;
SAFE_ACCESS;
SafeCExposedPropertyIter pepi;
CDfName dfnTmp;
olLog(("%p::In CExposedDocFile::Enum(%p)\n", this, ppenm));
olDebugOut((DEB_TRACE, "In CExposedDocFile::Enum:%p(%p)\n",
this, ppenm));
olChk(ValidateOutPtrBuffer(ppenm));
*ppenm = NULL;
olChk(Validate());
olChk(_pdf->CheckReverted());
olChk(TakeSafeSem());
SafeReadAccess();
pepi.Attach(new CExposedPropertyIter(this, BP_TO_P(CPubDocFile *, _pdf),
&dfnTmp, BP_TO_P(CDFBasis *, _pdfb),
_ppc, FALSE));
olMem((CExposedPropertyIter *)pepi);
TRANSFER_INTERFACE(pepi, IEnumSTATPROPSTG, ppenm);
olDebugOut((DEB_TRACE, "Out CExposedDocFile::Enum\n"));
EH_Err:
olLog(("%p::Out CExposedDocFile::Enum(). sc == %lX\n", this, sc));
return ResultFromScode(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CExposedDocFile::Stat, public
//
// Synopsis: Returns information about this property set
//
// Arguments: [pstat] - Stat structure to fill in
//
// Returns: Appropriate status code
//
// Modifies: [pstat]
//
// History: 30-Nov-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CExposedDocFile::Stat(STATPROPSETSTG *pstat)
{
SCODE sc;
SAFE_SEM;
SAFE_ACCESS;
FILETIME ft;
CDfName *pdfn;
olLog(("%p::In CExposedDocFile::Stat(%p)\n",
this, pstat));
olDebugOut((DEB_ITRACE, "In CExposedDocFile::Stat:%p(%p)\n",
this, pstat));
olChk(ValidateBuffer(pstat, sizeof(STATPROPSETSTG)));
memset(pstat, 0, sizeof(STATPROPSETSTG));
olChk(Validate());
olChk(_pdf->CheckReverted());
olChk(TakeSafeSem());
SafeReadAccess();
pdfn = _pdf->GetName();
olAssert(pdfn->GetLength() == CBPROPSETNAME);
memcpy(&pstat->iid, pdfn->GetBuffer()+2*sizeof(WCHAR), sizeof(IID));
olChk(_pdf->GetDF()->GetTime(WT_CREATION, &ft));
pstat->ctime = ft;
olChk(_pdf->GetDF()->GetTime(WT_MODIFICATION, &ft));
pstat->mtime = ft;
olChk(_pdf->GetDF()->GetTime(WT_ACCESS, &ft));
pstat->atime = ft;
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Stat\n"));
EH_Err:
olLog(("%p::Out CExposedDocFile::Stat(). sc == %lX\n", this, sc));
return sc;
}