diff options
Diffstat (limited to 'private/oleutest/stgdrt/tests.cxx')
-rw-r--r-- | private/oleutest/stgdrt/tests.cxx | 812 |
1 files changed, 812 insertions, 0 deletions
diff --git a/private/oleutest/stgdrt/tests.cxx b/private/oleutest/stgdrt/tests.cxx new file mode 100644 index 000000000..f033a6b7b --- /dev/null +++ b/private/oleutest/stgdrt/tests.cxx @@ -0,0 +1,812 @@ +//+-------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1992. +// +// File: tests.cxx +// +// Contents: DRT tests +// +// History: 23-Sep-92 DrewB Created +// +//--------------------------------------------------------------- + +#include "headers.cxx" +#pragma hdrstop + +#include "tests.hxx" +#include "ilb.hxx" + +void t_create(void) +{ + WStorage *pstgRoot, *pstgChild, *pstgChild2; + WStream *pstm; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgRoot); + pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0, + &pstgChild); + pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0, 0, + &pstgChild2); + pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, + &pstm); + pstm->Unwrap(); + pstgChild2->Commit(0); + pstgChild2->Unwrap(); + pstgChild->Commit(0); + pstgChild->Unwrap(); + VerifyStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))"); + pstgRoot->Unwrap(); +} + +void t_open(void) +{ + WStorage *pstgRoot, *pstgChild, *pstgChild2; + WStream *pstm; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgRoot); + CreateStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))"); + pstgRoot->Commit(0); + pstgRoot->Unwrap(); + + WStgOpenStorage(DRTDF, NULL, ROOTP(WSTG_READWRITE), NULL, + 0, &pstgRoot); + pstgRoot->OpenStorage(STR("Child"), NULL, STGP(WSTG_READWRITE), NULL, 0, + &pstgChild); + pstgChild->OpenStorage(STR("Child2"), NULL, STGP(WSTG_READWRITE), NULL, 0, + &pstgChild2); + pstgChild2->OpenStream(STR("Stream"), NULL, STMP(WSTG_READWRITE), 0, + &pstm); + pstm->Unwrap(); + pstgChild2->Unwrap(); + pstgChild->Unwrap(); + pstgRoot->Unwrap(); +} + +void t_addref(void) +{ + WStorage *pstg; + WStream *pstm; + ULONG ul; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstg); + pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); +#ifndef FLAT + if ((ul = pstm->AddRef()) != 2) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + if ((ul = pstm->Release()) != 1) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + pstm->Unwrap(); + if ((ul = pstg->AddRef()) != 2) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + if ((ul = pstg->Release()) != 1) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); +#else + if ((ul = pstm->AddRef()) <= 0) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + if ((ul = pstm->Release()) <= 0) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + pstm->Unwrap(); + if ((ul = pstg->AddRef()) <= 0) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); + if ((ul = pstg->Release()) <= 0) + error(EXIT_BADSC, "Wrong reference count - %lu\n", ul); +#endif + pstg->Unwrap(); +} + +void t_tmodify(void) +{ + WStorage *pstgRoot, *pstgChild, *pstgChild2; + WStream *pstm; + + // This test must use transacted mode to reproduce the + // expected behavior + ForceTransacted(); + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgRoot); + pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, + 0, &pstgChild); + pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0, + 0, &pstgChild2); + pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->Unwrap(); + pstgChild2->Commit(0); + VerifyStructure(pstgChild2->GetI(), "sStream"); + + // Test renaming a closed stream + pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")); + VerifyStructure(pstgChild2->GetI(), "sRenamedStream"); + + // Test rename reversion + pstgChild2->Revert(); + VerifyStructure(pstgChild2->GetI(), "sStream"); + + // Test destruction of closed object + pstgChild2->DestroyElement(STR("Stream")); + pstgChild2->Commit(0); + + // Test create of previously deleted object + pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstgChild2->Commit(0); + VerifyStructure(pstgChild2->GetI(), "sStream"); + +#if 0 + // 08/11/93 - Renaming open children no longer allowed + // Test renaming an open stream + pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")); + VerifyStructure(pstgChild2->GetI(), "sRenamedStream"); +#endif + + pstgChild2->Revert(); + VerifyStructure(pstgChild2->GetI(), "sStream"); + pstgChild2->DestroyElement(STR("Stream")); + pstgChild2->Commit(0); + pstm->Unwrap(); + + pstgChild2->Unwrap(); + VerifyStructure(pstgChild->GetI(), "dChild2()"); + + // Test rename of storage + pstgChild->RenameElement(STR("Child2"), STR("RenamedChild")); + pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, + &pstm); + pstm->Unwrap(); + pstgChild->DestroyElement(STR("Stream")); + pstgChild->Commit(0); + + // Test SetElementTimes + FILETIME tm; + STATSTG stat; + + tm.dwLowDateTime = 0x12345678; + tm.dwHighDateTime = 0x01bcdef0; + + // Set when element not open + pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL); + pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL); + pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm); + + pstgChild->OpenStorage(STR("RenamedChild"), NULL, STGP(WSTG_READWRITE), + NULL, 0, &pstgChild2); + pstgChild2->Stat(&stat, STATFLAG_NONAME); + if (!IsEqualTime(stat.ctime, tm) || + !IsEqualTime(stat.mtime, tm)) + error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n"); + + // Test SetClass and SetStateBits + pstgChild2->SetClass(IID_IStorage); + fExitOnFail = FALSE; + pstgChild2->SetStateBits(0xff00ff00, 0xffffffff); + pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee); + fExitOnFail = TRUE; + pstgChild2->Stat(&stat, STATFLAG_NONAME); + if (!IsEqualCLSID(stat.clsid, IID_IStorage)) + error(EXIT_BADSC, "Class ID set to %s\n", GuidText(&stat.clsid)); + if (stat.grfStateBits != 0x11881188) + errorprint("State bits set improperly: has %lX vs. %lX\n", + stat.grfStateBits, 0x11881188); + pstgChild2->Revert(); + pstgChild2->Stat(&stat, STATFLAG_NONAME); + if (!IsEqualCLSID(stat.clsid, CLSID_NULL)) + error(EXIT_BADSC, "Class ID reverted to %s\n", GuidText(&stat.clsid)); + if (stat.grfStateBits != 0) + errorprint("State bits reverted improperly: has %lX vs. %lX\n", + stat.grfStateBits, 0); + pstgChild2->Unwrap(); + + pstgChild->Unwrap(); + VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())"); + pstgRoot->Revert(); + VerifyStructure(pstgRoot->GetI(), ""); + pstgRoot->Commit(0); + VerifyStructure(pstgRoot->GetI(), ""); + pstgRoot->Unwrap(); + Unforce(); +} + +void t_dmodify(void) +{ + WStorage *pstgRoot, *pstgChild, *pstgChild2; + WStream *pstm; + ULONG cbSize1, cbSize2; + + // This test must use direct mode to reproduce the + // expected behavior + ForceDirect(); + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgRoot); + pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, + 0, &pstgChild); + pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0, + 0, &pstgChild2); + pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->Unwrap(); + VerifyStructure(pstgChild2->GetI(), "sStream"); + + // Test renaming a closed stream + pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")); + VerifyStructure(pstgChild2->GetI(), "sRenamedStream"); + + // Test destroying a stream + pstgChild2->DestroyElement(STR("RenamedStream")); + +#if 0 + // 08/11/93 - Renaming open child no longer allowed + // Test renaming an open stream + pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + VerifyStructure(pstgChild2->GetI(), "sStream"); + pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")); + VerifyStructure(pstgChild2->GetI(), "sRenamedStream"); + pstgChild2->DestroyElement(STR("RenamedStream")); + pstm->Unwrap(); +#endif + + pstgChild2->Unwrap(); + VerifyStructure(pstgChild->GetI(), "dChild2()"); + + // Test renaming a storage + pstgChild->RenameElement(STR("Child2"), STR("RenamedChild")); + pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, + &pstm); + pstm->Unwrap(); + pstgChild->DestroyElement(STR("Stream")); + + // Test SetElementTimes + FILETIME tm; + STATSTG stat; + + tm.dwLowDateTime = 0x12345678; + tm.dwHighDateTime = 0x01bcdef0; + + // Set when element not open + pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL); + pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL); + pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm); + + pstgChild->OpenStorage(STR("RenamedChild"), NULL, STMP(WSTG_READWRITE), + NULL, 0, &pstgChild2); + pstgChild2->Stat(&stat, STATFLAG_NONAME); + if (!IsEqualTime(stat.ctime, tm) || + !IsEqualTime(stat.mtime, tm)) + error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n"); + + // Test SetClass and SetStateBits + pstgChild2->SetClass(IID_IStorage); + fExitOnFail = FALSE; + pstgChild2->SetStateBits(0xff00ff00, 0xffffffff); + pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee); + fExitOnFail = TRUE; + pstgChild2->Stat(&stat, STATFLAG_NONAME); + if (!IsEqualCLSID(stat.clsid, IID_IStorage)) + error(EXIT_BADSC, "Class ID set improperly\n"); + if (stat.grfStateBits != 0x11881188) + errorprint("State bits set improperly: has %lX vs. %lX\n", + stat.grfStateBits, 0x11881188); + pstgChild2->Unwrap(); + + pstgChild->Unwrap(); + VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())"); + pstgRoot->Revert(); + VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())"); + pstgRoot->Commit(0); + VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())"); + pstgRoot->DestroyElement(STR("Child")); + VerifyStructure(pstgRoot->GetI(), ""); + + // Verify that space is reclaimed after modifications + pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->SetSize(65536); + pstm->Unwrap(); + cbSize1 = Length(DRTDF); + pstgRoot->DestroyElement(STR("Stream")); + pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->SetSize(65536); + pstm->Unwrap(); + cbSize2 = Length(DRTDF); + if (cbSize1 != cbSize2) + error(EXIT_BADSC, "Space is not being reclaimed, original %lu, " + "now %lu\n", cbSize1, cbSize2); + + pstgRoot->Unwrap(); + + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstgRoot); + + // removal cases + // 1) no right child + + CreateStructure(pstgRoot->GetI(), "d64,d32"); + VerifyStructure(pstgRoot->GetI(), "d64,d32"); + pstgRoot->DestroyElement(STR("64")); + VerifyStructure(pstgRoot->GetI(), "d32"); + + // 2) right child has no left child + + CreateStructure(pstgRoot->GetI(), "d64"); + VerifyStructure(pstgRoot->GetI(), "d32,d64"); + pstgRoot->DestroyElement(STR("32")); + VerifyStructure(pstgRoot->GetI(), "d64"); + + // 3) right child has left child + + CreateStructure(pstgRoot->GetI(), "d96,d80"); + VerifyStructure(pstgRoot->GetI(), "d64,d80,d96"); + pstgRoot->DestroyElement(STR("64")); + VerifyStructure(pstgRoot->GetI(), "d80,d96"); + + // 4) right child's left child has children + + CreateStructure(pstgRoot->GetI(), "d88,d84,d92"); + VerifyStructure(pstgRoot->GetI(), "d80,d84,d88,d92,d96"); + pstgRoot->DestroyElement(STR("80")); + VerifyStructure(pstgRoot->GetI(), "d84,d88,d92,d96"); + + pstgRoot->Unwrap(); + + Unforce(); +} + +void t_stat(void) +{ + WStorage *pstgRoot, *pstgChild; + WStream *pstm; + STATSTG stat; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgRoot); + pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0, + &pstgChild); + pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + + pstm->Stat(&stat, 0); + VerifyStat(&stat, STR("Stream"), STGTY_STREAM, STMP(WSTG_READWRITE)); + drtMemFree(stat.pwcsName); + + pstm->Stat(&stat, STATFLAG_NONAME); + VerifyStat(&stat, NULL, STGTY_STREAM, STMP(WSTG_READWRITE)); + + pstm->Unwrap(); + + pstgChild->Stat(&stat, 0); + VerifyStat(&stat, STR("Child"), STGTY_STORAGE, STGP(WSTG_READWRITE)); + drtMemFree(stat.pwcsName); + + pstgChild->Stat(&stat, STATFLAG_NONAME); + VerifyStat(&stat, NULL, STGTY_STORAGE, STGP(WSTG_READWRITE)); + + pstgChild->Unwrap(); + + pstgRoot->Stat(&stat, 0); + OLECHAR atcFullPath[_MAX_PATH]; + GetFullPath(DRTDF, atcFullPath); + VerifyStat(&stat, atcFullPath, STGTY_STORAGE, ROOTP(WSTG_READWRITE)); + drtMemFree(stat.pwcsName); + + pstgRoot->Stat(&stat, STATFLAG_NONAME); + VerifyStat(&stat, NULL, STGTY_STORAGE, ROOTP(WSTG_READWRITE)); + + pstgRoot->Unwrap(); +} + +static char NUMBERS[] = "12345678901234567890123456789012345678901234567890"; + +void t_stream(void) +{ + WStorage *pstg; + WStream *pstm, *pstmC; + char buf[sizeof(NUMBERS)*2]; + ULONG cb, ulPos; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg); + pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->Write(NUMBERS, sizeof(NUMBERS), &cb); + pstm->Commit(0); + pstm->Seek(0, WSTM_SEEK_SET, &ulPos); + if (ulPos != 0) + error(EXIT_BADSC, "Incorrect seek, ptr is %lu\n", ulPos); + pstm->Read(buf, sizeof(NUMBERS), &cb); + if (strcmp(buf, NUMBERS)) + error(EXIT_BADSC, "Incorrect stream contents\n"); + pstm->SetSize(sizeof(NUMBERS)/2); + pstm->Seek(0, WSTM_SEEK_SET, NULL); + fExitOnFail = FALSE; + pstm->Read(buf, sizeof(NUMBERS), &cb); + fExitOnFail = TRUE; + if (cb != sizeof(NUMBERS)/2) + error(EXIT_BADSC, "SetSize failed to size stream properly\n"); + if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2)) + error(EXIT_BADSC, "SetSize corrupted contents\n"); + pstm->Clone(&pstmC); + pstm->Seek(0, WSTM_SEEK_SET, NULL); + pstm->CopyTo(pstmC, sizeof(NUMBERS)/2, NULL, NULL); + pstm->Seek(0, WSTM_SEEK_SET, NULL); + pstm->CopyTo(pstmC, sizeof(NUMBERS)&~1, NULL, NULL); + pstm->Seek(0, WSTM_SEEK_SET, NULL); + pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb); + if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) || + memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) || + memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) || + memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2)) + error(EXIT_BADSC, "Stream contents incorrect\n"); + pstmC->Unwrap(); + pstm->Unwrap(); + pstg->Unwrap(); +} + +// Number of entries for enumeration test +#define ENUMENTRIES 10 + +// Flag indicating a name has already shown up in enumeration, +// must not conflict with STGTY_* +#define ENTRY_SEEN 0x100 + +// Check the validity of an enumeration element +static void elt_check(STATSTG *pstat, CStrList *psl) +{ + SStrEntry *pse; + + pse = psl->Find(pstat->pwcsName); + if (pse == NULL) + error(EXIT_BADSC, "Spurious element '%s'\n", pstat->pwcsName); + else if ((pse->user.dw & ~ENTRY_SEEN) != pstat->type) + error(EXIT_BADSC, "Element '%s' has wrong type - " + "has %lX vs. %lX\n", pstat->pwcsName, pstat->type, + pse->user.dw & ~ENTRY_SEEN); + else if (pse->user.dw & ENTRY_SEEN) + error(EXIT_BADSC, "Element '%s' has already been seen\n", + pstat->pwcsName); + pse->user.dw |= ENTRY_SEEN; +} + +// Do final validity checks for enumeration +static void enum_list_check(CStrList *psl) +{ + SStrEntry *pse; + + for (pse = psl->GetHead(); pse; pse = pse->pseNext) + { + if ((pse->user.dw & ENTRY_SEEN) == 0) + error(EXIT_BADSC, "Element '%s' not found\n", pse->atc); + pse->user.dw &= ~ENTRY_SEEN; + } +} + +void t_enum(void) +{ + int i; + OLECHAR atcName[CWCSTORAGENAME]; + WStorage *pstg, *pstg2; + WStream *pstm; + SStrEntry *pse; + CStrList sl; + + // Create some entries to enumerate + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg); + for (i = 0; i<ENUMENTRIES; i++) + { + olecsprintf(atcName, STR("Name%d"), rand()); + pse = sl.Add(atcName); + if (rand()%100 < 50) + { + pse->user.dw = STGTY_STORAGE; + pstg->CreateStorage(atcName, STGP(WSTG_READWRITE), 0, 0, &pstg2); + pstg2->Unwrap(); + } + else + { + pse->user.dw = STGTY_STREAM; + pstg->CreateStream(atcName, STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->Unwrap(); + } + } + + WEnumSTATSTG *penm; + STATSTG stat[2*ENUMENTRIES]; + SCODE sc; + + // Test plain, single element enumeration + pstg->EnumElements(0, NULL, 0, &penm); + for (;;) + { + sc = DfGetScode(penm->Next(1, stat, NULL)); + if (sc == S_FALSE) + break; + elt_check(stat, &sl); + drtMemFree(stat->pwcsName); + + } + enum_list_check(&sl); + + ULONG cFound; + + // Test rewind and multiple element enumeration with too many elements + penm->Reset(); + sc = DfGetScode(penm->Next(ENUMENTRIES*2, stat, &cFound)); + if (sc != S_FALSE) + error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of " + "S_FALSE\n", ScText(sc), sc); + if (cFound != ENUMENTRIES) + error(EXIT_BADSC, "Enumerator found %lu entries instead of " + "%d entries\n", cFound, ENUMENTRIES); + for (; cFound > 0; cFound--) + { + elt_check(&stat[cFound-1], &sl); + drtMemFree(stat[cFound-1].pwcsName); + } + enum_list_check(&sl); + + // Test skip and multiple enumeration with exact number of elements + penm->Reset(); + penm->Skip(ENUMENTRIES/2); + sc = DfGetScode(penm->Next(ENUMENTRIES-ENUMENTRIES/2, stat, &cFound)); + if (sc != S_OK) + error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of " + "S_OK\n", ScText(sc), sc); + if (cFound != ENUMENTRIES-ENUMENTRIES/2) + error(EXIT_BADSC, "Enumerator found %lu entries instead of " + "%d entries\n", cFound, ENUMENTRIES-ENUMENTRIES/2); + for (; cFound > 0; cFound--) + { + elt_check(&stat[cFound-1], &sl); + drtMemFree(stat[cFound-1].pwcsName); + } + sc = DfGetScode(penm->Next(1, stat, NULL)); + if (sc != S_FALSE) + error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of " + "S_FALSE\n", ScText(sc), sc); + + penm->Unwrap(); + pstg->Unwrap(); +} + +#define SCT_CLASSID IID_ILockBytes +#define SCT_STATEBITS 0xfef1f0f0 + +void t_stgcopyto(void) +{ + WStorage *pstgFrom, *pstgTo; + STATSTG statFrom, statTo; + + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstgFrom); + pstgFrom->Stat(&statFrom, 0); + + // Set some interesting values to make sure they're copied + pstgFrom->SetClass(SCT_CLASSID); + fExitOnFail = FALSE; + pstgFrom->SetStateBits(SCT_STATEBITS, 0xffffffff); + fExitOnFail = TRUE; + + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstgTo); + CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs"); + CreateStructure(pstgTo->GetI(), "dA(dY(sZ),sBs)"); + + pstgFrom->CopyTo(0, NULL, NULL, pstgTo); + + VerifyStructure(pstgTo->GetI(), + "dA(dB(dC(sA,sB,sC),sCs),dY(sZ),sBs),sAs"); + pstgTo->Stat(&statTo, 0); + if (!IsEqualCLSID(statTo.clsid, SCT_CLASSID)) + error(EXIT_BADSC, "Class ID mismatch after copy\n"); + if (statTo.grfStateBits != SCT_STATEBITS) + errorprint("State bits mismatch: has %lX vs. %lX\n", + statTo.grfStateBits, SCT_STATEBITS); + + pstgFrom->Unwrap(); + pstgTo->Unwrap(); + if (Exists(statFrom.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName); + drtMemFree(statFrom.pwcsName); + if (Exists(statTo.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName); + drtMemFree(statTo.pwcsName); +} + +#define MARSHAL_STM STR("Marshal") + +void do_marshal(WStorage *pstg, WStream *pstm) +{ + WStorage *pstgMarshal; + WStream *pstmMarshal; + + WStgCreateDocfile(MARSHALDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, + 0, &pstgMarshal); + pstgMarshal->CreateStream(MARSHAL_STM, STMP(WSTG_READWRITE), 0, 0, + &pstmMarshal); + WCoMarshalInterface(pstmMarshal, IID_IStorage, pstg->GetI(), 0, NULL, + MSHLFLAGS_NORMAL); + WCoMarshalInterface(pstmMarshal, IID_IStream, pstm->GetI(), 0, NULL, + MSHLFLAGS_NORMAL); + WCoMarshalInterface(pstmMarshal, IID_IUnknown, pstg->GetI(), 0, NULL, + MSHLFLAGS_NORMAL); + WCoMarshalInterface(pstmMarshal, IID_IUnknown, pstm->GetI(), 0, NULL, + MSHLFLAGS_NORMAL); + pstmMarshal->Unwrap(); + pstgMarshal->Commit(0); + pstgMarshal->Unwrap(); +} + +static char STREAM_DATA[] = "This is data to be written"; + +void do_unmarshal(WStorage **ppstg, WStream **ppstm, + IUnknown **ppstg2, IUnknown **ppstm2) +{ + IStorage *pistg; + WStorage *pstgMarshal; + WStream *pstmMarshal; + IStream *pistm; + + WStgOpenStorage(MARSHALDF, NULL, ROOTP(WSTG_READWRITE), NULL, 0, + &pstgMarshal); + pstgMarshal->OpenStream(MARSHAL_STM, NULL, STMP(WSTG_READWRITE), 0, + &pstmMarshal); + WCoUnmarshalInterface(pstmMarshal, IID_IStorage, (void **)&pistg); + *ppstg = WStorage::Wrap(pistg); + WCoUnmarshalInterface(pstmMarshal, IID_IStream, (void **)&pistm); + *ppstm = WStream::Wrap(pistm); + WCoUnmarshalInterface(pstmMarshal, IID_IUnknown, (void **)ppstg2); + WCoUnmarshalInterface(pstmMarshal, IID_IUnknown, (void **)ppstm2); + pstmMarshal->Unwrap(); + pstgMarshal->Unwrap(); +} + +void t_marshal(void) +{ + WStorage *pstg, *pstgM; + WStream *pstm, *pstmM; + IUnknown *pstgM2, *pstmM2; + ULONG cbRead, cbWritten; + char buf[sizeof(STREAM_DATA)]; + + WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstg); + pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm); + pstm->Write(STREAM_DATA, sizeof(STREAM_DATA), &cbWritten); + CreateStructure(pstg->GetI(), "dChild(dChild(sStream))"); + + do_marshal(pstg, pstm); + do_unmarshal(&pstgM, &pstmM, &pstgM2, &pstmM2); + pstm->Unwrap(); + pstg->Unwrap(); + + pstmM->Seek(0, WSTM_SEEK_SET, NULL); + pstmM->Read(buf, sizeof(STREAM_DATA), &cbRead); + if (strcmp(buf, STREAM_DATA)) + error(EXIT_BADSC, "Stream data mismatch\n"); + pstmM->Unwrap(); + pstmM2->Release(); + + VerifyStructure(pstgM->GetI(), "dChild(dChild(sStream)),sStream"); + pstgM->Unwrap(); + pstgM2->Release(); +} + +void t_stgmisc(void) +{ + WStorage *pstg; + SCODE sc; + STATSTG stat; + + // Can't make this call in transacted mode because we want + // the storage signature to make it into the file right away + WStgCreateDocfile(DRTDF, WSTG_READWRITE | WSTG_CREATE | + WSTG_SHARE_EXCLUSIVE, 0, &pstg); + if (!fOfs) + { + sc = DfGetScode(WStgIsStorageFile(DRTDF)); + if (sc == S_FALSE) + error(EXIT_BADSC, "Open file - Should be a storage object\n"); + pstg->Unwrap(); + sc = DfGetScode(WStgIsStorageFile(DRTDF)); + if (sc == S_FALSE) + error(EXIT_BADSC, "Closed file - Should be a storage object\n"); + } + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstg); + pstg->Stat(&stat, 0); + if (!Exists(stat.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not created\n", stat.pwcsName); + pstg->Unwrap(); + if (Exists(stat.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not deleted on release\n", + stat.pwcsName); + drtMemFree(stat.pwcsName); +} + +void t_ilb(void) +{ + WStorage *pstg; + SCODE sc; + // create an ILockBytes + + ILockBytes *pilb = new CMapBytes(); + if (pilb == NULL) + error(EXIT_BADSC, "Unable to allocate an ILockBytes\n"); + + // create a storage on the ILockBytes + + WStgCreateDocfileOnILockBytes(pilb, + WSTG_READWRITE | + WSTG_CREATE | + WSTG_SHARE_EXCLUSIVE, + 0, &pstg); + + // verify the ILockBytes + + sc = DfGetScode(WStgIsStorageILockBytes(pilb)); + if (sc == S_FALSE) + error(EXIT_BADSC, "Open ILockBytes - Should be a storage object\n"); + + // release the storage + + pstg->Unwrap(); + + // verify the ILockBytes + + sc = DfGetScode(WStgIsStorageILockBytes(pilb)); + + if (sc == S_FALSE) + error(EXIT_BADSC, "Released ILockBytes - Should be a storage object\n"); + + // open the ILockBytes + + WStgOpenStorageOnILockBytes(pilb, NULL, ROOTP(WSTG_READWRITE), + NULL, 0, &pstg); + + + // release the storage + + pstg->Unwrap(); + + // release the ILockBytes + + pilb->Release(); +} + +void t_movecopy(void) +{ + WStorage *pstgFrom, *pstgTo; + STATSTG statFrom, statTo; + + // create a source + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstgFrom); + pstgFrom->Stat(&statFrom, 0); + + // create a destination + WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE | + WSTG_DELETEONRELEASE, 0, &pstgTo); + pstgTo->Stat(&statTo, 0); + + // populate source + CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs"); + + // move a storage + pstgFrom->MoveElementTo(STR("A"), pstgTo, STR("M"), STGMOVE_MOVE); + VerifyStructure(pstgFrom->GetI(), + "sAs"); + VerifyStructure(pstgTo->GetI(), + "dM(dB(dC(sA,sB,sC),sCs),sBs)"); + + // copy a stream + pstgFrom->MoveElementTo(STR("As"), pstgTo, STR("Bs"), STGMOVE_COPY); + VerifyStructure(pstgFrom->GetI(), + "sAs"); + VerifyStructure(pstgTo->GetI(), + "dM(dB(dC(sA,sB,sC),sCs),sBs),sBs"); + + pstgFrom->Unwrap(); + pstgTo->Unwrap(); + if (Exists(statFrom.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName); + drtMemFree(statFrom.pwcsName); + if (Exists(statTo.pwcsName)) + error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName); + drtMemFree(statTo.pwcsName); +} |