NT4/private/ole32/stg/docfile/tests/oprop.cxx
2020-09-30 17:12:29 +02:00

623 lines
17 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: oprop.cxx
//
// Contents: OFS property test
//
// History: 03-Sep-93 DrewB Created
//
//----------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
struct PropDesc
{
DFPROPTYPE dpt;
char *pszName;
BOOL fArray;
size_t size;
};
PropDesc props[] =
{
VT_I2, "I2", TRUE, sizeof(short int),
VT_I4, "I4", TRUE, sizeof(long int),
VT_R4, "R4", TRUE, sizeof(float),
VT_R8, "R8", TRUE, sizeof(double),
VT_CY, "Currency", TRUE, sizeof(CY),
VT_DATE, "Date", TRUE, sizeof(DATE),
VT_BSTR, "Basic string", FALSE, sizeof(BSTR),
VT_BOOL, "BOOL", TRUE, sizeof(VARIANT_BOOL),
VT_I8, "I8", TRUE, sizeof(LARGE_INTEGER),
VT_LPSTR, "char string", TRUE, sizeof(LPSTR),
VT_BLOB, "BLOB", FALSE, sizeof(BLOB),
VT_LPWSTR, "WCHAR string", TRUE, sizeof(LPWSTR),
VT_FILETIME, "File time", TRUE, sizeof(FILETIME),
VT_UUID, "UUID", TRUE, sizeof(GUID)
#ifdef FULL_PROPS
,
VT_STREAM, "Stream", FALSE, sizeof(IStream *),
VT_STREAMED_OBJECT, "Streamed object", FALSE, sizeof(IStream *),
VT_STORAGE, "Storage", FALSE, sizeof(IStorage *),
VT_STORED_OBJECT, "Stored object", FALSE, sizeof(IStorage *)
#endif
};
#define CPROPS (sizeof(props)/sizeof(props[0]))
#define CTOTPROPS (2*CPROPS)
#define ARRAY_SIZE 16
struct _BSTR
{
UINT len;
char str[80];
};
#define I2_VAL 0x8564
#define I4_VAL 0xfef1f064
#define R4_VAL 1.25
#define R8_VAL 3.1415926535
#define DATE_VAL 4.0
#define F_VAL TRUE
#define BSTR_STR "This is a BSTR"
_BSTR BSTR_VAL = {sizeof(BSTR_STR)-1, BSTR_STR};
#define LPSTR_VAL "This is an LPSTR"
#define BLOB_VAL "This is binary data for a BLOB"
#define LPWSTR_VAL L"This is an LPWSTR"
#define STREAM_VAL "This is data for an IStream"
LARGE_INTEGER I8_VAL = {0x12345678, 0x87654321};
WCHAR wcsNames[CTOTPROPS][CWCSTORAGENAME];
WCHAR *pwcsNames[CTOTPROPS];
IStorage *pstgProp;
IStream *pstmProp;
int prop_index(DFPROPTYPE dpt)
{
int i;
for (i = 0; i<CPROPS; i++)
if (dpt == props[i].dpt)
return i;
printf("** Unknown prop type 0x%X **\n", dpt);
return 0;
}
void MakeSingleVal(DFPROPTYPE dpt, void *pval)
{
switch(dpt)
{
case VT_I2:
*(short int *)pval = (short int)I2_VAL;
break;
case VT_I4:
*(long int *)pval = I4_VAL;
break;
case VT_R4:
*(float *)pval = R4_VAL;
break;
case VT_R8:
*(double *)pval = R8_VAL;
break;
case VT_CY:
CY *pcy;
pcy = (CY *)pval;
pcy->Lo = 0x43215678;
pcy->Hi = 0x56784321;
break;
case VT_DATE:
*(DATE *)pval = DATE_VAL;
break;
case VT_BSTR:
*(BSTR *)pval = (BSTR)&BSTR_VAL.str;
break;
case VT_BOOL:
*(VARIANT_BOOL *)pval = F_VAL;
break;
case VT_I8:
*(LARGE_INTEGER *)pval = I8_VAL;
break;
case VT_LPSTR:
*(LPSTR *)pval = LPSTR_VAL;
break;
case VT_BLOB:
BLOB *pblob;
pblob = new BLOB;
#ifndef ZERO_LENGTH_BLOB
pblob->cbSize = sizeof(BLOB_VAL);
#else
pblob->cbSize = 0;
#endif
pblob->pBlobData = (BYTE *)BLOB_VAL;
*(BLOB **)pval = pblob;
break;
case VT_LPWSTR:
*(LPWSTR *)pval = LPWSTR_VAL;
break;
case VT_FILETIME:
FILETIME *pstm;
pstm = (FILETIME *)pval;
pstm->dwLowDateTime = 0x11223344;
pstm->dwHighDateTime = 0x55667788;
break;
case VT_UUID:
*(GUID **)pval = (GUID *)&IID_IStorage;
break;
case VT_STREAM:
case VT_STREAMED_OBJECT:
*(IStream **)pval = pstmProp;
break;
case VT_STORAGE:
case VT_STORED_OBJECT:
*(IStorage **)pval = pstgProp;
break;
default:
printf("** Unknown property type in MakeVal: %X\n", dpt);
break;
}
}
void MakeVal(DFPROPTYPE dpt, VARIANT *pval)
{
int i;
pval->vt = dpt;
if (dpt & VT_VECTOR)
{
BYTE *pb;
int indx;
indx = prop_index(dpt & ~VT_VECTOR);
pval->pcai = new CAI;
pval->pcai->cElems = ARRAY_SIZE;
pb = new BYTE[props[indx].size*ARRAY_SIZE];
pval->pcai->pElems = (short int *)pb;
for (i = 0; i<ARRAY_SIZE; i++)
{
MakeSingleVal(dpt & ~VT_VECTOR, pb);
pb += props[indx].size;
}
}
else
MakeSingleVal(dpt, &pval->iVal);
}
void UnmakeVal(VARIANT *pval)
{
if (pval->vt & VT_VECTOR)
{
delete pval->pcai->pElems;
delete pval->pcai;
}
else if (pval->vt == VT_BLOB)
delete pval->pblob;
}
void DispSingleVal(DFPROPTYPE dpt, void *pval)
{
switch(dpt)
{
case VT_EMPTY:
printf("empty\n");
break;
case VT_NULL:
printf("null\n");
break;
case VT_I2:
printf("0x%04hX\n", *(short int *)pval);
break;
case VT_I4:
printf("0x%08lX\n", *(long int *)pval);
break;
case VT_R4:
printf("%f\n", *(float *)pval);
break;
case VT_R8:
printf("%lf\n", *(double *)pval);
break;
case VT_CY:
CY *pcy;
pcy = (CY *)pval;
printf("0x%08lX:0x%08lX\n", pcy->Hi, pcy->Lo);
break;
case VT_DATE:
printf("%lf\n", *(DATE *)pval);
break;
case VT_BSTR:
printf("string form: '%s'\n", *(BSTR *)pval);
printf("binary form: %lu bytes\n",
*(UINT *)((BYTE *)*(BSTR *)pval-sizeof(UINT)));
BinText(*(UINT *)((BYTE *)*(BSTR *)pval-sizeof(UINT)),
(BYTE *)*(BSTR *)pval);
break;
case VT_BOOL:
printf("%d\n", *(VARIANT_BOOL *)pval);
break;
case VT_I8:
LARGE_INTEGER *pli;
pli = (LARGE_INTEGER *)pval;
printf("0x%08lX:%08lX\n", pli->HighPart, pli->LowPart);
break;
case VT_LPSTR:
printf("'%s'\n", *(LPSTR *)pval);
break;
case VT_BLOB:
BLOB *pblob;
pblob = *(BLOB **)pval;
printf("%lu bytes\n", pblob->cbSize);
BinText(pblob->cbSize, pblob->pBlobData);
break;
case VT_LPWSTR:
#define BUFSIZE 256
char szVal[BUFSIZE];
wcstombs(szVal, *(LPWSTR *)pval, BUFSIZE);
printf("'%s'\n", szVal);
break;
case VT_FILETIME:
FILETIME *pstm;
pstm = (FILETIME *)pval;
printf("0x%08lX:0x%08lX\n", pstm->dwHighDateTime, pstm->dwLowDateTime);
break;
case VT_UUID:
printf("UUID: %s\n", GuidText(*(GUID **)pval));
break;
case VT_STREAM:
case VT_STREAMED_OBJECT:
IStream *pistm;
pistm = *(IStream **)pval;
BYTE buf[2*sizeof(STREAM_VAL)];
ULONG cbRead;
pistm->Read(buf, 2*sizeof(STREAM_VAL), &cbRead);
printf("read %lu bytes\n", cbRead);
BinText(cbRead, buf);
break;
case VT_STORAGE:
case VT_STORED_OBJECT:
IStorage *pistg;
pistg = *(IStorage **)pval;
printf("contents:\n");
c_tree(pistg);
break;
default:
printf("** Unknown property type in DispVal: 0x%X\n", dpt);
break;
}
}
void DispVal(VARIANT *pdpv)
{
ULONG i;
DFPROPTYPE dpt;
dpt = pdpv->vt & ~VT_VECTOR;
printf("%s val is ", props[prop_index(dpt)].pszName);
if (pdpv->vt & VT_VECTOR)
{
BYTE *pb = (BYTE *)pdpv->pcai->pElems;
int indx = prop_index(dpt);
printf("%lu element array:\n", pdpv->pcai->cElems);
for (i = 0; i<pdpv->pcai->cElems; i++)
{
printf(" %02d - ", i+1);
DispSingleVal(dpt, pb);
pb += props[indx].size;
}
}
else
DispSingleVal(dpt, &pdpv->iVal);
}
void test_props(IPropertyStorage *pprop)
{
VARIANT val[CTOTPROPS], *pval;
PROPSPEC pspec[CTOTPROPS];
ULONG i, cProps;
WCHAR *pwcs, **ppwcs;
FILETIME dtm, ttl;
PROPID id[CTOTPROPS];
HRESULT hr;
// Set up property value data
pval = val;
pwcs = (WCHAR *)&wcsNames[0];
ppwcs = pwcsNames;
cProps = 0;
for (i = 0; i < CPROPS; i++)
{
#if 1
pspec[cProps].ulKind = PRSPEC_LPWSTR;
pspec[cProps].lpwstr = pwcs;
#else
pspec[cProps].ulKind = PRSPEC_DISPID;
pspec[cProps].dispid = i;
#endif
mbstowcs(pwcs, props[i].pszName, CWCSTORAGENAME);
*ppwcs++ = pwcs;
pwcs += CWCSTORAGENAME;
MakeVal(props[i].dpt, pval++);
cProps++;
#if 1
if (props[i].fArray)
{
pspec[cProps].ulKind = PRSPEC_LPWSTR;
pspec[cProps].lpwstr = pwcs;
pwcs[0] = L'#';
mbstowcs(pwcs+1, props[i].pszName, CWCSTORAGENAME);
*ppwcs++ = pwcs;
pwcs += CWCSTORAGENAME;
MakeVal(props[i].dpt | VT_VECTOR, pval++);
cProps++;
}
#endif
}
printf("%lu properties\n", cProps);
// WriteMultiple for named properties
hr = pprop->WriteMultiple(cProps, pspec, id, val);
Result(hr, "WriteMultiple");
for (i = 0; i < cProps; i++)
{
printf("%2d propid is %lu\n", i, id[i]);
UnmakeVal(&val[i]);
}
#if 1
// ReadMultiple for named properties
hr = pprop->ReadMultiple(cProps, pspec, &dtm, &ttl, id, &pval);
Result(hr, "ReadMultiple");
printf("dtm is %s\n", FileTimeText(&dtm));
printf("ttl is 0x%08lX:%08lX\n", ttl.dwHighDateTime, ttl.dwLowDateTime);
for (i = 0; i<cProps; i++)
{
printf("%2d propid is %lu\n", i, id[i]);
DispVal(&pval[i]);
}
hr = FreeVariantArray(cProps, pval);
Result(hr, "FreeVariantArray");
#endif
#if 0
// GetIDsOfNames
hr = pprop->GetIDsOfNames(cProps, pwcsNames, id);
Result(hr, "GetIDsOfNames");
for (i = 0; i < cProps; i++)
printf("%2d propid is %lu\n", i, id[i]);
#endif
#if 1
// Non-existent property
PROPSPEC pspecNot;
pspecNot.ulKind = PRSPEC_LPWSTR;
pspecNot.lpwstr = L"NotThere";
hr = pprop->ReadMultiple(1, &pspecNot, &dtm, &ttl, id, &pval);
Result(hr, "ReadMultiple on non-existent property");
for (i = 0; i<1; i++)
{
printf("%2d propid is %lu\n", i, id[i]);
DispVal(&pval[i]);
}
hr = FreeVariantArray(1, pval);
Result(hr, "FreeVariantArray");
#endif
#if 1
// Enumerator test
IEnumSTATPROPSTG *penm;
STATPROPSTG stat;
char szName[CWCSTORAGENAME];
hr = pprop->Enum(&penm);
Result(hr, "Enum");
for (;;)
{
hr = penm->Next(1, &stat, NULL);
Result(hr, "Next");
if (GetScode(hr) == S_FALSE)
break;
if (stat.lpwstrName)
{
wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
CoMemFree(stat.lpwstrName);
printf("%s, ", szName);
}
printf("vt 0x%X, did %lu, pid %lu, size %lu\n", stat.vt, stat.dispid,
stat.propid, stat.cbSize);
}
printf("Release enumerator = %lu\n",
penm->Release());
#endif
#if 1
// DeleteMultiple
hr = pprop->DeleteMultiple(cProps, pspec);
Result(hr, "DeleteMultiple");
hr = pprop->Enum(&penm);
Result(hr, "Enum");
for (;;)
{
hr = penm->Next(1, &stat, NULL);
Result(hr, "Next");
if (GetScode(hr) == S_FALSE)
break;
if (stat.lpwstrName)
{
wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
CoMemFree(stat.lpwstrName);
printf("%s, ", szName);
}
printf("vt 0x%X, did %lu, pid %lu, size %lu\n", stat.vt, stat.dispid,
stat.propid, stat.cbSize);
}
printf("Release enumerator = %lu\n",
penm->Release());
#endif
// Get a propid
pspec[0].ulKind = PRSPEC_DISPID;
pspec[0].dispid = 2;
MakeVal(VT_I2, val);
cProps = 1;
hr = pprop->WriteMultiple(cProps, pspec, id, val);
Result(hr, "WriteMultiple");
// WriteMultiple with ids and names
pspec[0].ulKind = PRSPEC_DISPID;
pspec[0].dispid = 1;
MakeVal(VT_I2, val);
pspec[1].ulKind = PRSPEC_LPWSTR;
pspec[1].lpwstr = L"TestName";
MakeVal(VT_I4, val+1);
pspec[2].ulKind = PRSPEC_PROPID;
pspec[2].propid = id[0];
MakeVal(VT_I8, val+2);
cProps = 3;
hr = pprop->WriteMultiple(cProps, pspec, id, val);
Result(hr, "WriteMultiple");
for (i = 0; i < cProps; i++)
{
printf("%2d propid is %lu\n", i, id[i]);
UnmakeVal(&val[i]);
}
// ReadMultiple for ids and id for a named property
pspec[1].ulKind = PRSPEC_PROPID;
pspec[1].propid = id[1];
hr = pprop->ReadMultiple(cProps, pspec, &dtm, &ttl, id, &pval);
Result(hr, "ReadMultiple");
printf("dtm is %s\n", FileTimeText(&dtm));
printf("ttl is 0x%08lX:%08lX\n", ttl.dwHighDateTime, ttl.dwLowDateTime);
for (i = 0; i<cProps; i++)
{
printf("%2d propid is %lu\n", i, id[i]);
DispVal(&pval[i]);
}
hr = FreeVariantArray(cProps, pval);
Result(hr, "FreeVariantArray");
}
void _CRTAPI1 main(int argc, char *argv[])
{
IStorage *pstg, *pstgRoot;
IPropertySetStorage *ppset;
IPropertyStorage *pprop;
HRESULT hr;
StartTest("oprop");
CmdArgs(argc, argv);
CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstgRoot, NULL);
hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
(void **)&ppset);
Result(hr, "QI to IPropertySetStorage");
hr = ppset->Create(IID_IPropertySetStorage, STGP(STGM_RW), 0,
&pprop);
Result(hr, "Create propset");
hr = pstgRoot->Commit(0);
Result(hr, "Commit root");
pprop->Release();
ppset->Release();
pstgRoot->Release();
OpenTestFile(NULL, ROOTP(STGM_RW), FALSE, &pstgRoot, NULL);
hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
(void **)&ppset);
Result(hr, "QI to IPropertySetStorage");
hr = ppset->Open(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
Result(hr, "Open propset");
#if 0
// BUGBUG - Should be in propset if possible
pstg = pstgRoot;
hr = pstg->CreateStorage(TEXT("Storage"), STGP(STGM_RW), 0, 0,
&pstgProp);
Result(hr, "Create embedding in propset");
hr = pstgProp->CreateStream(TEXT("Stream"), STMP(STGM_RW), 0, 0,
&pstmProp);
Result(hr, "Create stream in embedding");
hr = pstmProp->Write(STREAM_VAL, sizeof(STREAM_VAL), NULL);
Result(hr, "Write to stream");
LARGE_INTEGER lOff;
LISet32(lOff, 0);
hr = pstmProp->Seek(lOff, STREAM_SEEK_SET, NULL);
Result(hr, "Seek to zero");
#endif
test_props(pprop);
printf("Release IPropertyStorage = %lu\n",
pprop->Release());
#if 0
printf("Release stream = %lu\n",
pstmProp->Release());
printf("Release embedding = %lu\n",
pstgProp->Release());
#endif
#if 0
printf("Release cheat IStorage = %lu\n",
pstg->Release());
#endif
hr = ppset->Open(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
Result(hr, "Open propset");
printf("Release IPropertyStorage = %lu\n",
pprop->Release());
#if 1
IEnumSTATPROPSETSTG *penm;
STATPROPSETSTG stat;
hr = ppset->Enum(&penm);
Result(hr, "Enum");
for (;;)
{
hr = penm->Next(1, &stat, NULL);
Result(hr, "Next");
if (GetScode(hr) == S_FALSE)
break;
printf("IID: %s\n", GuidText(&stat.iid));
printf("ctime %s\n", FileTimeText(&stat.ctime));
printf("mtime %s\n", FileTimeText(&stat.mtime));
printf("atime %s\n", FileTimeText(&stat.atime));
}
printf("Release enumerator = %lu\n",
penm->Release());
#if 0
hr = ppset->Delete(IID_IPropertySetStorage);
Result(hr, "Delete propset");
hr = ppset->Enum(&penm);
Result(hr, "Enum");
for (;;)
{
hr = penm->Next(1, &stat, NULL);
Result(hr, "Next");
if (GetScode(hr) == S_FALSE)
break;
printf("IID: %s\n", GuidText(&stat.iid));
printf("ctime %s\n", FileTimeText(&stat.ctime));
printf("mtime %s\n", FileTimeText(&stat.mtime));
printf("atime %s\n", FileTimeText(&stat.atime));
}
printf("Release enumerator = %lu\n",
penm->Release());
#endif
#endif
printf("Release IPropertySetStorage = %lu\n",
ppset->Release());
printf("Release root docfile = %lu\n",
pstgRoot->Release());
EndTest(0);
}