884 lines
22 KiB
C++
884 lines
22 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
||
|
//
|
||
|
// File: ofstest.cxx
|
||
|
//
|
||
|
// History: 30-Jun-93 DrewB Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include "pch.cxx"
|
||
|
#pragma hdrstop
|
||
|
#include "notify.hxx"
|
||
|
|
||
|
#if DBG == 1
|
||
|
DECLARE_INFOLEVEL(astg);
|
||
|
#endif
|
||
|
|
||
|
BYTE inbuf[4096];
|
||
|
#define STREAMNAME L"MyStream"
|
||
|
#define STGNAME L"EmbeddedStorage"
|
||
|
#define STGNAME2 L"RenamedStorage"
|
||
|
#define ROOTNAME "RootStorage"
|
||
|
|
||
|
WCHAR pwcsRootName[1024];
|
||
|
|
||
|
#define FailMsg(MSG) {printf MSG; exit(1);}
|
||
|
|
||
|
#define DoCmd(MSG, CODE, FAILMSG) \
|
||
|
printf(MSG " => %s (0x%lX)\n", (sc = ResultFromScode(CODE), ScText(sc)), sc); \
|
||
|
if (FAILED(sc)) {printf(FAILMSG "\n");}
|
||
|
|
||
|
#define SHIFT(c,v) ( (c)--, (v)++)
|
||
|
|
||
|
#include <assert.h>
|
||
|
|
||
|
void BeginTest(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = CoInitialize(NULL);
|
||
|
Result(hr, "CoInitialize");
|
||
|
}
|
||
|
|
||
|
|
||
|
void EndTest(int rc)
|
||
|
{
|
||
|
if (rc == 0)
|
||
|
printf("Test SUCCEEDED\n");
|
||
|
else
|
||
|
printf("Test FAILED\n");
|
||
|
CoUninitialize();
|
||
|
exit(rc);
|
||
|
}
|
||
|
|
||
|
void PrintStat(STATSTG *pstat, BOOL fEnum)
|
||
|
{
|
||
|
printf("%s: '%ws'\n", pstat->type == STGTY_STORAGE ? "Storage" : "Stream",
|
||
|
pstat->pwcsName);
|
||
|
//printf("Type: %lu, %lu\n", pstat->type, pstat->dwStgFmt);
|
||
|
printf("Type: %lu, %lu\n", pstat->type);
|
||
|
if (!fEnum)
|
||
|
printf("Mode: %lX\n", pstat->grfMode);
|
||
|
if (pstat->type == STGTY_STREAM)
|
||
|
{
|
||
|
printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
|
||
|
pstat->cbSize.LowPart);
|
||
|
if (!fEnum)
|
||
|
printf("Locks: %lX\n", pstat->grfLocksSupported);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pstat->ctime.dwHighDateTime != 0 ||
|
||
|
pstat->ctime.dwLowDateTime != 0)
|
||
|
printf("Ctime: %s\n", FileTimeText(&pstat->ctime));
|
||
|
if (pstat->mtime.dwHighDateTime != 0 ||
|
||
|
pstat->mtime.dwLowDateTime != 0)
|
||
|
printf("Mtime: %s\n", FileTimeText(&pstat->mtime));
|
||
|
if (pstat->atime.dwHighDateTime != 0 ||
|
||
|
pstat->atime.dwLowDateTime != 0)
|
||
|
printf("Atime: %s\n", FileTimeText(&pstat->atime));
|
||
|
}
|
||
|
if (!fEnum)
|
||
|
printf("Clsid: %s\n", GuidText(&pstat->clsid));
|
||
|
}
|
||
|
void PrintStatInfo(STATSTG *pstat)
|
||
|
{
|
||
|
PrintStat(pstat, TRUE);
|
||
|
}
|
||
|
|
||
|
void t_filelkb(void)
|
||
|
{
|
||
|
#if DBG == 1
|
||
|
const WCHAR OLEFILELKBNAME[] = L"astgtest.dfl";
|
||
|
const TCHAR FILELKBNAME[] = TEXT("astgtest.dfl");
|
||
|
const int BLOCKSIZE = 4096;
|
||
|
const int NUMBLOCKS = 16;
|
||
|
BYTE buf[BLOCKSIZE];
|
||
|
SCODE sc;
|
||
|
|
||
|
HRESULT hr;
|
||
|
ILockBytes *pilb;
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
if (!DeleteFileA(FILELKBNAME))
|
||
|
#else
|
||
|
if (!DeleteFile(FILELKBNAME))
|
||
|
#endif
|
||
|
DoCmd("Delete docfile", GetLastError(),
|
||
|
"Could not delete docfile.");
|
||
|
|
||
|
|
||
|
|
||
|
hr = StgGetDebugFileLockBytes(OLEFILELKBNAME, &pilb);
|
||
|
Result(hr, "StgGetDebugFileLockBytes");
|
||
|
|
||
|
//Test WriteAt
|
||
|
for (int i = 0; i < NUMBLOCKS; i++)
|
||
|
{
|
||
|
ULONG cbWritten;
|
||
|
ULARGE_INTEGER uli;
|
||
|
uli.QuadPart = (BLOCKSIZE * (NUMBLOCKS - i - 1));
|
||
|
|
||
|
memset(buf, i+'A', BLOCKSIZE);
|
||
|
hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
|
||
|
Result(hr, "ILockBytes::WriteAt");
|
||
|
if (cbWritten != BLOCKSIZE)
|
||
|
{
|
||
|
Fail("Incorrect byte count. Got %lu, expected %lu",
|
||
|
cbWritten,
|
||
|
BLOCKSIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Test ReadAt
|
||
|
for (i = 0; i < NUMBLOCKS; i++)
|
||
|
{
|
||
|
ULONG cbWritten;
|
||
|
ULARGE_INTEGER uli;
|
||
|
uli.QuadPart = BLOCKSIZE * i;
|
||
|
|
||
|
hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbWritten);
|
||
|
Result(hr, "ILockBytes::ReadAt");
|
||
|
if (cbWritten != BLOCKSIZE)
|
||
|
{
|
||
|
Fail("Incorrect byte count. Got %lu, expected %lu",
|
||
|
cbWritten,
|
||
|
BLOCKSIZE);
|
||
|
}
|
||
|
//Check contents
|
||
|
BYTE buf2[BLOCKSIZE];
|
||
|
memset(buf2, (NUMBLOCKS - i - 1)+'A', BLOCKSIZE);
|
||
|
if (memcmp(buf, buf2, BLOCKSIZE))
|
||
|
{
|
||
|
Fail("Buffers compared incorrectly.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Test SetSize
|
||
|
{
|
||
|
const ULONG CHECKSIZE = 180000;
|
||
|
ULARGE_INTEGER uli;
|
||
|
uli.QuadPart = CHECKSIZE;
|
||
|
hr = pilb->SetSize(uli);
|
||
|
Result(hr, "SetSize");
|
||
|
|
||
|
//Verify size
|
||
|
STATSTG statstg;
|
||
|
hr = pilb->Stat(&statstg, STATFLAG_DEFAULT);
|
||
|
PrintStat(&statstg, FALSE);
|
||
|
Result(hr, "Stat");
|
||
|
if (statstg.cbSize.QuadPart != CHECKSIZE)
|
||
|
{
|
||
|
Fail("File size differs");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pilb->Release();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void t_filllkb(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
IFillLockBytes *pflb;
|
||
|
ILockBytes *pilb;
|
||
|
|
||
|
const WCHAR OLEFILLLKBNAME[] = L"fill.dfl";
|
||
|
const TCHAR FILLLKBNAME[] = TEXT("fill.dfl");
|
||
|
const int BLOCKSIZE = 4096;
|
||
|
const int NUMBLOCKS = 16;
|
||
|
BYTE buf[BLOCKSIZE];
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
DeleteFileA(FILLLKBNAME);
|
||
|
#else
|
||
|
DeleteFile(FILLLKBNAME);
|
||
|
#endif
|
||
|
|
||
|
|
||
|
hr = StgGetIFillLockBytesOnFile(OLEFILLLKBNAME, &pflb);
|
||
|
Result(hr, "StgGetIFillLockBytesOnFile");
|
||
|
|
||
|
hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
|
||
|
Result(hr, "QueryInterface for ILockBytes");
|
||
|
|
||
|
void *foo;
|
||
|
pflb->QueryInterface(IID_IFillLockBytes, (void **)&foo);
|
||
|
pflb->QueryInterface(IID_IProgressNotify, (void **)&foo);
|
||
|
|
||
|
{
|
||
|
//Test ReadAt - should fail
|
||
|
ULARGE_INTEGER uli;
|
||
|
ULONG cbWritten;
|
||
|
uli.QuadPart = 0;
|
||
|
|
||
|
hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbWritten);
|
||
|
if (hr != E_PENDING)
|
||
|
{
|
||
|
Fail("Should have returned E_PENDING. Got %lx", hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
//Test WriteAt - should fail
|
||
|
ULARGE_INTEGER uli;
|
||
|
ULONG cbWritten;
|
||
|
uli.QuadPart = 0;
|
||
|
|
||
|
hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
|
||
|
if (hr != E_PENDING)
|
||
|
{
|
||
|
Fail("Should have returned E_PENDING. Got %lx", hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
ULONG cbWritten;
|
||
|
//Fill the first block.
|
||
|
memset(buf, 'A', BLOCKSIZE);
|
||
|
|
||
|
hr = pflb->FillAppend(buf, BLOCKSIZE, &cbWritten);
|
||
|
Result(hr, "FillAppend");
|
||
|
if (cbWritten != BLOCKSIZE)
|
||
|
{
|
||
|
Fail("Incorrect number of bytes written. Got %lu, requested %lu",
|
||
|
cbWritten,
|
||
|
BLOCKSIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
//Test ReadAt - should succeed
|
||
|
ULARGE_INTEGER uli;
|
||
|
ULONG cbRead;
|
||
|
uli.QuadPart = 0;
|
||
|
|
||
|
hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbRead);
|
||
|
Result(hr, "ReadAt");
|
||
|
if (cbRead != BLOCKSIZE)
|
||
|
{
|
||
|
Fail("Incorrect bytes read. Got %lu, requested %lu",
|
||
|
cbRead,
|
||
|
BLOCKSIZE);
|
||
|
}
|
||
|
|
||
|
//Verify contents.
|
||
|
BYTE buf2[BLOCKSIZE];
|
||
|
memset(buf2, 'A', BLOCKSIZE);
|
||
|
if (memcmp(buf, buf2, BLOCKSIZE) != 0)
|
||
|
{
|
||
|
Fail("Buffer compare failed.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
//Test WriteAt
|
||
|
ULARGE_INTEGER uli;
|
||
|
ULONG cbWritten;
|
||
|
uli.QuadPart = 0;
|
||
|
|
||
|
memset(buf, 'B', BLOCKSIZE);
|
||
|
hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
|
||
|
Result(hr, "WriteAt");
|
||
|
|
||
|
if (cbWritten != BLOCKSIZE)
|
||
|
{
|
||
|
Fail("Incorrect number of bytes written. Got %lu, requested %lu",
|
||
|
cbWritten,
|
||
|
BLOCKSIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
//sanity check of IStorage/IStream code on async docfiles
|
||
|
void t_asyncstg(void)
|
||
|
{
|
||
|
IStorage *pdf = NULL;
|
||
|
IStorage *pdf2 = NULL;
|
||
|
IStream *pst = NULL;
|
||
|
IStorage *pstgRoot;
|
||
|
IStream *pstm;
|
||
|
IEnumSTATSTG *penm = NULL;
|
||
|
|
||
|
void *foo;
|
||
|
SCODE sc;
|
||
|
HRESULT hr;
|
||
|
|
||
|
ILockBytes *pilb;
|
||
|
IFillLockBytes *pflb;
|
||
|
CHAR *pszName = ROOTNAME;
|
||
|
const CHAR *test = "Async Docfile test string";
|
||
|
const WCHAR OLEFILLLKBNAME[] = L"async.dfl";
|
||
|
const TCHAR FILLLKBNAME[] = TEXT("async.dfl");
|
||
|
const int BLOCKSIZE = 4096;
|
||
|
const int NUMBLOCKS = 16;
|
||
|
BYTE buf[BLOCKSIZE];
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
DeleteFileA(FILLLKBNAME);
|
||
|
#else
|
||
|
DeleteFile(FILLLKBNAME);
|
||
|
#endif
|
||
|
|
||
|
mbstowcs(pwcsRootName, pszName, 1024);
|
||
|
|
||
|
hr = StgGetIFillLockBytesOnFile(OLEFILLLKBNAME, &pflb);
|
||
|
Result(hr, "StgGetIFillLockBytesOnFile");
|
||
|
|
||
|
hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
|
||
|
Result(hr, "QueryInterface for ILockBytes");
|
||
|
|
||
|
pflb->Terminate(FALSE);
|
||
|
|
||
|
// create a storage on the ILockBytes
|
||
|
hr = StgCreateDocfileOnILockBytes(pilb,
|
||
|
STGM_READWRITE |
|
||
|
STGM_CREATE |
|
||
|
STGM_SHARE_EXCLUSIVE,
|
||
|
0, &pstgRoot);
|
||
|
Result(hr, "StgCreateDocfileOnILockBytes");
|
||
|
|
||
|
hr = pstgRoot->Commit(0);
|
||
|
Result(hr, "Commit");
|
||
|
pstgRoot->Release();
|
||
|
|
||
|
//open the async stg
|
||
|
do
|
||
|
{ sc = StgOpenAsyncDocfileOnIFillLockBytes(
|
||
|
pflb,
|
||
|
STGM_DIRECT| STGM_READWRITE |
|
||
|
STGM_SHARE_EXCLUSIVE,
|
||
|
NULL,
|
||
|
&pdf);
|
||
|
|
||
|
if (sc == E_PENDING)
|
||
|
Sleep(1000);
|
||
|
|
||
|
} while (sc == E_PENDING);
|
||
|
|
||
|
|
||
|
|
||
|
DoCmd("Create root", sc, "Unable to create root");
|
||
|
|
||
|
DoCmd("Create stream",pdf->CreateStream(STREAMNAME,
|
||
|
STGM_READWRITE |
|
||
|
STGM_SHARE_EXCLUSIVE |
|
||
|
STGM_CREATE,
|
||
|
0,
|
||
|
0,
|
||
|
&pst),"Unable to create stream");
|
||
|
|
||
|
ULONG ulBytes;
|
||
|
|
||
|
strcpy((char *)inbuf, test);
|
||
|
|
||
|
DoCmd("Write to stream", pst->Write(inbuf, strlen(test), &ulBytes),
|
||
|
"Unable to write");
|
||
|
|
||
|
if (ulBytes != strlen(test))
|
||
|
FailMsg(("Wrote %lu bytes, expected %lu\n", ulBytes, strlen(test)));
|
||
|
|
||
|
memset(inbuf, 0, strlen(test));
|
||
|
|
||
|
LARGE_INTEGER li;
|
||
|
LISet32(li, 0);
|
||
|
|
||
|
DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL),"Seek failed.");
|
||
|
|
||
|
DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes), "Read failed.");
|
||
|
|
||
|
if (ulBytes != strlen(test))
|
||
|
FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
|
||
|
|
||
|
printf("String read was %s\n",inbuf);
|
||
|
if (strcmp((char *)inbuf, test))
|
||
|
FailMsg(("Strings are not identical\n"));
|
||
|
|
||
|
printf("Release stream = %lu\n",
|
||
|
pst->Release());
|
||
|
pst = NULL;
|
||
|
|
||
|
DoCmd("Open stream", pdf->OpenStream(STREAMNAME,
|
||
|
NULL,
|
||
|
STGM_READWRITE |
|
||
|
STGM_SHARE_EXCLUSIVE,
|
||
|
0,
|
||
|
&pst),
|
||
|
"Could not open stream.");
|
||
|
|
||
|
memset(inbuf, 0, strlen(test));
|
||
|
|
||
|
LISet32(li, 0);
|
||
|
|
||
|
DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL), "Seek failed.");
|
||
|
|
||
|
DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes),
|
||
|
"Read failed.");
|
||
|
|
||
|
if (ulBytes != strlen(test))
|
||
|
FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
|
||
|
|
||
|
printf("String read was %s\n",inbuf);
|
||
|
if (strcmp((char *)inbuf, test))
|
||
|
FailMsg(("Strings are not identical\n"));
|
||
|
|
||
|
printf("Release stream = %lu\n",
|
||
|
pst->Release());
|
||
|
pst = NULL;
|
||
|
|
||
|
DoCmd("Open storage", pdf->CreateStorage(STGNAME,
|
||
|
STGM_READWRITE |
|
||
|
STGM_SHARE_EXCLUSIVE |
|
||
|
STGM_FAILIFTHERE,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&pdf2),
|
||
|
"Unable to create internal storage");
|
||
|
|
||
|
DoCmd("SetClass", pdf2->SetClass(IID_IUnknown), "SetClass failed.");
|
||
|
|
||
|
STATSTG stat;
|
||
|
|
||
|
DoCmd("Embedding Stat()", pdf2->Stat(&stat, STATFLAG_DEFAULT),
|
||
|
"Stat failed.");
|
||
|
PrintStatInfo(&stat);
|
||
|
|
||
|
printf("Release internal storage = %lu\n", pdf2->Release());
|
||
|
pdf2 = NULL;
|
||
|
|
||
|
//Stat IStorage
|
||
|
|
||
|
DoCmd("Root storage Stat()", pdf->Stat(&stat, STATFLAG_DEFAULT),
|
||
|
"Stat failed.");
|
||
|
PrintStatInfo(&stat);
|
||
|
|
||
|
//Enumerate contents of root.
|
||
|
|
||
|
DoCmd("EnumElements()", pdf->EnumElements(0, NULL, 0, &penm),
|
||
|
"EnumElements failed.");
|
||
|
|
||
|
do
|
||
|
{
|
||
|
ULONG ulTemp;
|
||
|
|
||
|
DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
|
||
|
"Next failed.");
|
||
|
|
||
|
if (SUCCEEDED(sc) && (sc != S_FALSE))
|
||
|
{
|
||
|
PrintStatInfo(&stat);
|
||
|
}
|
||
|
} while (sc == S_OK);
|
||
|
printf("\n\n");
|
||
|
|
||
|
//Rename the embedded storage
|
||
|
DoCmd("Rename storage", pdf->RenameElement(STGNAME, STGNAME2),
|
||
|
"Rename failed.");
|
||
|
|
||
|
//Rewind iterator
|
||
|
DoCmd("Reset",penm->Reset(),"Reset failed.");
|
||
|
do
|
||
|
{
|
||
|
ULONG ulTemp;
|
||
|
|
||
|
DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
|
||
|
"Next failed.");
|
||
|
|
||
|
if (SUCCEEDED(sc) && (sc != S_FALSE))
|
||
|
{
|
||
|
PrintStatInfo(&stat);
|
||
|
}
|
||
|
} while (sc == S_OK);
|
||
|
printf("\n\n");
|
||
|
|
||
|
//Delete the embedded storage
|
||
|
DoCmd("Delete storage", pdf->DestroyElement(STGNAME2),
|
||
|
"Could not delete storage.");
|
||
|
|
||
|
//Rewind iterator
|
||
|
DoCmd("Reset",penm->Reset(),"Reset failed.");
|
||
|
do
|
||
|
{
|
||
|
ULONG ulTemp;
|
||
|
|
||
|
DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
|
||
|
"Next failed.");
|
||
|
if (SUCCEEDED(sc) && (sc != S_FALSE))
|
||
|
{
|
||
|
PrintStatInfo(&stat);
|
||
|
}
|
||
|
} while (sc == S_OK);
|
||
|
printf("\n\n");
|
||
|
|
||
|
printf("Release enumerator = %lu\n",
|
||
|
penm->Release());
|
||
|
penm = NULL;
|
||
|
|
||
|
|
||
|
printf("Release root = %lu\n",
|
||
|
pdf->Release());
|
||
|
|
||
|
pdf = NULL;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CDebugFillLockBytes
|
||
|
//
|
||
|
// Purpose: exercise the Notify routine
|
||
|
//
|
||
|
// Interface:
|
||
|
//
|
||
|
// History: 11-Jan-96 Susia Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#define UNTERMINATED 0
|
||
|
#define TERMINATED_NORMAL 1
|
||
|
#define TERMINATED_ABNORMAL 2
|
||
|
ULONG ulWaterMark;
|
||
|
ULONG ulFailurePoint;
|
||
|
|
||
|
|
||
|
CFillLockBytes *p_gflb;
|
||
|
|
||
|
DWORD PulseNotification(void *args)
|
||
|
{
|
||
|
DWORD casenum;
|
||
|
DWORD *caseptr;
|
||
|
caseptr = (DWORD *) args;
|
||
|
casenum = *caseptr;
|
||
|
|
||
|
|
||
|
switch( casenum )
|
||
|
{
|
||
|
case 1:
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->Terminate(FALSE);
|
||
|
break;
|
||
|
case 2:
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->Terminate(TRUE);
|
||
|
break;
|
||
|
case 3:
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
Sleep(100);
|
||
|
p_gflb->SetFailureInfo(10, 10);
|
||
|
p_gflb->PulseFillEvent();
|
||
|
break;
|
||
|
default :
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
ExitThread(0);
|
||
|
return casenum;
|
||
|
|
||
|
}
|
||
|
|
||
|
void t_notify()
|
||
|
{
|
||
|
CAsyncStorage *pstg;
|
||
|
CAsyncStream *pstm;
|
||
|
CAsyncEnum *penum;
|
||
|
CFillLockBytes *pflb;
|
||
|
ILockBytes *plkb = NULL;
|
||
|
|
||
|
DWORD casenum;
|
||
|
DWORD dwFlags;
|
||
|
DWORD thrdid;
|
||
|
DWORD term;
|
||
|
SCODE sc;
|
||
|
HRESULT hr;
|
||
|
HANDLE hthread;
|
||
|
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pstg = new CAsyncStorage(NULL, pflb);
|
||
|
|
||
|
ulFailurePoint = 10;
|
||
|
ulWaterMark = 5;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
|
||
|
// case 1:first try with no connection point.
|
||
|
// Should block until TERMINATED event.
|
||
|
// _dwTerminated should be TERMINATED_NORMAL
|
||
|
// Notify should return S_OK
|
||
|
casenum = 1;
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstg->Notify();
|
||
|
|
||
|
DoCmd("Notify storage case 1 (normal termination)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_NORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify storage case 1 (normal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
|
||
|
// stream notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
pstm = new CAsyncStream(NULL, pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstm->Notify();
|
||
|
|
||
|
DoCmd("Notify stream case 1 (normal termination)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_NORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify stream case 1 (normal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
// enumerator notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
penum = new CAsyncEnum(NULL,pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = penum->Notify();
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 1 (normal termination)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_NORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 1 (normal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
//cleanup
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
delete pstg;
|
||
|
delete pstm;
|
||
|
delete penum;
|
||
|
|
||
|
// case 2: try with no connection point.
|
||
|
// Should block until abnormal termination.
|
||
|
// _dwTerminated should be TERMINATED_ABNORMAL
|
||
|
// Notify should return STG_E_INCOMPLETE
|
||
|
casenum = 2;
|
||
|
|
||
|
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
pstg = new CAsyncStorage(NULL, pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstg->Notify();
|
||
|
if (sc == STG_E_INCOMPLETE)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify storage case 2 (abnormal termination)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_ABNORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify storage case 2 (abnormal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
// stream notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
pstm = new CAsyncStream(NULL, pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstm->Notify();
|
||
|
|
||
|
if (sc == STG_E_INCOMPLETE)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify stream case 2 (abnormal termination)", sc, "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_ABNORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify stream case 2 (abnormal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
// enumerator notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
penum = new CAsyncEnum(NULL,pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = penum->Notify();
|
||
|
|
||
|
if (sc == STG_E_INCOMPLETE)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 2 (abnormal termination)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == TERMINATED_ABNORMAL)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 2 (abnormal termination)", sc, "Notify returned prematurely");
|
||
|
|
||
|
|
||
|
//cleanup:
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
delete pstg;
|
||
|
delete pstm;
|
||
|
delete penum;
|
||
|
|
||
|
// case 3: Should block until file is completely downloaded
|
||
|
// (with watermark >= failurepoint)
|
||
|
// _dwTerminated should be UNTERMINATED
|
||
|
// Notify should return S_OK
|
||
|
casenum = 3;
|
||
|
|
||
|
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
pstg = new CAsyncStorage(NULL, pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstg->Notify();
|
||
|
|
||
|
DoCmd("Notify storage case 3 (watermark reached end)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == UNTERMINATED)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify storage case 3 (watermark reached end)", sc, "Notify returned prematurely");
|
||
|
|
||
|
// stream notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
pstm = new CAsyncStream(NULL, pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = pstm->Notify();
|
||
|
|
||
|
DoCmd("Notify stream case 3 (watermark reached end)", sc, "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == UNTERMINATED)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify stream case 3 (watermark reached end)", sc, "Notify returned prematurely");
|
||
|
|
||
|
// enumerator notify
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
pflb = new CFillLockBytes(plkb);
|
||
|
pflb->Init();
|
||
|
p_gflb = pflb;
|
||
|
pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
|
||
|
penum = new CAsyncEnum(NULL,pflb);
|
||
|
|
||
|
hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
|
||
|
(void *) &casenum,
|
||
|
0, &thrdid);
|
||
|
sc = penum->Notify();
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 3 (watermark reached end)", sc , "Notify Failed");
|
||
|
pflb->GetTerminationStatus(&dwFlags);
|
||
|
if (dwFlags == UNTERMINATED)
|
||
|
sc = S_OK;
|
||
|
else sc = STG_E_TERMINATED;
|
||
|
|
||
|
DoCmd("Notify enumSTATSTG case 3 (watermark reached end)", sc, "Notify returned prematurely");
|
||
|
|
||
|
|
||
|
//cleanup:
|
||
|
TerminateThread(hthread,0);
|
||
|
delete pflb;
|
||
|
delete pstg;
|
||
|
delete pstm;
|
||
|
delete penum;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void _CRTAPI1 main(int argc, char **argv)
|
||
|
{
|
||
|
SCODE sc;
|
||
|
BeginTest();
|
||
|
t_filelkb();
|
||
|
t_filllkb();
|
||
|
t_asyncstg();
|
||
|
t_notify();
|
||
|
|
||
|
|
||
|
EndTest(0);
|
||
|
exit(0);
|
||
|
|
||
|
}
|
||
|
|