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.
5635 lines
167 KiB
5635 lines
167 KiB
// tmarsh.cxx : various tests related to marshalling...
|
|
//
|
|
#include <windows.h>
|
|
#include <ole2.h>
|
|
#include <stdio.h>
|
|
|
|
#include "tmarshal.h"
|
|
#include "tunk.h"
|
|
#include <iballs.h>
|
|
#include <icube.h>
|
|
#include <iloop.h>
|
|
#include <stream.hxx> // CStreamOnFile
|
|
#include <tstmain.hxx> // fQuiet
|
|
|
|
// BUGBUG: these should be in a public place somewhere.
|
|
DEFINE_OLEGUID(CLSID_Balls, 0x0000013a, 1, 8);
|
|
DEFINE_OLEGUID(CLSID_Cubes, 0x0000013b, 1, 8);
|
|
DEFINE_OLEGUID(CLSID_LoopSrv, 0x0000013c, 1, 8);
|
|
DEFINE_OLEGUID(CLSID_QI, 0x00000140, 0, 8);
|
|
DEFINE_OLEGUID(CLSID_QIHANDLER1, 0x00000141, 0, 8);
|
|
|
|
DEFINE_OLEGUID(IID_IInternalUnknown,0x00000021, 0, 0);
|
|
DEFINE_OLEGUID(IID_IStdIdentity, 0x0000001b, 0, 0);
|
|
DEFINE_OLEGUID(CLSID_OLEPSFACTORY, 0x00000320, 0, 0);
|
|
|
|
const GUID CLSID_LoopSrv =
|
|
{0x0000013c,0x0001,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
// testsrv.exe
|
|
const GUID CLSID_TestEmbed =
|
|
{0x99999999,0x0000,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x47}};
|
|
|
|
const GUID CLSID_Async =
|
|
{0x00000401,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID CLSID_QI =
|
|
{0x00000140,0x0000,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID CLSID_QIHANDLER1 =
|
|
{0x00000141,0x0000,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
//const GUID IID_IMultiQI =
|
|
// {0x00000020,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID IID_IInternalUnknown =
|
|
{0x00000021,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID IID_IStdIdentity =
|
|
{0x0000001b,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
const GUID CLSID_OLEPSFACTORY =
|
|
{0x00000320,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
extern "C" const GUID CLSID_TestEmbed;
|
|
|
|
|
|
// external functions
|
|
STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phdl);
|
|
HRESULT VerifyOBJREFFormat(IStream *pStm, DWORD mshlflags);
|
|
DWORD _stdcall RundownClient(void *param);
|
|
|
|
// APIs exported by OLE32 but not in the header files.
|
|
STDAPI CoGetIIDFromMarshaledInterface(IStream *pStm, IID *piid);
|
|
|
|
|
|
// function prototypes - TRUE return means the test passed
|
|
BOOL TestMarshalFormat(void);
|
|
BOOL TestGetIIDFromMI(void);
|
|
BOOL TestLocalInterfaceNormal(void);
|
|
BOOL TestUnmarshalGUIDNULL(void);
|
|
BOOL TestUnmarshalDifferentIID(void);
|
|
BOOL TestUniqueQIPointer(void);
|
|
BOOL TestLocalInterfaceTableStrong(void);
|
|
BOOL TestLocalInterfaceTableWeak(void);
|
|
BOOL TestRemoteInterfaceNormal(void);
|
|
BOOL TestRemoteInterfaceTableStrong(void);
|
|
BOOL TestNoPing(void);
|
|
BOOL TestEcho(void);
|
|
BOOL TestMiddleMan(void);
|
|
BOOL TestLoop(void);
|
|
BOOL TestLockObjectExternal(void);
|
|
BOOL TestDisconnectObject(void);
|
|
BOOL TestHandler(void);
|
|
BOOL TestReleaseMarshalData(void);
|
|
BOOL TestCustomMarshalNormal(void);
|
|
BOOL TestCustomMarshalTable(void);
|
|
BOOL TestGetStandardMarshal(void);
|
|
BOOL TestLocalInterfaceDiffMachine(void);
|
|
BOOL TestRemoteInterfaceDiffMachine(void);
|
|
BOOL TestExpiredOXIDs(void);
|
|
BOOL TestNonNDRProxy(void);
|
|
BOOL TestTIDAndLID(void);
|
|
BOOL TestMarshalSizeMax(void);
|
|
BOOL TestMarshalStorage(void);
|
|
BOOL TestMultiQINormal(void);
|
|
BOOL TestMultiQIHandler(void);
|
|
BOOL TestCrossThread(void);
|
|
BOOL TestPSClsid(void);
|
|
BOOL TestPSClsid2(void);
|
|
|
|
BOOL TestAsync(void);
|
|
BOOL TestRundown(void);
|
|
BOOL TestAggregate(void);
|
|
BOOL TestCreateRemoteHandler(void);
|
|
BOOL TestStorageInterfaceDiffMachine(void);
|
|
|
|
|
|
WCHAR *pwszFileName[] = {L"c:\\mshlfile.1",
|
|
L"c:\\mshlfile.2",
|
|
L"c:\\mshlfile.3"};
|
|
|
|
|
|
|
|
|
|
// internal subroutines
|
|
void VerifyRHRefCnt(IUnknown *punk, ULONG ulExpectedRefCnt);
|
|
void VerifyObjRefCnt(IUnknown *punk, ULONG ulExpectedRefCnt);
|
|
|
|
TCHAR g_szIniFile[MAX_PATH];
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMarshal - main test driver
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL GetProfileValue(TCHAR *pszKeyName, int nDefault)
|
|
{
|
|
return (GetPrivateProfileInt(TEXT("Marshal Test"),
|
|
pszKeyName,
|
|
nDefault,
|
|
g_szIniFile));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMarshal - main test driver
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestMarshal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
// Get file name of .ini file, TMARSHAL.INI in the current directory
|
|
GetCurrentDirectory (MAX_PATH, g_szIniFile);
|
|
lstrcat(g_szIniFile, TEXT("\\TMARSHAL.INI"));
|
|
|
|
|
|
if (GetProfileValue(TEXT("Format"),1))
|
|
RetVal &= TestMarshalFormat();
|
|
|
|
if (GetProfileValue(TEXT("GetIIDFromMI"),1))
|
|
RetVal &= TestGetIIDFromMI();
|
|
|
|
if (GetProfileValue(TEXT("MarshalSizeMax"),1))
|
|
RetVal &= TestMarshalSizeMax();
|
|
|
|
if (GetProfileValue(TEXT("GetStandardMarshal"),1))
|
|
RetVal &= TestGetStandardMarshal();
|
|
|
|
if (GetProfileValue(TEXT("LocalInterfaceNormal"),1))
|
|
RetVal &= TestLocalInterfaceNormal();
|
|
|
|
if (GetProfileValue(TEXT("UniqueQIPointer"),1))
|
|
RetVal &= TestUniqueQIPointer();
|
|
|
|
if (GetProfileValue(TEXT("LocalInterfaceTableStrong"),1))
|
|
RetVal &= TestLocalInterfaceTableStrong();
|
|
|
|
if (GetProfileValue(TEXT("LocalInterfaceTableWeak"),1))
|
|
RetVal &= TestLocalInterfaceTableWeak();
|
|
|
|
if (GetProfileValue(TEXT("RemoteInterfaceNormal"),1))
|
|
RetVal &= TestRemoteInterfaceNormal();
|
|
|
|
if (GetProfileValue(TEXT("UnmarshalGUIDNULL"),1))
|
|
RetVal &= TestUnmarshalGUIDNULL();
|
|
|
|
if (GetProfileValue(TEXT("UnmarshalDifferentIID"),1))
|
|
RetVal &= TestUnmarshalDifferentIID();
|
|
|
|
if (GetProfileValue(TEXT("RemoteInterfaceTableStrong"),1))
|
|
RetVal &= TestRemoteInterfaceTableStrong();
|
|
|
|
if (GetProfileValue(TEXT("CrossThread"),1))
|
|
RetVal &= TestCrossThread();
|
|
|
|
if (GetProfileValue(TEXT("CustomMarshalNormal"),1))
|
|
RetVal &= TestCustomMarshalNormal();
|
|
|
|
if (GetProfileValue(TEXT("CustomMarshalTable"),1))
|
|
RetVal &= TestCustomMarshalTable();
|
|
|
|
if (GetProfileValue(TEXT("Echo"),1))
|
|
RetVal &= TestEcho();
|
|
|
|
if (GetProfileValue(TEXT("Loop"),1))
|
|
RetVal &= TestLoop();
|
|
|
|
if (GetProfileValue(TEXT("LockObjectExternal"),1))
|
|
RetVal &= TestLockObjectExternal();
|
|
|
|
if (GetProfileValue(TEXT("DisconnectObject"),1))
|
|
RetVal &= TestDisconnectObject();
|
|
|
|
if (GetProfileValue(TEXT("ReleaseMarshalData"),1))
|
|
RetVal &= TestReleaseMarshalData();
|
|
|
|
if (GetProfileValue(TEXT("MultiQINormal"),1))
|
|
RetVal &= TestMultiQINormal();
|
|
|
|
if (GetProfileValue(TEXT("MultiQIHandler"),1))
|
|
RetVal &= TestMultiQIHandler();
|
|
|
|
if (GetProfileValue(TEXT("Handler"),1))
|
|
RetVal &= TestHandler();
|
|
|
|
if (GetProfileValue(TEXT("MiddleMan"),1))
|
|
RetVal &= TestMiddleMan();
|
|
|
|
if (GetProfileValue(TEXT("MarshalStorage"),1))
|
|
RetVal &= TestMarshalStorage();
|
|
|
|
if (GetProfileValue(TEXT("LocalDiffMachine"),1))
|
|
RetVal &= TestLocalInterfaceDiffMachine();
|
|
|
|
if (GetProfileValue(TEXT("RemoteDiffMachine"),1))
|
|
RetVal &= TestRemoteInterfaceDiffMachine();
|
|
|
|
if (GetProfileValue(TEXT("ExpiredOXIDs"),1))
|
|
RetVal &= TestExpiredOXIDs();
|
|
|
|
if (GetProfileValue(TEXT("NonNDRProxy"),1))
|
|
RetVal &= TestNonNDRProxy();
|
|
|
|
if (GetProfileValue(TEXT("TIDAndLID"),1))
|
|
RetVal &= TestTIDAndLID();
|
|
|
|
if (GetProfileValue(TEXT("NoPing"),1))
|
|
RetVal &= TestNoPing();
|
|
|
|
if (GetProfileValue(TEXT("PSClsid"),1))
|
|
RetVal &= TestPSClsid();
|
|
|
|
if (GetProfileValue(TEXT("PSClsid2"),1))
|
|
RetVal &= TestPSClsid2();
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
if (GetProfileValue(TEXT("Rundown"),0))
|
|
RetVal &= TestRundown();
|
|
|
|
if (GetProfileValue(TEXT("Async"),0))
|
|
RetVal &= TestAsync();
|
|
|
|
if (GetProfileValue(TEXT("StorageDiffMachine"),0))
|
|
RetVal &= TestStorageInterfaceDiffMachine();
|
|
|
|
if (GetProfileValue(TEXT("Aggregate"),0))
|
|
RetVal &= TestAggregate();
|
|
|
|
if (GetProfileValue(TEXT("CreateRemoteHandler"),0))
|
|
RetVal &= TestCreateRemoteHandler();
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// subroutine to verify that the RH RefCnt is as expected.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
typedef IMarshal * (* PFNDBG_FINDRH)(IUnknown *punk);
|
|
PFNDBG_FINDRH gpfnFindRH = NULL;
|
|
|
|
HMODULE ghOle32Dll = NULL;
|
|
BOOL gfTriedToLoad = FALSE;
|
|
|
|
|
|
void LoadProc()
|
|
{
|
|
if (!gfTriedToLoad)
|
|
{
|
|
gfTriedToLoad = TRUE;
|
|
|
|
ghOle32Dll = LoadLibrary(TEXT("OLE32.DLL"));
|
|
if (ghOle32Dll)
|
|
{
|
|
gpfnFindRH = (PFNDBG_FINDRH) GetProcAddress(ghOle32Dll,
|
|
"Dbg_FindRemoteHdlr");
|
|
}
|
|
}
|
|
}
|
|
|
|
void FreeProc()
|
|
{
|
|
if (ghOle32Dll)
|
|
{
|
|
FreeLibrary(ghOle32Dll);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// subroutine to verify that the RH RefCnt is as expected.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
void VerifyRHRefCnt(IUnknown *punk, ULONG ulExpectedRefCnt)
|
|
{
|
|
if (gpfnFindRH == NULL)
|
|
{
|
|
LoadProc();
|
|
}
|
|
|
|
if (gpfnFindRH)
|
|
{
|
|
// this function is internal to COMPOBJ marshalling.
|
|
IMarshal *pIM = (gpfnFindRH)(punk);
|
|
if (pIM == NULL)
|
|
{
|
|
if (ulExpectedRefCnt != 0)
|
|
printf ("ERROR: RH RefCnt 0, expected=%x\n", ulExpectedRefCnt);
|
|
return;
|
|
}
|
|
|
|
ULONG ulRefCnt = pIM->Release();
|
|
if (ulRefCnt != ulExpectedRefCnt)
|
|
{
|
|
printf ("ERROR: RH RefCnt=%x, expected=%x\n", ulRefCnt, ulExpectedRefCnt);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// subroutine to verify that the Object RefCnt is as expected.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
void VerifyObjRefCnt(IUnknown *punk, ULONG ulExpectedRefCnt)
|
|
{
|
|
if (ulExpectedRefCnt == 0)
|
|
return; // cant verify this
|
|
|
|
//#if DBG==1
|
|
// this function is internal to COMPOBJ marshalling.
|
|
punk->AddRef();
|
|
ULONG ulRefCnt = punk->Release();
|
|
if (ulRefCnt != ulExpectedRefCnt)
|
|
{
|
|
printf ("ERROR: Object RefCnt=%x, expected=%x\n", ulRefCnt, ulExpectedRefCnt);
|
|
}
|
|
//#endif
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// MarshalAndRead
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
HRESULT MarshalAndRead(IUnknown *punkIn, BYTE *pbuf, ULONG *pulSize)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
|
|
ULARGE_INTEGER ulSeekEnd;
|
|
LARGE_INTEGER lSeekStart;
|
|
LISet32(lSeekStart, 0);
|
|
|
|
IStream *pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
// get current seek position
|
|
hres = pStm->Seek(lSeekStart, STREAM_SEEK_CUR, &ulSeekEnd);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
OUTPUT (" - Seek Current OK\n");
|
|
|
|
// go back to begining
|
|
hres = pStm->Seek(lSeekStart, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
OUTPUT (" - Seek Start OK\n");
|
|
|
|
// read in the data
|
|
hres = pStm->Read(pbuf ,ulSeekEnd.LowPart, pulSize);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Read on stream failed\n")
|
|
OUTPUT (" - Read OK\n");
|
|
|
|
Cleanup:
|
|
|
|
// release the stream
|
|
pStm->Release();
|
|
|
|
if (RetVal == TRUE)
|
|
return S_OK;
|
|
else
|
|
return hres;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// GetTestUnk - return an inproc IUnknown ptr.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
IUnknown *GetTestUnk()
|
|
{
|
|
IUnknown *punkIn = (IUnknown *)(IParseDisplayName *) new CTestUnk();
|
|
return punkIn;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// RunThread - runs a thread and waits for it to complete
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
void RunThread(void *param, HANDLE hEvent, LPTHREAD_START_ROUTINE pfn)
|
|
{
|
|
DWORD dwThrdId;
|
|
HANDLE hThrd = CreateThread(NULL, 0, pfn, param, 0, &dwThrdId);
|
|
|
|
if (hThrd)
|
|
{
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
// enter a message pump to accept incoming calls from the
|
|
// other thread.
|
|
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// wait for the other thread to run to completion
|
|
WaitForSingleObject(hEvent, 0xffffffff);
|
|
}
|
|
|
|
// close the thread handle
|
|
CloseHandle(hThrd);
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestAsync
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestAsync(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *pUnkSrv = NULL;
|
|
IAdviseSink *pAdvSnk = NULL;
|
|
|
|
OUTPUT ("Starting TestAsync\n");
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_Async, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnkSrv);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
|
|
OUTPUT (" - QI for IAdviseSink\n");
|
|
hRes = pUnkSrv->QueryInterface(IID_IAdviseSink, (void **)&pAdvSnk);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QI for IAdviseSink failed\n")
|
|
|
|
// now call on the IAdviseSink Interface
|
|
pAdvSnk->OnSave();
|
|
|
|
Sleep(30);
|
|
|
|
// release the interface
|
|
pAdvSnk->Release();
|
|
pAdvSnk = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pAdvSnk)
|
|
{
|
|
ulRefCnt = pAdvSnk->Release();
|
|
TEST_FAILED(ulRefCnt != 1, "pAdvSnk RefCnt not zero\n");
|
|
}
|
|
|
|
if (pUnkSrv)
|
|
{
|
|
ulRefCnt = pUnkSrv->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "PunkSrv RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestAsync");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test marshal format
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestMarshalFormat(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
BOOL fSame = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
BYTE buf1[600];
|
|
BYTE buf2[600];
|
|
ULONG ulSize1 = sizeof(buf1);
|
|
ULONG ulSize2 = sizeof(buf2);
|
|
|
|
OUTPUT ("Starting TestMarshalFormat\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
hres = MarshalAndRead(punkIn, buf1, &ulSize1);
|
|
TEST_FAILED_EXIT(FAILED(hres), "MarshalAndRead failed\n")
|
|
OUTPUT (" - First MarshalAndRead OK\n");
|
|
|
|
hres = MarshalAndRead(punkIn, buf2, &ulSize2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "MarshalAndRead failed\n")
|
|
OUTPUT (" - Second MarshalAndRead OK\n");
|
|
|
|
TEST_FAILED_EXIT((ulSize1 != ulSize2), "Buffer Sizes Differ\n")
|
|
fSame = !memcmp(buf1, buf2, ulSize1);
|
|
|
|
TEST_FAILED_EXIT(!fSame, "Buffer Contents Differ\n")
|
|
OUTPUT (" - Buffers Compare OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
CoDisconnectObject(punkIn,0);
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestMarshalFormat");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test CoGetMarshalSizeMax
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestMarshalSizeMax(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
ULONG ulSize = 0;
|
|
|
|
OUTPUT ("Starting TestMarshalSizeMax\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
hres = CoGetMarshalSizeMax(&ulSize, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetMarshalSizeMax failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - CoGetMarshalSizeMax OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
if (punkIn)
|
|
{
|
|
punkIn->Release();
|
|
punkIn = NULL;
|
|
}
|
|
|
|
return TestResult(RetVal, "TestMarshalSizeMax");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_NORMAL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLocalInterfaceNormal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkOut2 = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestLocalInterfaceNormal\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// since we are unmarshalling in the same process, the RH should go away.
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero");
|
|
punkOut = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// the RH should have gone away, and we should have only the original
|
|
// refcnt from creation left on the object.
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
#if 0
|
|
// this test disabled for DCOM since we no longer write into the stream
|
|
// to mark the thing as having been unmarshaled. This lets unmarshals
|
|
// work with read-only streams.
|
|
|
|
|
|
// test unmarshalling twice. this should fail since we did marshal
|
|
// flags normal and already unmarshalled it once.
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut2);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoUnmarshalInterface second time succeeded but should have failed\n")
|
|
OUTPUT (" - Second CoUnmarshalInterface OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// CoReleaseMarshalData should fail because Unmarshall already called it.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoReleaseMarshalData succeeded but should have failed.\n")
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
#endif
|
|
// ----------------------------------------------------------------------
|
|
|
|
// marshal again and try CoRelease without having first done an
|
|
// unmarshal. this should work.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release the object and try to unmarshal it again. Should fail
|
|
// since the object has gone away.
|
|
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
punkIn = NULL;
|
|
|
|
// go back to start of stream
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoUnmarshalInterface should have failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut2)
|
|
{
|
|
ulRefCnt = punkOut2->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut2 RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestLocalInterfaceNormal");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_NORMAL when the object returns a
|
|
// differnt interface pointer on each subsequent QI for the same
|
|
// interface
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestUniqueQIPointer(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
ICube *pCubeIn = NULL;
|
|
ICube *pCubeOut = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestUniqueQIPointer\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
hres = punkIn->QueryInterface(IID_ICube, (void **)&pCubeIn);
|
|
TEST_FAILED_EXIT((pCubeIn == NULL), "QI for IID_ICube failed\n")
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = CoMarshalInterface(pStm, IID_ICube, pCubeIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(pCubeIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// since we are unmarshalling in the same process, the RH should go away.
|
|
hres = CoUnmarshalInterface(pStm, IID_ICube, (LPVOID FAR*)&pCubeOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(pCubeIn, 0);
|
|
VerifyRHRefCnt(pCubeOut, 0);
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
|
|
VerifyObjRefCnt(pCubeIn, 1);
|
|
VerifyObjRefCnt(pCubeOut, 1);
|
|
VerifyObjRefCnt(punkIn, 3);
|
|
|
|
// make sure the Ctrl Unknown interface pointers are identical
|
|
hres = pCubeOut->QueryInterface(IID_IUnknown, (void **)&punkOut);
|
|
TEST_FAILED_EXIT((punkOut == NULL), "QI for IID_IUnknown failed\n")
|
|
VerifyObjRefCnt(punkOut, 4);
|
|
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK\n");
|
|
|
|
// attempt a call on the in interface pointer.
|
|
hres = pCubeIn->MoveCube(0,0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "pCubeIn->MoveCube failed\n")
|
|
|
|
// release the in-pointer
|
|
ulRefCnt = pCubeIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCubeIn RefCnt not zero\n");
|
|
pCubeIn = NULL;
|
|
|
|
// now call on the out interface pointer
|
|
hres = pCubeOut->MoveCube(0,0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "pCubeOut->MoveCube failed\n")
|
|
|
|
// release the out-pointer
|
|
ulRefCnt = pCubeOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCubeOut RefCnt not zero\n");
|
|
pCubeOut = NULL;
|
|
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (pCubeIn)
|
|
{
|
|
ulRefCnt = pCubeIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCubeIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pCubeOut)
|
|
{
|
|
ulRefCnt = pCubeOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCubeOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt == 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestUniqueQIPointer");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_TABLESTRONG
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLocalInterfaceTableStrong(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkOut2 = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestLocalInterfaceTableStrong\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_TABLESTRONG);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// unmarshalling should leave the RH intact, as it is marshalled for TABLE.
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero");
|
|
punkOut = NULL;
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// test unmarshalling twice - should work since we used flags table
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface second time succeeded but should have failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Second CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut2->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut2 RefCnt is zero");
|
|
punkOut2 = NULL;
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// CoReleaseMarshalData should release the marshalled data TABLESTRONG
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut2)
|
|
{
|
|
ulRefCnt = punkOut2->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut2 RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestLocalInterfaceTableStrong");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_TABLEWEAK
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLocalInterfaceTableWeak(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkOut2 = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestLocalInterfaceTableWeak\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IParseDisplayName, punkIn, 0, NULL, MSHLFLAGS_TABLEWEAK);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// unmarshalling should leave the RH intact, as it is marshalled for TABLE.
|
|
hres = CoUnmarshalInterface(pStm, IID_IParseDisplayName, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero");
|
|
punkOut = NULL;
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// test unmarshalling twice - should work since we used flags table
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IParseDisplayName, (LPVOID FAR*)&punkOut2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface second time succeeded but should have failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut2)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...2nd Local Unmarshal\n")
|
|
OUTPUT (" - Second CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut2->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut2 RefCnt is zero");
|
|
punkOut2 = NULL;
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// CoReleaseMarshalData should release the marshalled data TABLEWEAK
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkIn RefCnt is not zero");
|
|
punkIn = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut2)
|
|
{
|
|
ulRefCnt = punkOut2->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut2 RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestLocalInterfaceTableWeak");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test calling CoUmarshalInterface with GUID_NULL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Structure passed between apartments.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
typedef struct tagThreadUnmarshalInfo
|
|
{
|
|
HANDLE hEvent;
|
|
IStream *pStm;
|
|
IUnknown *pUnk;
|
|
IID iid;
|
|
DWORD dwInitFlag;
|
|
DWORD dwThreadId;
|
|
ULONG RelRefCnt;
|
|
HRESULT hr;
|
|
} ThreadUnmarshalInfo;
|
|
|
|
|
|
DWORD _stdcall ThreadTestUnmarshal(void *params)
|
|
{
|
|
ThreadUnmarshalInfo *pInfo = (ThreadUnmarshalInfo *)params;
|
|
BOOL RetVal = TRUE;
|
|
ULONG ulRefCnt= 0;
|
|
IUnknown *punkOut = NULL;
|
|
HRESULT hres;
|
|
|
|
hres = CoInitializeEx(NULL, pInfo->dwInitFlag);
|
|
|
|
hres = CoUnmarshalInterface(pInfo->pStm, pInfo->iid, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
// make sure the interface pointers are identical
|
|
if (pInfo->pUnk != NULL && pInfo->pUnk != punkOut)
|
|
{
|
|
TEST_FAILED(TRUE, "Interface ptrs are wrong\n")
|
|
}
|
|
else
|
|
{
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
}
|
|
|
|
// release the interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED(ulRefCnt != pInfo->RelRefCnt, "Released punkOut RefCnt is wrong\n");
|
|
|
|
OUTPUT (" - Release OK\n");
|
|
}
|
|
|
|
pInfo->hr = hres;
|
|
|
|
CoUninitialize();
|
|
|
|
// signal the other thread we are done.
|
|
// but only if we were called from a different thread
|
|
|
|
if (pInfo->dwThreadId != 0)
|
|
{
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
PostThreadMessage(pInfo->dwThreadId, WM_QUIT, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetEvent(pInfo->hEvent);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL TestUnmarshalGUIDNULL(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
ULONG ulRefCnt, i;
|
|
HANDLE hEvent = NULL;
|
|
ThreadUnmarshalInfo Info;
|
|
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestUnmarshalGUIDNULL\n");
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
TEST_FAILED_EXIT(hEvent == NULL, "CreateEvent failed\n")
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// reset the stream ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IParseDisplayName, punkIn,
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
|
|
// reset the stream ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
Info.hEvent = hEvent;
|
|
Info.pStm = pStm;
|
|
Info.iid = GUID_NULL;
|
|
Info.dwInitFlag = gInitFlag;
|
|
Info.dwThreadId = 0;
|
|
|
|
if (i==0)
|
|
{
|
|
// first time, call on same thread, expect original ptr and
|
|
// non-zero refcnt after release
|
|
Info.pUnk = punkIn;
|
|
Info.RelRefCnt = 1;
|
|
|
|
ThreadTestUnmarshal(&Info);
|
|
}
|
|
else
|
|
{
|
|
// second time, call on different thread
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
// apartment thread, expect differnt ptr and
|
|
// zero refcnt after release
|
|
|
|
Info.dwThreadId = GetCurrentThreadId();
|
|
Info.pUnk = 0;
|
|
Info.RelRefCnt = 0;
|
|
}
|
|
else
|
|
{
|
|
// multi-thread, expect same ptr and non-zero refcnt
|
|
// after release
|
|
|
|
Info.dwThreadId = GetCurrentThreadId();
|
|
Info.pUnk = punkIn;
|
|
Info.RelRefCnt = 1;
|
|
}
|
|
|
|
RunThread(&Info, hEvent, ThreadTestUnmarshal);
|
|
CloseHandle(hEvent);
|
|
}
|
|
|
|
// release the punkIn.
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
punkIn = NULL;
|
|
|
|
hres = Info.hr;
|
|
OUTPUT (" - Run Complete\n");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestUnmarshalGUIDNULL");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test calling CoUmarshalInterface with an IID different from
|
|
// the IID that was marshaled.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestUnmarshalDifferentIID(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
ULONG ulRefCnt, i;
|
|
HANDLE hEvent = NULL;
|
|
ThreadUnmarshalInfo Info;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestUnmarshalDifferentIID\n");
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
TEST_FAILED_EXIT(hEvent == NULL, "CreateEvent failed\n")
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// reset the stream ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IParseDisplayName, punkIn,
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
|
|
// reset the stream ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
Info.hEvent = hEvent;
|
|
Info.pStm = pStm;
|
|
Info.iid = IID_IOleWindow;
|
|
Info.pUnk = punkIn;
|
|
Info.dwInitFlag = gInitFlag;
|
|
Info.dwThreadId = 0;
|
|
|
|
if (i==0)
|
|
{
|
|
// first time, call on same thread, expect different ptr and
|
|
// non-zero refcnt after release
|
|
Info.pUnk = 0;
|
|
Info.RelRefCnt = 1;
|
|
|
|
ThreadTestUnmarshal(&Info);
|
|
}
|
|
else
|
|
{
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
// apartment thread, expect differnt ptr and
|
|
// zero refcnt after release
|
|
|
|
Info.dwThreadId = GetCurrentThreadId();
|
|
Info.pUnk = 0;
|
|
Info.RelRefCnt = 0;
|
|
}
|
|
else
|
|
{
|
|
// multi-thread, expect same ptr and non-zero refcnt
|
|
// after release
|
|
|
|
Info.dwThreadId = GetCurrentThreadId();
|
|
Info.pUnk = 0;
|
|
Info.RelRefCnt = 1;
|
|
}
|
|
|
|
RunThread(&Info, hEvent, ThreadTestUnmarshal);
|
|
CloseHandle(hEvent);
|
|
}
|
|
|
|
// release the punkIn.
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
punkIn = NULL;
|
|
|
|
hres = Info.hr;
|
|
OUTPUT (" - Run Complete\n");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestUnmarshalDifferentIID");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test REMOTE interface MSHLFLAGS_NORMAL
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestRemoteInterfaceNormal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestRemoteInterfaceNormal\n");
|
|
|
|
// Create an IClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject failed\n")
|
|
VerifyRHRefCnt((IUnknown *)pICF, 1);
|
|
OUTPUT (" - Aquired Remote Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IUnknown, (void **)&punkIn);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((punkIn == NULL), "CreateInstance failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Created Instance.\n");
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
// VerifyRHRefCnt((IUnknown *)pICF, 0);
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// unmarshal the interface. should get the same proxy back.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 2);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..1st Remote Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
|
|
|
|
// release the interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
#if 0
|
|
// test unmarshalling twice. this should fail since we marshalled normal
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoUnmarshalInterface succeeded but should have failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Second CoUnmarshalInterface OK.\n");
|
|
punkOut = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// CoReleaseMarshalData should FAIL since we already unmarshalled it
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoReleaseMarshalData succeeded but should have failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
#endif
|
|
// ----------------------------------------------------------------------
|
|
|
|
// marshal again and try CoRelease without having first done an
|
|
// unmarshal. this should work.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (pICF)
|
|
{
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestRemoteInterfaceNormal");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test REMOTE interface MSHLFLAGS_TABLESTRONG
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestRemoteInterfaceTableStrong(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestRemoteInterfaceTableStrong\n");
|
|
|
|
// Create an IClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject failed\n")
|
|
OUTPUT (" - Aquired Remote Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IUnknown, (void **)&punkIn);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((punkIn == NULL), "CreateInstance failed\n")
|
|
OUTPUT (" - Created Instance.\n");
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create a shared memory stream for the marshaled moniker
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_TABLESTRONG);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hres), "CoMarshalInterface succeeded but should have failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
#if 0
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..1st Remote Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
|
|
// release it
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
punkOut = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// test unmarshalling twice.
|
|
// this should work since we did marshal flags TABLE_STRONG
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
OUTPUT (" - Second CoUnmarshalInterface OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// CoReleaseMarshalData should WORK for TABLESTRONG interfaces
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
#endif
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
// release instance
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0,"punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestRemoteInterfaceTableStrong");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test CUSTOM interface MSHLFLAGS_NORMAL --- CODEWORK
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestCustomMarshalNormal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
return TestResult(RetVal, "TestCustomMarshalNormal");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test CUSTOM interface MSHLFLAGS_TABLESTRONG --- CODEWORK
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestCustomMarshalTable(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
return TestResult(RetVal, "TestCustomMarshalTableStrong");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestEcho
|
|
//
|
|
// test sending an interface to a remote server and getting the same
|
|
// interface back again. the test is done with once with a local
|
|
// interface and once with a remote interface.
|
|
//
|
|
// Local Interface Remote Interface
|
|
//
|
|
// 1. marshal [in] local marshal [in] remote proxy
|
|
// 2. unmarshal [in] remote unmarshal [in] local proxy
|
|
// 3. marshal [out] remote proxy marshal [out] local
|
|
// 4. unmarshal [in] local proxy unmarshal [out] remote
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestEcho(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
IBalls *pIBalls = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkIn2 = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestEcho\n");
|
|
|
|
// Create an IBall ClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject failed\n")
|
|
OUTPUT (" - Aquired Remote Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IBalls, (void **)&pIBalls);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((pIBalls == NULL), "CreateInstance failed\n")
|
|
OUTPUT (" - Created First Instance.\n");
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IUnknown, (void **)&punkIn2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((punkIn2 == NULL), "CreateInstance failed\n")
|
|
OUTPUT (" - Created Second Instance.\n");
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// create a local interface
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// call a method that echos the local interface right back to us.
|
|
hres = pIBalls->Echo(punkIn, &punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Echo on IBalls failed\n")
|
|
TEST_FAILED_EXIT((punkOut == NULL), "Echo on IBalls failed\n")
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..Echo\n")
|
|
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - Echo OK.\n");
|
|
|
|
// release the out interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt != 1, "punkOut RefCnt is not 1\n");
|
|
OUTPUT (" - Released punkOut OK\n");
|
|
|
|
// release the In interface
|
|
ulRefCnt = punkIn->Release();
|
|
punkIn = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkIn RefCnt is not zero\n");
|
|
OUTPUT (" - Released punkIn OK\n");
|
|
|
|
OUTPUT (" - Echo Local Interface OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// call a method that echos a remote interface right back to us.
|
|
hres = pIBalls->Echo(punkIn2, &punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Echo on IBalls failed\n")
|
|
TEST_FAILED_EXIT((punkOut == NULL), "Echon on IBalls failed\n")
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn2 != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..Echo\n")
|
|
|
|
VerifyObjRefCnt(punkIn2, 2);
|
|
VerifyRHRefCnt(punkIn2, 2);
|
|
OUTPUT (" - Echo OK.\n");
|
|
|
|
// release the out interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt != 1, "punkOut RefCnt is not 1\n");
|
|
OUTPUT (" - Released punkOut OK\n");
|
|
|
|
// release the In interface
|
|
ulRefCnt = punkIn2->Release();
|
|
punkIn2 = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkIn2 RefCnt is not zero\n");
|
|
OUTPUT (" - Released punkIn2 OK\n");
|
|
|
|
OUTPUT (" - Echo Remote Interface OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release the IBalls interface
|
|
ulRefCnt = pIBalls->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "pIBalls RefCnt is not zero\n");
|
|
pIBalls = NULL;
|
|
OUTPUT (" - Released IBalls OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pICF)
|
|
{
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pIBalls)
|
|
{
|
|
ulRefCnt = pIBalls->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pIBalls RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn2)
|
|
{
|
|
ulRefCnt = punkIn2->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn2 RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestEcho");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMiddleMan
|
|
//
|
|
// test sending an remote interface to a second different process.
|
|
//
|
|
// 1. marshal [in] remote proxy
|
|
// 2. unmarshal [in] remote proxy
|
|
// 3. marshal [out] remote proxy
|
|
// 4. unmarshal [in] local proxy
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestMiddleMan(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
IBalls *pIBalls = NULL;
|
|
ICube *pICubes = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestMiddleMan\n");
|
|
|
|
// Create an IBall ClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject Balls failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject Balls failed\n")
|
|
OUTPUT (" - Aquired Remote Balls Class Object.\n");
|
|
VerifyObjRefCnt(pICF, 1);
|
|
VerifyRHRefCnt(pICF, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IBalls, (void **)&pIBalls);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((pIBalls == NULL), "CreateInstance failed\n")
|
|
OUTPUT (" - Created Balls Instance.\n");
|
|
|
|
VerifyObjRefCnt(pIBalls, 1);
|
|
VerifyRHRefCnt(pIBalls, 1);
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Balls Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create an ICube ClassFactory Interface.
|
|
grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Cubes,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject Cubes failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject Cubes failed\n")
|
|
OUTPUT (" - Aquired Remote Cubes Class Object.\n");
|
|
VerifyObjRefCnt(pICF, 1);
|
|
VerifyRHRefCnt(pICF, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_ICube, (void **)&pICubes);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance Cubes failed\n")
|
|
TEST_FAILED_EXIT((pICubes == NULL), "CreateInstance Cubes failed\n")
|
|
OUTPUT (" - Created Cubes Instance.\n");
|
|
|
|
VerifyObjRefCnt(pICubes, 1);
|
|
VerifyRHRefCnt(pICubes, 1);
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Cubes Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// pass the remote cubes interface to the balls interface.
|
|
hres = pIBalls->IsContainedIn(pICubes);
|
|
TEST_FAILED_EXIT(FAILED(hres), "IsContainedIn failed\n")
|
|
VerifyObjRefCnt(pIBalls, 1);
|
|
VerifyRHRefCnt(pIBalls, 1);
|
|
VerifyObjRefCnt(pICubes, 1);
|
|
VerifyRHRefCnt(pICubes, 1);
|
|
OUTPUT (" - IsContainedIn OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// pass the remote balls interface to the cubes interface.
|
|
hres = pICubes->Contains(pIBalls);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Contains failed\n")
|
|
VerifyObjRefCnt(pIBalls, 1);
|
|
VerifyRHRefCnt(pIBalls, 1);
|
|
VerifyObjRefCnt(pICubes, 1);
|
|
VerifyRHRefCnt(pICubes, 1);
|
|
OUTPUT (" - Contains OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// echo the remote ICubes interface to the remote IBalls interface
|
|
hres = pICubes->QueryInterface(IID_IUnknown, (void **)&punkIn);
|
|
TEST_FAILED_EXIT(FAILED(hres), "QueryInterface IUnknown failed\n")
|
|
VerifyRHRefCnt(pICubes, 2);
|
|
VerifyObjRefCnt(pICubes, 2);
|
|
OUTPUT (" - QueryInterface OK.\n");
|
|
|
|
hres = pIBalls->Echo(punkIn, &punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Echo on IBalls failed\n")
|
|
TEST_FAILED_EXIT((punkOut == NULL), "Echo on IBalls failed\n")
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..Echo\n")
|
|
|
|
VerifyObjRefCnt(punkIn, 3);
|
|
VerifyRHRefCnt(punkIn, 3);
|
|
OUTPUT (" - Echo OK.\n");
|
|
|
|
// release the out interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED(ulRefCnt != 2, "punkOut RefCnt is not 2\n");
|
|
OUTPUT (" - Released punkOut OK\n");
|
|
|
|
// release the In interface
|
|
ulRefCnt = punkIn->Release();
|
|
punkIn = NULL;
|
|
TEST_FAILED(ulRefCnt != 1, "punkIn RefCnt is not 1\n");
|
|
OUTPUT (" - Released punkIn OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release the ICubes interface
|
|
ulRefCnt = pICubes->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICubes RefCnt is not zero\n");
|
|
pICubes = NULL;
|
|
OUTPUT (" - Released ICubes OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release the IBalls interface
|
|
ulRefCnt = pIBalls->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pIBalls RefCnt is not zero\n");
|
|
pIBalls = NULL;
|
|
OUTPUT (" - Released IBalls OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pICF)
|
|
{
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
}
|
|
|
|
if (pIBalls)
|
|
{
|
|
ulRefCnt = pIBalls->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pIBalls RefCnt not zero\n");
|
|
}
|
|
|
|
if (pICubes)
|
|
{
|
|
ulRefCnt = pICubes->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICubes RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestMiddleMan");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLoop
|
|
//
|
|
// tests A calling B calling A calling B etc n times, to see if Rpc
|
|
// can handle this.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLoop(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
ILoop *pLocalLoop = NULL;
|
|
ILoop *pRemoteLoop = NULL;
|
|
|
|
OUTPUT ("Starting TestLoop\n");
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_LoopSrv, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ILoop, (void **)&pLocalLoop);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
|
|
// create the remote object
|
|
hRes = CoCreateInstance(CLSID_LoopSrv, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ILoop, (void **)&pRemoteLoop);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance Second failed\n")
|
|
|
|
// initialize the two instances
|
|
OUTPUT (" - Initializing Instances\n");
|
|
hRes = pLocalLoop->Init(pRemoteLoop);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "Initialize First failed\n")
|
|
hRes = pRemoteLoop->Init(pLocalLoop);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "Initialize Second failed\n")
|
|
|
|
// now start the test
|
|
OUTPUT (" - Running LoopTest\n");
|
|
hRes = pLocalLoop->Loop(10);
|
|
TEST_FAILED(FAILED(hRes), "Loop failed\n")
|
|
|
|
// uninitialize the two instances
|
|
OUTPUT (" - Uninitializing Instances\n");
|
|
hRes = pLocalLoop->Uninit();
|
|
TEST_FAILED_EXIT(FAILED(hRes), "Uninitialize First failed\n")
|
|
hRes = pRemoteLoop->Uninit();
|
|
TEST_FAILED_EXIT(FAILED(hRes), "Uninitialize Second failed\n")
|
|
|
|
Cleanup:
|
|
|
|
// release the two instances
|
|
OUTPUT (" - Releasing Instances\n");
|
|
|
|
if (pRemoteLoop)
|
|
pRemoteLoop->Release();
|
|
|
|
if (pLocalLoop)
|
|
pLocalLoop->Release();
|
|
|
|
return TestResult(RetVal, "TestLoop");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMultiQINormal
|
|
//
|
|
// tests IMultiQI interface on Normal proxies
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
ULONG cMisc = 4;
|
|
const IID *iidMisc[] = {
|
|
&IID_IParseDisplayName, &IID_IPersistStorage,
|
|
&IID_IPersistFile, &IID_IStorage,
|
|
&IID_IOleContainer, &IID_IOleItemContainer,
|
|
&IID_IOleInPlaceSite, &IID_IOleInPlaceActiveObject,
|
|
&IID_IOleInPlaceObject, &IID_IOleInPlaceUIWindow,
|
|
&IID_IOleInPlaceFrame, &IID_IOleWindow};
|
|
|
|
MULTI_QI arMQI[20];
|
|
MULTI_QI *pMQIResStart = arMQI;
|
|
|
|
BOOL TestMultiQINormal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
IUnknown *pUnk = NULL;
|
|
IUnknown *pUnk2 = NULL;
|
|
IMultiQI *pMQI = NULL;
|
|
ULONG i = 0, j=0, cRefs = 0;
|
|
MULTI_QI *pMQIRes = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
ULONG cSupported = 4;
|
|
const IID *iidSupported[] = {&IID_IUnknown, &IID_IMultiQI,
|
|
&IID_IClientSecurity, &IID_IMarshal,
|
|
&IID_IStdIdentity, &IID_IProxyManager};
|
|
|
|
ULONG cUnSupported = 2;
|
|
const IID *iidUnSupported[] = {&IID_IInternalUnknown,
|
|
&IID_IServerSecurity};
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT ("Starting TestMultiQINormal\n");
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_QI, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnk);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance QISRV failed\n")
|
|
|
|
VerifyObjRefCnt(pUnk, 1);
|
|
VerifyRHRefCnt(pUnk, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT ("\n - NormalQI for supported interfaces\n");
|
|
|
|
// loop through all the supported interfaces doing a normal QI.
|
|
|
|
for (i=0; i<cSupported; i++)
|
|
{
|
|
hRes = pUnk->QueryInterface(*iidSupported[i], (void **)&pUnk2);
|
|
TEST_FAILED(FAILED(hRes), "QueryInterface on supported interfaces failed\n")
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// release the interface
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
OUTPUT (" - QI for supported interface OK\n");
|
|
pUnk2->Release();
|
|
}
|
|
}
|
|
|
|
|
|
OUTPUT ("\n - NormalQI for unsupported interfaces\n");
|
|
|
|
// loop through all the unsupported interfaces doing a normal QI.
|
|
|
|
for (i=0; i<cUnSupported; i++)
|
|
{
|
|
hRes = pUnk->QueryInterface(*iidUnSupported[i], (void **)&pUnk2);
|
|
TEST_FAILED(SUCCEEDED(hRes), "QueryInterface on unsupported interface succeeded but should have failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// release the interface
|
|
pUnk2->Release();
|
|
}
|
|
else
|
|
{
|
|
VerifyObjRefCnt(pUnk, 1);
|
|
VerifyRHRefCnt(pUnk, 1);
|
|
|
|
OUTPUT (" - QI for unsupported interface OK.\n");
|
|
}
|
|
}
|
|
|
|
// should be back to normal (IUnknown)
|
|
VerifyObjRefCnt(pUnk, 1);
|
|
VerifyRHRefCnt(pUnk, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
hRes = pUnk->QueryInterface(IID_IMultiQI, (void **)&pMQI);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QI for IMultiQI failed\n")
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
|
|
OUTPUT ("\n - MultiQI for supported interfaces\n");
|
|
|
|
// now issue a MultiQI for the supported interfaces
|
|
pMQIRes = pMQIResStart;
|
|
for (i=0; i<cSupported; i++, pMQIRes++)
|
|
{
|
|
pMQIRes->pIID = iidSupported[i];
|
|
pMQIRes->pItf = NULL;
|
|
}
|
|
|
|
pMQIRes = pMQIResStart;
|
|
hRes = pMQI->QueryMultipleInterfaces(cSupported, pMQIRes);
|
|
TEST_FAILED(hRes != S_OK, "QueryMultipleInterfaces should have return S_OK\n")
|
|
VerifyObjRefCnt(pUnk, 2 + cSupported);
|
|
VerifyRHRefCnt(pUnk, 2 + cSupported);
|
|
|
|
for (i=0; i<cSupported; i++, pMQIRes++)
|
|
{
|
|
TEST_FAILED(pMQIRes->pItf == NULL, "QueryMultipleInterfaces on supported interfaces returned NULL\n")
|
|
TEST_FAILED(FAILED(pMQIRes->hr), "QueryMultipleInterfaces on supported interfaces failed\n")
|
|
|
|
if (pMQIRes->pItf != NULL)
|
|
{
|
|
OUTPUT (" - MultiQI for supported interface OK\n");
|
|
pMQIRes->pItf->Release();
|
|
|
|
VerifyObjRefCnt(pUnk, 2 + cSupported - (i+1));
|
|
VerifyRHRefCnt(pUnk, 2 + cSupported - (i+1));
|
|
}
|
|
}
|
|
|
|
// should be back to normal (IUnknown + IMultiQI)
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT ("\n - MultiQI for unsupported interfaces\n");
|
|
|
|
// now issue a MultiQI for the unsupported interfaces
|
|
pMQIRes = pMQIResStart;
|
|
for (i=0; i<cUnSupported; i++, pMQIRes++)
|
|
{
|
|
pMQIRes->pIID = iidUnSupported[i];
|
|
pMQIRes->pItf = NULL;
|
|
}
|
|
|
|
pMQIRes = pMQIResStart;
|
|
hRes = pMQI->QueryMultipleInterfaces(cUnSupported, pMQIRes);
|
|
TEST_FAILED(hRes != E_NOINTERFACE, "QueryMultipleInterfaces should have return E_NOINTERFACES\n")
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
for (i=0; i<cUnSupported; i++, pMQIRes++)
|
|
{
|
|
TEST_FAILED(pMQIRes->pItf != NULL, "QueryMultipleInterfaces on supported interfaces returned NULL\n")
|
|
TEST_FAILED(SUCCEEDED(pMQIRes->hr), "QueryMultipleInterfaces on supported interfaces failed\n")
|
|
|
|
if (pMQIRes->pItf != NULL)
|
|
{
|
|
pMQIRes->pItf->Release();
|
|
}
|
|
else
|
|
{
|
|
OUTPUT (" - MultiQI for unsupported interface OK\n");
|
|
}
|
|
}
|
|
|
|
// should back to normal refcnts (IUnknown + IMultiQI)
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// repeat this test twice, first time goes remote for the misc interfaces,
|
|
// second time finds them already instantiated.
|
|
|
|
for (j=0; j<2; j++)
|
|
{
|
|
OUTPUT ("\n - MultiQI for combination of interfaces\n");
|
|
|
|
pMQIRes = pMQIResStart;
|
|
for (i=0; i<cMisc; i++, pMQIRes++)
|
|
{
|
|
pMQIRes->pIID = iidMisc[i];
|
|
pMQIRes->pItf = NULL;
|
|
}
|
|
|
|
for (i=0; i<cSupported; i++, pMQIRes++)
|
|
{
|
|
pMQIRes->pIID = iidSupported[i];
|
|
pMQIRes->pItf = NULL;
|
|
}
|
|
|
|
for (i=0; i<cUnSupported; i++, pMQIRes++)
|
|
{
|
|
pMQIRes->pIID = iidUnSupported[i];
|
|
pMQIRes->pItf = NULL;
|
|
}
|
|
|
|
pMQIRes = pMQIResStart;
|
|
hRes = pMQI->QueryMultipleInterfaces(cSupported + cUnSupported + cMisc, pMQIRes);
|
|
TEST_FAILED(hRes != S_FALSE, "QueryMultipleInterfaces should have return S_FALSE\n")
|
|
VerifyObjRefCnt(pUnk, 2 + cSupported + cMisc);
|
|
VerifyRHRefCnt(pUnk, 2 + cSupported + cMisc);
|
|
|
|
for (i=0; i<cMisc; i++, pMQIRes++)
|
|
{
|
|
TEST_FAILED(pMQIRes->pItf == NULL, "QueryMultipleInterfaces on supported interfaces returned NULL\n")
|
|
TEST_FAILED(FAILED(pMQIRes->hr), "QueryMultipleInterfaces on supported interfaces failed\n")
|
|
|
|
if (pMQIRes->pItf != NULL)
|
|
{
|
|
OUTPUT (" - MultiQI for supported remote interface OK\n");
|
|
pMQIRes->pItf->Release();
|
|
|
|
VerifyObjRefCnt(pUnk, 2 + cSupported + cMisc - (i+1));
|
|
VerifyRHRefCnt(pUnk, 2 + cSupported + cMisc - (i+1));
|
|
}
|
|
}
|
|
|
|
for (i=0; i<cSupported; i++, pMQIRes++)
|
|
{
|
|
TEST_FAILED(pMQIRes->pItf == NULL, "QueryMultipleInterfaces on supported interfaces returned NULL\n")
|
|
TEST_FAILED(FAILED(pMQIRes->hr), "QueryMultipleInterfaces on supported interfaces failed\n")
|
|
|
|
if (pMQIRes->pItf != NULL)
|
|
{
|
|
OUTPUT (" - MultiQI for supported local interface OK\n");
|
|
pMQIRes->pItf->Release();
|
|
|
|
VerifyObjRefCnt(pUnk, 2 + cSupported - (i+1));
|
|
VerifyRHRefCnt(pUnk, 2 + cSupported - (i+1));
|
|
}
|
|
}
|
|
|
|
for (i=0; i<cUnSupported; i++, pMQIRes++)
|
|
{
|
|
TEST_FAILED(pMQIRes->pItf != NULL, "QueryMultipleInterfaces on supported interfaces returned NULL\n")
|
|
TEST_FAILED(SUCCEEDED(pMQIRes->hr), "QueryMultipleInterfaces on supported interfaces failed\n")
|
|
|
|
if (pMQIRes->pItf != NULL)
|
|
{
|
|
pMQIRes->pItf->Release();
|
|
}
|
|
else
|
|
{
|
|
OUTPUT (" - MultiQI for unsupported local interface OK\n");
|
|
}
|
|
}
|
|
|
|
// should back to normal refcnts (IUnknown + IMultiQI)
|
|
VerifyObjRefCnt(pUnk, 2);
|
|
VerifyRHRefCnt(pUnk, 2);
|
|
|
|
} // for (j=...)
|
|
|
|
// ----------------------------------------------------------------------
|
|
Cleanup:
|
|
|
|
// release the two instances
|
|
OUTPUT (" - Releasing Instances\n");
|
|
|
|
if (pMQI)
|
|
{
|
|
pMQI->Release();
|
|
}
|
|
|
|
if (pUnk)
|
|
{
|
|
cRefs = pUnk->Release();
|
|
TEST_FAILED(cRefs != 0, "Last release not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestMultiQINormal");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMultiQIHandler
|
|
//
|
|
// tests IMultiQI interface on Handlers
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestMultiQIHandler(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
IUnknown *pUnk = NULL;
|
|
IUnknown *pUnk2 = NULL;
|
|
ULONG i = 0;
|
|
MULTI_QI *pMQIRes = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
ULONG cSupported = 4;
|
|
const IID *iidSupported[] = {&IID_IUnknown, &IID_IMarshal,
|
|
&IID_IStdIdentity, &IID_IProxyManager};
|
|
|
|
ULONG cUnSupported = 4;
|
|
const IID *iidUnSupported[] = {&IID_IInternalUnknown, &IID_IClientSecurity,
|
|
&IID_IServerSecurity, &IID_IMultiQI};
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT ("Starting TestMultiQIHandler\n");
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_QIHANDLER1, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnk);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance QIHANDLER1 failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT ("\n - NormalQI for supported interfaces\n");
|
|
|
|
// loop through all the supported interfaces doing a normal QI.
|
|
|
|
for (i=0; i<cSupported; i++)
|
|
{
|
|
hRes = pUnk->QueryInterface(*iidSupported[i], (void **)&pUnk2);
|
|
TEST_FAILED(FAILED(hRes), "QueryInterface on supported interfaces failed\n")
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// release the interface
|
|
OUTPUT (" - QI for supported interface OK\n");
|
|
pUnk2->Release();
|
|
}
|
|
}
|
|
|
|
OUTPUT ("\n - NormalQI for unsupported interfaces\n");
|
|
|
|
// loop through all the unsupported interfaces doing a normal QI.
|
|
|
|
for (i=0; i<cUnSupported; i++)
|
|
{
|
|
hRes = pUnk->QueryInterface(*iidUnSupported[i], (void **)&pUnk2);
|
|
TEST_FAILED(SUCCEEDED(hRes), "QueryInterface on unsupported interface succeeded but should have failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// release the interface
|
|
pUnk2->Release();
|
|
}
|
|
else
|
|
{
|
|
OUTPUT (" - QI for unsupported interface OK.\n");
|
|
}
|
|
}
|
|
// ----------------------------------------------------------------------
|
|
Cleanup:
|
|
|
|
// release the two instances
|
|
OUTPUT (" - Releasing Instances\n");
|
|
|
|
if (pUnk)
|
|
pUnk->Release();
|
|
|
|
return TestResult(RetVal, "TestMultiQIHandler");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestHandler
|
|
//
|
|
// tests activating a server that has a handler
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestHandler(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ULONG cRefs = 0;
|
|
HRESULT hRes = S_OK;
|
|
IUnknown *pUnkSrv = NULL;
|
|
IUnknown *pUnkHdl = NULL;
|
|
IRunnableObject *pIRO = NULL;
|
|
IOleObject *pIOO = NULL;
|
|
IDropTarget *pIDT = NULL;
|
|
|
|
|
|
OUTPUT ("Starting TestHandler\n");
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_TestEmbed, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnkSrv);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance LOCAL_SERVER failed\n")
|
|
VerifyObjRefCnt(pUnkSrv, 1);
|
|
OUTPUT (" - CoCreateInstance LOCAL_SERVER succeeded\n");
|
|
|
|
OUTPUT (" - QI for IRunnableObject\n");
|
|
hRes = pUnkSrv->QueryInterface(IID_IRunnableObject, (void **)&pIRO);
|
|
TEST_FAILED(SUCCEEDED(hRes), "QI for IRO on LOCAL_SERVER succeeded\n")
|
|
|
|
if (pIRO)
|
|
{
|
|
pIRO->Release();
|
|
pIRO = NULL;
|
|
}
|
|
|
|
OUTPUT (" - Releasing Instance\n");
|
|
if (pUnkSrv)
|
|
{
|
|
cRefs = pUnkSrv->Release();
|
|
TEST_FAILED(cRefs != 0, "REFCNT wrong on Release\n")
|
|
pUnkSrv = NULL;
|
|
}
|
|
OUTPUT (" - LOCAL_SERVER case complete\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// create the remote object
|
|
|
|
hRes = CoCreateInstance(CLSID_TestEmbed, NULL, CLSCTX_INPROC_HANDLER,
|
|
IID_IUnknown, (void **)&pUnkHdl);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance INPROC_HANDLER failed\n")
|
|
VerifyObjRefCnt(pUnkHdl, 1);
|
|
VerifyRHRefCnt(pUnkHdl, 1);
|
|
OUTPUT (" - CoCreateInstance INPROC_HANDLER succeeded\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// query for some unsupported interface to ensure OLE handles QI
|
|
// when not yet connected to the server.
|
|
|
|
OUTPUT (" - QI for IDropTarget\n");
|
|
hRes = pUnkHdl->QueryInterface(IID_IDropTarget, (void **)&pIDT);
|
|
VerifyObjRefCnt(pUnkHdl, 1);
|
|
VerifyRHRefCnt(pUnkHdl, 1);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hRes),
|
|
"QI for IDropTarget on INPROC_HANDLER worked but should have failed!\n")
|
|
|
|
// the return value from failed QI on a handler that was never connected
|
|
// must be E_NOINTERFACE
|
|
TEST_FAILED_EXIT(hRes != E_NOINTERFACE,
|
|
"QI for IDropTarget on INPROC_HANDLER did not return E_NOINTERFACE!\n")
|
|
|
|
OUTPUT (" - Query for remote Interface before connected OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// run the remote server
|
|
|
|
OUTPUT (" - QI for IRunnableObject\n");
|
|
hRes = pUnkHdl->QueryInterface(IID_IRunnableObject, (void **)&pIRO);
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QI for IRO on INPROC_HANDLER failed\n")
|
|
|
|
hRes = pIRO->Run(NULL);
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
TEST_FAILED(FAILED(hRes), "IRO->Run on INPROC_HANDLER failed\n")
|
|
OUTPUT (" - INPROC_HANDLER run OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test stoping the server
|
|
|
|
OUTPUT (" - Stop the Server\n");
|
|
hRes = pUnkHdl->QueryInterface(IID_IOleObject, (void **)&pIOO);
|
|
VerifyObjRefCnt(pUnkHdl, 3);
|
|
VerifyRHRefCnt(pUnkHdl, 3);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QI for IOleObject on INPROC_HANDLER failed\n")
|
|
|
|
hRes = pIOO->Close(OLECLOSE_NOSAVE);
|
|
VerifyObjRefCnt(pUnkHdl, 3);
|
|
VerifyRHRefCnt(pUnkHdl, 3);
|
|
|
|
TEST_FAILED(FAILED(hRes), "IOO->Close on INPROC_HANDLER failed\n")
|
|
pIOO->Release();
|
|
pIOO = NULL;
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
OUTPUT (" - INPROC_HANDLER Close OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// query again for some unsupported interface to ensure OLE handles QI
|
|
// when disconnected from the server.
|
|
|
|
OUTPUT (" - QI for IDropTarget\n");
|
|
hRes = pUnkHdl->QueryInterface(IID_IDropTarget, (void **)&pIDT);
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
TEST_FAILED_EXIT(SUCCEEDED(hRes),
|
|
"QI for IDropTarget on disconnected INPROC_HANDLER worked but should have failed!\n")
|
|
|
|
// the return value from failed QI on a handler that has been disconnected
|
|
// must be CO_O_OBJNOTCONNECTED
|
|
|
|
TEST_FAILED_EXIT(hRes != CO_E_OBJNOTCONNECTED,
|
|
"QI for IDropTarget on INPROC_HANDLER did not return CO_E_OBJNOTCONNECTED!\n")
|
|
|
|
OUTPUT (" - Query for remote Interface after disconnected OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test restarting the server
|
|
|
|
Sleep(500);
|
|
OUTPUT (" - Run the Server Again\n");
|
|
hRes = pIRO->Run(NULL);
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
|
|
TEST_FAILED(FAILED(hRes), "Second IRO->Run on INPROC_HANDLER failed\n")
|
|
OUTPUT (" - Second INPROC_HANDLER Run OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test stoping the server
|
|
|
|
OUTPUT (" - Stop the Server\n");
|
|
hRes = pUnkHdl->QueryInterface(IID_IOleObject, (void **)&pIOO);
|
|
VerifyObjRefCnt(pUnkHdl, 3);
|
|
VerifyRHRefCnt(pUnkHdl, 3);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QI for IOleObject on INPROC_HANDLER failed\n")
|
|
|
|
hRes = pIOO->Close(OLECLOSE_NOSAVE);
|
|
VerifyObjRefCnt(pUnkHdl, 3);
|
|
VerifyRHRefCnt(pUnkHdl, 3);
|
|
|
|
TEST_FAILED(FAILED(hRes), "IOO->Close on INPROC_HANDLER failed\n")
|
|
pIOO->Release();
|
|
pIOO = NULL;
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
OUTPUT (" - INPROC_HANDLER Close OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test using weak references
|
|
|
|
OUTPUT (" - Call OleSetContainedObject TRUE\n");
|
|
hRes = OleSetContainedObject(pUnkHdl, 1);
|
|
TEST_FAILED(FAILED(hRes), "1st OleSetContainedObject on pUnkHdl failed\n")
|
|
OUTPUT (" - OleSetContainedObject OK\n");
|
|
|
|
Sleep(500);
|
|
OUTPUT (" - Run the Server Again\n");
|
|
hRes = pIRO->Run(NULL);
|
|
VerifyObjRefCnt(pUnkHdl, 2);
|
|
VerifyRHRefCnt(pUnkHdl, 2);
|
|
|
|
TEST_FAILED(FAILED(hRes), "Third IRO->Run on INPROC_HANDLER failed\n")
|
|
OUTPUT (" - Third INPROC_HANDLER Run OK\n");
|
|
|
|
// try making the references strong again
|
|
OUTPUT (" - Call OleSetContainedObject FALSE\n");
|
|
hRes = OleSetContainedObject(pUnkHdl, 0);
|
|
TEST_FAILED(FAILED(hRes), "2nd OleSetContainedObject on pUnkHdl failed\n")
|
|
OUTPUT (" - OleSetContainedObject OK\n");
|
|
|
|
// try making the references weak again
|
|
OUTPUT (" - Call OleSetContainedObject TRUE\n");
|
|
hRes = OleSetContainedObject(pUnkHdl, 1);
|
|
TEST_FAILED(FAILED(hRes), "3rd OleSetContainedObject on pUnkHdl failed\n")
|
|
OUTPUT (" - OleSetContainedObject OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// cleanup
|
|
|
|
pIRO->Release();
|
|
pIRO = NULL;
|
|
VerifyObjRefCnt(pUnkHdl, 1);
|
|
VerifyRHRefCnt(pUnkHdl, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT (" - Releasing Instance\n");
|
|
if (pUnkHdl)
|
|
{
|
|
cRefs = pUnkHdl->Release();
|
|
TEST_FAILED(cRefs != 0, "REFCNT wrong on Release\n")
|
|
pUnkHdl = NULL;
|
|
}
|
|
OUTPUT (" - INPROC_HANDLER case complete\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
// release the two instances
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
if (pIDT)
|
|
{
|
|
pIDT->Release();
|
|
}
|
|
|
|
if (pIRO)
|
|
{
|
|
pIRO->Release();
|
|
}
|
|
|
|
if (pIOO)
|
|
{
|
|
pIOO->Release();
|
|
}
|
|
|
|
if (pUnkSrv)
|
|
{
|
|
pUnkSrv->Release();
|
|
}
|
|
|
|
if (pUnkHdl)
|
|
{
|
|
pUnkHdl->Release();
|
|
}
|
|
|
|
return TestResult(RetVal, "TestHandler");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestGetStandardMarshal
|
|
//
|
|
// test CoGetStandardMarshal API
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestGetStandardMarshal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
IMarshal *pIM = NULL, *pIM2 = NULL;
|
|
IStream *pStm;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punkOut = NULL;
|
|
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestGetStandardMarshal\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = CoGetStandardMarshal(IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL, &pIM);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetStandardMarshal failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
hres = CoGetStandardMarshal(IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL, &pIM2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoGetStandardMarshal failed\n")
|
|
VerifyRHRefCnt(punkIn, 2);
|
|
|
|
TEST_FAILED((pIM != pIM2), "CoGetStandardMarshal returned two different interfaces.\n")
|
|
ulRefCnt = pIM2->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 1, "pIM2 RefCnt is wrong");
|
|
pIM2 = NULL;
|
|
|
|
hres = CoGetStandardMarshal(IID_IUnknown, NULL, 0, NULL, MSHLFLAGS_NORMAL, &pIM2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "third CoGetStandardMarshal failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
OUTPUT (" - CoGetStandardMarshal OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = pIM->MarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "MarshalInterface failed\n")
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// since we are unmarshalling in the same process, the RH should go away.
|
|
hres = pIM->UnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "UnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - UnmarshalInterface OK\n");
|
|
|
|
// release interface and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero");
|
|
punkOut = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = pIM->MarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "MarshalInterface failed\n")
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// since we are unmarshalling in the same process, the RH should go away.
|
|
hres = pIM2->UnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "UnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match...1st Local Unmarshal\n")
|
|
OUTPUT (" - Second UnmarshalInterface OK\n");
|
|
|
|
// release interface and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero");
|
|
punkOut = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
ulRefCnt = pIM2->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "pIM2 RefCnt is zero");
|
|
pIM2 = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release the marshalled data
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = pIM->MarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "MarshalInterface failed\n")
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = pIM->ReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Release Marshal Data failed\n.");
|
|
OUTPUT (" - ReleaseMarshalData OK\n");
|
|
|
|
|
|
// the RH should go away, and we should have only the original
|
|
// refcnt from creation left on the object.
|
|
ulRefCnt = pIM->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "pIM RefCnt not zero");
|
|
pIM = NULL;
|
|
|
|
// release the original object
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkIn RefCnt not zero");
|
|
punkIn = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestGetStandardMarshal");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestLockObjectExternal
|
|
//
|
|
// test CoLockObjectExternal API
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLockObjectExternal(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkIn = NULL;
|
|
IStream *pStm = NULL;
|
|
|
|
OUTPUT ("Starting TestLockObjectExternal\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test calling it once, then releasing it once
|
|
|
|
hres = CoLockObjectExternal(punkIn, TRUE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - CoLockObjectExternal TRUE OK\n");
|
|
|
|
hres = CoLockObjectExternal(punkIn, FALSE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoLockObjectExternal failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoLockObjectExternal FALSE OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test calling it twice, then releasing it twice
|
|
|
|
// the first AddRef inc's the StrongCnt, the RH, and the real object.
|
|
hres = CoLockObjectExternal(punkIn, TRUE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - CoLockObjectExternal TRUE OK\n");
|
|
|
|
// the second AddRef inc's the StrongCnt and the RH, but not the
|
|
// real object.
|
|
hres = CoLockObjectExternal(punkIn, TRUE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal failed.\n")
|
|
VerifyRHRefCnt(punkIn, 2);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - CoLockObjectExternal TRUE OK\n");
|
|
|
|
// the second release Dec's the StrongCnt and the RH, but not the
|
|
// real object.
|
|
hres = CoLockObjectExternal(punkIn, FALSE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoLockObjectExternal failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - CoLockObjectExternal FALSE OK\n");
|
|
|
|
// the last Release dec's the StrongCnt, the RH, and the real object.
|
|
hres = CoLockObjectExternal(punkIn, FALSE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoLockObjectExternal failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoLockObjectExternal FALSE OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test calling it once, then releasing the punkIn and ensuring
|
|
// the object is still alive.
|
|
|
|
hres = CoLockObjectExternal(punkIn, TRUE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - CoLockObjectExternal TRUE OK\n");
|
|
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 1, "Release returned incorrect value.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - punkIn->Release OK\n");
|
|
|
|
hres = CoLockObjectExternal(punkIn, FALSE, FALSE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoLockObjectExternal failed\n")
|
|
punkIn = NULL;
|
|
OUTPUT (" - CoLockObjectExternal FALSE OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test calling marshal interface, followed by CLOE(F,T). This
|
|
// should disconnect the object. This is bizarre backward compatibility
|
|
// semantics that some LOTUS apps do rely on.
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL,
|
|
MSHLFLAGS_TABLESTRONG);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface TABLE_STRONG OK\n");
|
|
|
|
hres = CoLockObjectExternal(punkIn, FALSE, TRUE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal(F,T) failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - CoLockObjectExternal FALSE TRUE OK\n");
|
|
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL,
|
|
MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface NORMAL OK\n");
|
|
|
|
hres = CoLockObjectExternal(punkIn, FALSE, TRUE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal(F,T) failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - CoLockObjectExternal FALSE TRUE OK\n");
|
|
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL,
|
|
MSHLFLAGS_TABLEWEAK);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoMarshalInterface TABLEWEAK OK\n");
|
|
|
|
// BUGBUG: refcnts seem to be wrong on the following call:
|
|
|
|
hres = CoLockObjectExternal(punkIn, FALSE, TRUE);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoLockObjectExternal(F,T) failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - CoLockObjectExternal FALSE TRUE OK\n");
|
|
|
|
punkIn->Release();
|
|
punkIn = NULL;
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
pStm->Release();
|
|
}
|
|
|
|
return TestResult(RetVal, "TestLockObjectExternal");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestReleaseMarshalData
|
|
//
|
|
// test CoReleaseMarshalData API
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestReleaseMarshalData(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG cRefs;
|
|
IUnknown *punkIn = NULL;
|
|
IStream *pStm = NULL;
|
|
LARGE_INTEGER large_int;
|
|
|
|
|
|
OUTPUT ("Starting TestReleaseMarshalData\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// Create a shared memory stream for the marshaled object
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// try RMD on NORMAL marshal
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - MarshalInterface NORMAL OK\n");
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData NORMAL OK\n");
|
|
|
|
|
|
// try RMD on TABLESTRONG marshal
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_TABLESTRONG);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - MarshalInterface TABLESTRONG OK\n");
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData TABLESTRONG OK\n");
|
|
|
|
// try RMD on TABLEWEAK marshal
|
|
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_TABLEWEAK);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
OUTPUT (" - MarshalInterface TABLEWEAK OK\n");
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
OUTPUT (" - CoReleaseMarshalData TABLEWEAK OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (punkIn)
|
|
{
|
|
cRefs = punkIn->Release();
|
|
TEST_FAILED(cRefs != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
pStm->Release();
|
|
}
|
|
|
|
return TestResult(RetVal, "TestReleaseMarshalData");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestDisconnectObject
|
|
//
|
|
// test CoDisconnectObject API
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestDisconnectObject(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkIn = NULL;
|
|
IStream *pStm = NULL;
|
|
LARGE_INTEGER large_int;
|
|
|
|
|
|
OUTPUT ("Starting TestDisconnectObject\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// Create a shared memory stream for the marshaled object
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
// test calling it without having ever marshalled it.
|
|
|
|
hres = CoDisconnectObject(punkIn, 0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoDisconnectObject succeeded but should have failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
OUTPUT (" - first CoDisconnectObject OK\n");
|
|
|
|
|
|
// test calling after having marshalled it.
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_TABLEWEAK);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed.\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
VerifyObjRefCnt(punkIn, 2);
|
|
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = CoDisconnectObject(punkIn, 0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "second CoDisconnectObject failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
OUTPUT (" - second CoDisconnectObject OK\n");
|
|
|
|
// now release the marshalled data
|
|
|
|
LISet32(large_int, 0);
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoReleaseMarshalData failed.\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
OUTPUT (" - CoReleaseMarshalData OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
pStm->Release();
|
|
}
|
|
|
|
return TestResult(RetVal, "TestDisconnectObject");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestOXIDs
|
|
//
|
|
// tests A calling B calling A calling B etc n times, to see if Rpc
|
|
// can handle this.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestExpiredOXIDs(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
ILoop *pLocalLoop = NULL;
|
|
IClassFactory *pUnk = NULL;
|
|
|
|
OUTPUT ("Starting TestExpiredOXIDs\n");
|
|
|
|
// start the local server process manually so it stays alive for the
|
|
// duration of the test (even though we dont have an OXIDEntry for it.
|
|
|
|
STARTUPINFO startupInfo;
|
|
PROCESS_INFORMATION processInfo;
|
|
memset(&processInfo, 0, sizeof(processInfo));
|
|
memset(&startupInfo, 0, sizeof(startupInfo));
|
|
|
|
RetVal = CreateProcess(TEXT("ballsrv.exe"),
|
|
NULL, // command line
|
|
NULL, // security for process
|
|
NULL, // security for thread
|
|
FALSE, // inherit handles
|
|
NORMAL_PRIORITY_CLASS,
|
|
NULL, // environment block
|
|
NULL, // current directory
|
|
&startupInfo,
|
|
&processInfo);
|
|
|
|
if (RetVal == FALSE)
|
|
{
|
|
hRes = GetLastError();
|
|
OUTPUT (" - CreateProcess Failed\n");
|
|
}
|
|
else
|
|
{
|
|
// give the process time to register its class object
|
|
Sleep(2000);
|
|
}
|
|
|
|
for (ULONG i=0; i<7; i++)
|
|
{
|
|
// create a new instance of a local server that is already running,
|
|
// causing us to reuse the same OXID.
|
|
|
|
hRes = CoGetClassObject(CLSID_Balls,
|
|
CLSCTX_LOCAL_SERVER,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pUnk);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoGetClassObject ballsrv failed\n")
|
|
|
|
// release interface (lets OXIDEntry be placed on the expired list)
|
|
pUnk->Release();
|
|
pUnk = NULL;
|
|
|
|
for (ULONG j=0; j<i; j++)
|
|
{
|
|
// create (i) new instances of another class and release them
|
|
// right away. This causes (i) new processes to start and (i)
|
|
// entries of the OXID table expired list to get flushed.
|
|
|
|
hRes = CoCreateInstance(CLSID_LoopSrv, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ILoop, (void **)&pLocalLoop);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
pLocalLoop->Release();
|
|
pLocalLoop = NULL;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
// release the two instances
|
|
OUTPUT (" - Releasing Instances\n");
|
|
|
|
if (pUnk)
|
|
pUnk->Release();
|
|
|
|
if (pLocalLoop)
|
|
pLocalLoop->Release();
|
|
|
|
// kill the server process
|
|
if (processInfo.hProcess != 0)
|
|
{
|
|
BOOL fKill = TerminateProcess(processInfo.hProcess, 0);
|
|
if (!fKill)
|
|
{
|
|
hRes = GetLastError();
|
|
OUTPUT (" - TermintateProcess Failed\n");
|
|
}
|
|
|
|
CloseHandle(processInfo.hThread);
|
|
CloseHandle(processInfo.hProcess);
|
|
}
|
|
|
|
return TestResult(RetVal, "TestExpiredOXIDs");
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestAggregate
|
|
//
|
|
// tests creating an RH that is aggregated.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestAggregate(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
IUnknown *punkOuter = NULL;
|
|
IUnknown *pUnk = NULL;
|
|
IBalls *pIBall = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
|
|
OUTPUT ("Starting TestAggregate\n");
|
|
|
|
punkOuter = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkOuter == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkOuter, 1);
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_Balls, punkOuter, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnk);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
|
|
// now release the object
|
|
ulRefCnt = pUnk->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "Release failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// create our interface to pass to the remote object.
|
|
hRes = CoCreateInstance(CLSID_Balls, punkOuter, CLSCTX_LOCAL_SERVER,
|
|
IID_IUnknown, (void **)&pUnk);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
|
|
hRes = pUnk->QueryInterface(IID_IBalls, (void **)&pIBall);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "QueryInterface failed\n")
|
|
|
|
// now release the interface
|
|
ulRefCnt = pIBall->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "Release failed\n")
|
|
|
|
// now release the object
|
|
ulRefCnt = pUnk->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "Release failed\n")
|
|
|
|
// now release the punkOuter
|
|
ulRefCnt = punkOuter->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "Release failed\n")
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
return TestResult(RetVal, "TestAggregate");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestCreateRemoteHandler
|
|
//
|
|
// test CoCreateRemoteHandler API and unmarshalling data into it.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestCreateRemoteHandler(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkBall = NULL;
|
|
IUnknown *punkOuter = NULL;
|
|
IClassFactory *pICF = NULL;
|
|
|
|
|
|
OUTPUT ("Starting TestCreateRemoteHandler\n");
|
|
|
|
|
|
// create the controlling unknown for the remote object.
|
|
punkOuter = GetTestUnk();
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// create a remote object that we will aggregate.
|
|
|
|
// Create an IBall ClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject Balls failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject Balls failed\n")
|
|
OUTPUT (" - Aquired Remote Balls Class Object.\n");
|
|
VerifyObjRefCnt(pICF, 1);
|
|
VerifyRHRefCnt(pICF, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(punkOuter, IID_IUnknown, (void **)&punkBall);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((punkBall == NULL), "CreateInstance failed\n")
|
|
OUTPUT (" - Created Balls Instance.\n");
|
|
|
|
VerifyObjRefCnt(punkBall, 1);
|
|
VerifyRHRefCnt(punkBall, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Balls Class Object.\n");
|
|
|
|
// release the remote object handler
|
|
ulRefCnt = punkBall->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkBall RefCnt not zero");
|
|
punkBall = NULL;
|
|
|
|
// release the outer
|
|
ulRefCnt = punkOuter->Release();
|
|
TEST_FAILED_EXIT(ulRefCnt != 0, "punkOuter RefCnt not zero");
|
|
punkOuter = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
if (punkBall)
|
|
{
|
|
ulRefCnt = punkBall->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkBall RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOuter)
|
|
{
|
|
ulRefCnt = punkOuter->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOuter RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestCreateRemoteHandler");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestTIDAndLID
|
|
//
|
|
// test the values of TID and MID to ensure they are correct across
|
|
// calls.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
HRESULT TIDAndLIDSubroutine();
|
|
DWORD _stdcall TIDAndLIDServer(void *param);
|
|
|
|
|
|
BOOL TestTIDAndLID(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes;
|
|
|
|
// First, try it across process boundaries.
|
|
hRes = TIDAndLIDSubroutine();
|
|
TEST_FAILED(FAILED(hRes), "TIDAndLID different process failed\n")
|
|
|
|
|
|
// Next, try it across thread boundaries.
|
|
// Spin a thread to be the server of the TIDAndLID
|
|
|
|
HANDLE hEvent[2];
|
|
hEvent[0]= CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
hEvent[1]= CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
DWORD dwThrdId = 0;
|
|
HANDLE hThrd = CreateThread(NULL, 0,
|
|
TIDAndLIDServer,
|
|
&hEvent[0], 0, &dwThrdId);
|
|
if (hThrd)
|
|
{
|
|
// wait for thread to register its class object
|
|
WaitForSingleObject(hEvent[0], 0xffffffff);
|
|
Sleep(0);
|
|
|
|
// Now run the whole test again. This time CoGetClassObject should
|
|
// find the server running in the other thread.
|
|
|
|
hRes = TIDAndLIDSubroutine();
|
|
TEST_FAILED(FAILED(hRes), "TIDAndLID different process failed\n")
|
|
|
|
// signal the other thread to exit
|
|
CloseHandle(hThrd);
|
|
PostThreadMessage(dwThrdId, WM_QUIT, 0, 0);
|
|
|
|
// wait for other thread to call CoUninitialize
|
|
WaitForSingleObject(hEvent[1], 0xffffffff);
|
|
CloseHandle(hEvent[0]);
|
|
CloseHandle(hEvent[1]);
|
|
}
|
|
else
|
|
{
|
|
hRes = GetLastError();
|
|
TEST_FAILED(hRes, "CreateThread failed\n")
|
|
}
|
|
|
|
return TestResult(RetVal, "TestTIDAndLID");
|
|
}
|
|
|
|
HRESULT TIDAndLIDSubroutine()
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ULONG ulRefCnt;
|
|
ICube *pCube = NULL;
|
|
IUnknown *pUnk = NULL;
|
|
HRESULT hRes;
|
|
|
|
// create our interface to pass to the remote object.
|
|
OUTPUT (" - Create Instance of ICube\n");
|
|
hRes = CoCreateInstance(CLSID_Cubes, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ICube, (void **)&pCube);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance CLSID_Cubes failed\n")
|
|
OUTPUT (" - Instance of ICubes created OK\n");
|
|
|
|
pUnk = GetTestUnk();
|
|
|
|
hRes = pCube->PrepForInputSyncCall(pUnk);
|
|
TEST_FAILED(FAILED(hRes), "pCube->PreForInputSyncCall failed\n")
|
|
|
|
hRes = pCube->InputSyncCall();
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
TEST_FAILED(FAILED(hRes), "pCube->InputSyncCall failed\n")
|
|
}
|
|
else
|
|
{
|
|
TEST_FAILED(SUCCEEDED(hRes), "pCube->InputSyncCall should have failed\n")
|
|
}
|
|
OUTPUT (" - Completed Release inside InputSync call\n");
|
|
|
|
|
|
OUTPUT (" - Get the current LID information\n");
|
|
UUID lidCaller;
|
|
CoGetCurrentLogicalThreadId(&lidCaller);
|
|
|
|
OUTPUT (" - call on ICube interface\n");
|
|
hRes = pCube->SimpleCall(GetCurrentProcessId(),
|
|
GetCurrentThreadId(),
|
|
lidCaller);
|
|
|
|
TEST_FAILED(FAILED(hRes), "pCube->SimpleCall failed\n")
|
|
|
|
// release the interface
|
|
OUTPUT (" - Release the ICube interface\n");
|
|
ulRefCnt = pCube->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCube RefCnt not zero\n");
|
|
pCube = NULL;
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Subroutine Complete. Doing Cleanup\n");
|
|
|
|
if (pCube != NULL)
|
|
{
|
|
pCube->Release();
|
|
pCube = NULL;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
// current COINIT flag used on main thread
|
|
extern DWORD gInitFlag;
|
|
|
|
DWORD _stdcall TIDAndLIDServer(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
|
|
HANDLE *pHandle = (HANDLE *) param;
|
|
|
|
HANDLE hEvent[2];
|
|
hEvent[0] = *pHandle;
|
|
hEvent[1] = *(pHandle+1);
|
|
|
|
OUTPUT (" - TIDAndLIDServer Start\n");
|
|
|
|
HRESULT hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "TIDAndLIDServer CoInitialize failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
DWORD dwReg;
|
|
IClassFactory *pICF = new CTestUnkCF();
|
|
|
|
if (pICF)
|
|
{
|
|
hRes = CoRegisterClassObject(CLSID_Cubes, pICF,
|
|
CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE, &dwReg);
|
|
|
|
TEST_FAILED(FAILED(hRes), "TIDAndLID CoRegisterClassObject failed\n")
|
|
SetEvent(hEvent[0]);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
hRes = CoRevokeClassObject(dwReg);
|
|
TEST_FAILED(FAILED(hRes), "TIDAndLID CoRevokeClassObject failed\n")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// set the event anyway
|
|
TEST_FAILED(TRUE, "TIDAndLID new CTestUnkCF failed\n")
|
|
SetEvent(hEvent[0]);
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
else
|
|
{
|
|
// wake the other guy anyway
|
|
SetEvent(hEvent[0]);
|
|
}
|
|
|
|
// signal we've called CoUninitialize
|
|
SetEvent(hEvent[1]);
|
|
|
|
OUTPUT (" - TIDAndLIDServer done\n");
|
|
return hRes;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestNonNDRProxy
|
|
//
|
|
// test using a non-NDR proxy and stub for ICube interface.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestNonNDRProxy(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes;
|
|
ULONG ulRefCnt;
|
|
ICube *pCube = NULL;
|
|
|
|
|
|
OUTPUT ("Starting TestNonNDR\n");
|
|
|
|
// stomp on the registry to use our custom proxy dll for ICube interface
|
|
BYTE szValueSave[MAX_PATH];
|
|
DWORD cbValue = sizeof(szValueSave);
|
|
DWORD dwType;
|
|
|
|
LONG lRes = RegQueryValueEx(HKEY_CLASSES_ROOT,
|
|
TEXT("Interface\\{00000139-0001-0008-C000-000000000046}\\ProxyStubClsid32"),
|
|
NULL,
|
|
&dwType,
|
|
szValueSave,
|
|
&cbValue);
|
|
|
|
if (lRes == ERROR_SUCCESS)
|
|
{
|
|
BYTE szValueNew[40];
|
|
strcpy((char *)&szValueNew[0], "{0000013e-0001-0008-C000-000000000046}");
|
|
|
|
lRes = RegSetValueEx(HKEY_CLASSES_ROOT,
|
|
TEXT("Interface\\{00000139-0001-0008-C000-000000000046}\\ProxyStubClsid32"),
|
|
NULL,
|
|
dwType,
|
|
szValueNew,
|
|
sizeof(szValueNew));
|
|
}
|
|
|
|
// create our interface to pass to the remote object.
|
|
OUTPUT (" - Create Instance of ICube\n");
|
|
hRes = CoCreateInstance(CLSID_Cubes, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ICube, (void **)&pCube);
|
|
TEST_FAILED_EXIT(FAILED(hRes), "CoCreateInstance failed\n")
|
|
OUTPUT (" - Instance of ICube created OK\n");
|
|
|
|
|
|
OUTPUT (" - Make first call on ICube interface\n");
|
|
hRes = pCube->MoveCube(23, 34);
|
|
TEST_FAILED(FAILED(hRes), "ICube->MoveCube failed\n")
|
|
|
|
// release the interface
|
|
OUTPUT (" - Release the ICube interface\n");
|
|
ulRefCnt = pCube->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pCube RefCnt not zero\n");
|
|
pCube = NULL;
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// restore the registry to use real proxy dll for ICube interface
|
|
if (lRes == ERROR_SUCCESS)
|
|
{
|
|
lRes = RegSetValueEx(HKEY_CLASSES_ROOT,
|
|
TEXT("Interface\\{00000139-0001-0008-C000-000000000046}\\ProxyStubClsid32"),
|
|
NULL,
|
|
dwType,
|
|
szValueSave,
|
|
cbValue);
|
|
}
|
|
|
|
return TestResult(RetVal, "TestNonNDR");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test rundown
|
|
//
|
|
// - build 9 objects
|
|
// - marshal 3 NORMAL, 3 TABLE_STRONG, 3 TABLE_WEAK.
|
|
// - start 3 clients that each do 3 things...
|
|
// Unmarshal Objects
|
|
// Call Method on each object
|
|
// Release Objects
|
|
// each client has a sleep before one of the operations to let rundown
|
|
// happen.
|
|
// - CoDisconnectObject each of the 9 objects
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestRundown(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
BOOL fSame = TRUE;
|
|
ULONG k = 0;
|
|
HRESULT hres;
|
|
IStream *pstm[3] = {NULL, NULL, NULL};
|
|
IUnknown *punk[9] = {NULL, NULL, NULL,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL};
|
|
|
|
DWORD mshlflags[3] = {MSHLFLAGS_NORMAL,
|
|
MSHLFLAGS_TABLESTRONG,
|
|
MSHLFLAGS_TABLEWEAK};
|
|
|
|
MSG msg;
|
|
DWORD dwEndTime;
|
|
|
|
|
|
OUTPUT ("Starting TestRundown\n");
|
|
|
|
|
|
// create 9 objects to play with
|
|
OUTPUT ("Creating Nine Objects\n");
|
|
for (ULONG i=0; i<9; i++)
|
|
{
|
|
punk[i] = GetTestUnk();
|
|
TEST_FAILED_EXIT((punk[i] == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punk[i], 1);
|
|
}
|
|
|
|
|
|
// create 3 streams on files
|
|
OUTPUT ("Creating Three Streams\n");
|
|
for (i=0; i<3; i++)
|
|
{
|
|
pstm[i] = (IStream *) new CStreamOnFile(pwszFileName[i] ,hres, FALSE);
|
|
TEST_FAILED_EXIT((pstm[i] == NULL), "new CStreamOnFile failed\n")
|
|
TEST_FAILED_EXIT(FAILED(hres), "CStreamOnFile failed\n")
|
|
VerifyObjRefCnt(pstm[i], 1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// marshal the nine objects into 3 different streams on files.
|
|
OUTPUT ("Marshal Nine Objects into Three Streams\n");
|
|
|
|
|
|
// loop on stream
|
|
for (i=0; i<3; i++)
|
|
{
|
|
// loop on marshal flags
|
|
for (ULONG j=0; j<3; j++)
|
|
{
|
|
hres = CoMarshalInterface(pstm[i], IID_IParseDisplayName, punk[k++],
|
|
0, NULL, mshlflags[j]);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
}
|
|
}
|
|
|
|
|
|
// release the streams
|
|
OUTPUT ("Releasing the streams\n");
|
|
for (i=0; i<3; i++)
|
|
{
|
|
pstm[i]->Release();
|
|
pstm[i] = NULL;
|
|
}
|
|
|
|
|
|
// start the 3 client processes
|
|
OUTPUT ("Start Three Client Processes\n");
|
|
|
|
#if 0
|
|
for (i=0; i<3; i++)
|
|
{
|
|
DWORD dwThrdId = 0;
|
|
HANDLE hThrd = CreateThread(NULL, 0,
|
|
RundownClient,
|
|
(void *)i,
|
|
0, &dwThrdId);
|
|
|
|
if (hThrd)
|
|
{
|
|
CloseHandle(hThrd);
|
|
}
|
|
else
|
|
{
|
|
hres = GetLastError();
|
|
TEST_FAILED_EXIT(hres, "CreateThread failed\n")
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// sleep for some time to let the clients run
|
|
OUTPUT ("Waiting 12 minutes to let clients run\n");
|
|
|
|
dwEndTime = GetTickCount() + 780000;
|
|
|
|
while (GetTickCount() < dwEndTime)
|
|
|
|
{
|
|
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (GetMessage(&msg, NULL, 0, 0))
|
|
DispatchMessage(&msg);
|
|
}
|
|
else
|
|
{
|
|
Sleep(250);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// disconnect the nine objects
|
|
OUTPUT ("Disconnecting Nine Objects\n");
|
|
for (i=0; i<9; i++)
|
|
{
|
|
if (punk[i] != NULL)
|
|
{
|
|
hres = CoDisconnectObject(punk[i], 0);
|
|
punk[i] = NULL;
|
|
TEST_FAILED(FAILED(hres), "CoDisconnectObject failed\n")
|
|
}
|
|
}
|
|
|
|
// release the streams
|
|
OUTPUT ("Releasing the streams\n");
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (pstm[i] != NULL)
|
|
{
|
|
pstm[i]->Release();
|
|
pstm[i] = NULL;
|
|
}
|
|
}
|
|
|
|
return TestResult(RetVal, "TestRundown");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test rundown worker thread
|
|
//
|
|
// starts a thread that will do...
|
|
// Unmarshal Objects
|
|
// Call Method on each object
|
|
// Release Objects
|
|
//
|
|
// perform a sleep before one of the operations to let rundown
|
|
// happen.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall RundownClient(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ULONG i = 0;
|
|
HRESULT hres;
|
|
IStream *pstm = NULL;
|
|
IBindCtx *pbctx = NULL;
|
|
IParseDisplayName *punk[3] = {NULL, NULL, NULL};
|
|
|
|
|
|
OUTPUT (" Starting RundownClient\n");
|
|
|
|
// get the filename from the passed in parameter
|
|
DWORD dwThreadNum = (DWORD)param;
|
|
|
|
hres = CoInitialize(NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoInitialzie failed\n")
|
|
|
|
|
|
// create a stream on the file
|
|
OUTPUT (" - CreateStreamOnFile\n");
|
|
pstm = (IStream *) new CStreamOnFile(pwszFileName[dwThreadNum], hres, TRUE);
|
|
TEST_FAILED_EXIT((pstm == NULL), "CStreamOnFile failed\n")
|
|
TEST_FAILED_EXIT(FAILED(hres), "CStreamOnFile failed\n")
|
|
VerifyObjRefCnt(pstm, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
if (dwThreadNum == 2)
|
|
Sleep(5000);
|
|
|
|
// unmarshal the interfaces
|
|
OUTPUT (" - Unmarshal the interfaces\n");
|
|
for (i=0; i<3; i++)
|
|
{
|
|
hres = CoUnmarshalInterface(pstm, IID_IParseDisplayName,
|
|
(void **)&punk[i]);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
}
|
|
OUTPUT (" - Unmarshaled the interfaces OK.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
if (dwThreadNum == 1)
|
|
Sleep(5000);
|
|
|
|
hres = CreateBindCtx(0, &pbctx);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateBindCtx failed\n")
|
|
|
|
// call the objects
|
|
for (i=0; i<3; i++)
|
|
{
|
|
ULONG cbEaten = 0;
|
|
IMoniker *pmnk = NULL;
|
|
|
|
hres = punk[i]->ParseDisplayName(pbctx, pwszFileName[dwThreadNum],
|
|
&cbEaten, &pmnk);
|
|
TEST_FAILED(FAILED(hres), "call on object failed\n")
|
|
|
|
if (pmnk)
|
|
{
|
|
pmnk->Release();
|
|
}
|
|
}
|
|
OUTPUT (" - Called the interfaces OK.\n");
|
|
|
|
pbctx->Release();
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
if (dwThreadNum == 0)
|
|
Sleep(5000);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Rundown Thread Complete. Doing Cleanup\n");
|
|
|
|
// release the objects
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (punk[i] != NULL)
|
|
{
|
|
punk[i]->Release();
|
|
punk[i] = NULL;
|
|
}
|
|
}
|
|
OUTPUT (" - Released the interfaces OK.\n");
|
|
|
|
// release the stream
|
|
pstm->Release();
|
|
|
|
CoUninitialize();
|
|
|
|
return TestResult(RetVal, "TestRundown");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestMarshalStorage
|
|
//
|
|
// test marshalling a docfile
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestMarshalStorage(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
ULONG ulRefCnt;
|
|
IStorage *pStgIn = NULL;
|
|
IStorage *pStgOut = NULL;
|
|
IStream *pStm = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestMarshalStorage\n");
|
|
|
|
// create a docfile
|
|
hres = StgCreateDocfile(L"foo.bar",
|
|
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
|
|
0, &pStgIn);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "StgCreateDocFile failed\n")
|
|
|
|
// create a stream to marshal the storage into
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// marshal the interface
|
|
hres = CoMarshalInterface(pStm, IID_IStorage, pStgIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// since we are unmarshalling in the same process, the RH should go away.
|
|
hres = CoUnmarshalInterface(pStm, IID_IStorage, (LPVOID FAR*)&pStgOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
|
|
// make sure the interface pointers are identical
|
|
if (pStgIn != pStgOut)
|
|
OUTPUT("WARNING: CoUnmarshalInterface Local...ptrs dont match\n")
|
|
else
|
|
OUTPUT (" - CoUnmarshalInterface OK\n");
|
|
|
|
// release it and make sure it does not go away - refcnt > 0
|
|
ulRefCnt = pStgOut->Release();
|
|
pStgOut = NULL;
|
|
TEST_FAILED(ulRefCnt == 0, "pStgOut RefCnt is not zero");
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// the RH should have gone away, and we should have only the original
|
|
// refcnt from creation left on the object.
|
|
VerifyObjRefCnt(pStgIn, 1);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
if (pStgIn)
|
|
{
|
|
ulRefCnt = pStgIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStgIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStgOut)
|
|
{
|
|
ulRefCnt = pStgOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStgOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStm RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestMarshalStorage");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_NORMAL, MSHCTX_DIFFERENTMACHINE
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestStorageInterfaceDiffMachine(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt = 0;
|
|
IStorage *pStgIn = NULL;
|
|
IStorage *pStgOut = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestStorageInterfaceDiffMachine\n");
|
|
|
|
// create a docfile
|
|
hres = StgCreateDocfile(L"foo.bar",
|
|
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
|
|
0, &pStgIn);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateDocfile failed\n")
|
|
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
hres = CoMarshalInterface(pStm, IID_IStorage, pStgIn,
|
|
MSHCTX_DIFFERENTMACHINE, 0,
|
|
MSHLFLAGS_NORMAL);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
VerifyRHRefCnt(pStgIn, 1);
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IStorage, (LPVOID FAR*)&pStgOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(pStgIn, 0);
|
|
|
|
// release them
|
|
ulRefCnt = pStgOut->Release();
|
|
pStgOut = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
ulRefCnt = pStgIn->Release();
|
|
pStgIn = NULL;
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
if (pStgIn)
|
|
{
|
|
ulRefCnt = pStgIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStgIn RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStgOut)
|
|
{
|
|
ulRefCnt = pStgOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStgOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pStm RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestStorageInterfaceDiffMachine");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test REMOTE interface MSHLFLAGS_NORMAL, MSHCTX_DIFFERENTMACHINE
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestRemoteInterfaceDiffMachine(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestRemoteInterfaceDifferentMachine\n");
|
|
|
|
// Create an IClassFactory Interface.
|
|
DWORD grfContext=CLSCTX_LOCAL_SERVER; // handler/server/local server
|
|
hres = CoGetClassObject(CLSID_Balls,
|
|
grfContext,
|
|
NULL, // pvReserved
|
|
IID_IClassFactory,
|
|
(void **)&pICF);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetClassObject failed\n")
|
|
TEST_FAILED_EXIT((pICF == NULL), "CoGetClassObject failed\n")
|
|
VerifyRHRefCnt((IUnknown *)pICF, 1);
|
|
OUTPUT (" - Aquired Remote Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// note, since pICF is a class object, it has special super secret
|
|
// behaviour to make it go away. create an instance, release the
|
|
// class object, then release the instance.
|
|
|
|
hres = pICF->CreateInstance(NULL, IID_IUnknown, (void **)&punkIn);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CreateInstance failed\n")
|
|
TEST_FAILED_EXIT((punkIn == NULL), "CreateInstance failed\n")
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Created Instance.\n");
|
|
|
|
// release class object
|
|
ulRefCnt = pICF->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "pICF RefCnt not zero\n");
|
|
// VerifyRHRefCnt((IUnknown *)pICF, 0);
|
|
pICF = NULL;
|
|
OUTPUT (" - Released Class Object.\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
MSHCTX_DIFFERENTMACHINE, 0,
|
|
MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// unmarshal the interface. should get the same proxy back.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 2);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..1st Remote Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
|
|
|
|
// release the interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestRemoteInterfaceDiffMachine");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test LOCAL interface MSHLFLAGS_NORMAL, MSHCTX_DIFFERENTMACHINE
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
BOOL TestLocalInterfaceDiffMachine(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
LPCLASSFACTORY pICF = NULL;
|
|
ULONG ulRefCnt;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestLocalInterfaceDifferentMachine\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
MSHCTX_DIFFERENTMACHINE, 0,
|
|
MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// unmarshal the interface. should get the same proxy back.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
|
|
|
|
// release the interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
return TestResult(RetVal, "TestLocalInterfaceDiffMachine");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test NOPING with MSHLFLAGS NORMAL, TABLEWEAK and TABLESTRONG
|
|
//
|
|
// CodeWork: ensure SORF_FLAG set correctly.
|
|
// ensure precedence rules are followed.
|
|
// ensure protocol is followed.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
typedef struct tagNoPingThreadInfo
|
|
{
|
|
HANDLE hEvent;
|
|
IStream *pStm;
|
|
HRESULT hr;
|
|
} NoPingThreadInfo;
|
|
|
|
DWORD _stdcall NoPingThread(void *param);
|
|
|
|
BOOL TestNoPing(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt, i;
|
|
IUnknown *punkOut = NULL;
|
|
IUnknown *punkIn = NULL;
|
|
IUnknown *punk[5] = {NULL, NULL, NULL, NULL, NULL};
|
|
NoPingThreadInfo npInfo;
|
|
DWORD dwThrdId = 0;
|
|
HANDLE hThrd;
|
|
IMarshal *pIM = NULL;
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestNoPing\n");
|
|
|
|
punkIn = GetTestUnk();
|
|
TEST_FAILED_EXIT((punkIn == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punkIn, 1);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// marshal it NORMAL, TABLEWEAK and TABLESTRONG with the NOPING flag
|
|
// set, and unmarshal each in the server apartment.
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
0, 0, (i | MSHLFLAGS_NOPING));
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
|
|
// verify the marshal format
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = VerifyOBJREFFormat(pStm, (i | MSHLFLAGS_NOPING));
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
|
|
|
|
// unmarshal the interface. should get the same proxy back.
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoUnmarshalInterface(pStm, IID_IUnknown, (LPVOID FAR*)&punkOut);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoUnmarshalInterface failed\n")
|
|
|
|
|
|
// make sure the interface pointers are identical
|
|
if (punkIn != punkOut)
|
|
TEST_FAILED_EXIT(TRUE, "Interface ptrs dont match..1st Local Unmarshal\n")
|
|
OUTPUT (" - CoUnmarshalInterface OK.\n");
|
|
|
|
// check the refcnt on the stdid
|
|
if (i == 0)
|
|
{
|
|
// normal case, stdid should have been cleaned up
|
|
VerifyRHRefCnt(punkIn, 0);
|
|
}
|
|
else
|
|
{
|
|
// table case, stdid should still exist
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
}
|
|
|
|
// release the interface
|
|
ulRefCnt = punkOut->Release();
|
|
punkOut = NULL;
|
|
|
|
TEST_FAILED_EXIT(ulRefCnt == 0, "punkOut RefCnt is zero\n");
|
|
VerifyRHRefCnt(punkIn, (i == 0) ? 0 : 1);
|
|
OUTPUT (" - Release OK\n");
|
|
|
|
if (i > 0)
|
|
{
|
|
// need to release marshal data on table marshaled interfaces
|
|
// reset the stream
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED_EXIT(FAILED(hres), "ReleaseMarshalData failed\n")
|
|
}
|
|
|
|
// reset the stream
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
}
|
|
|
|
|
|
// check the precedence rules
|
|
|
|
// Whatever an interface is first marshaled as is what sets the
|
|
// PING / NOPING flags. Marshal first as normal then noping and
|
|
// expect a normal 2nd marshal. Then marshal first as noping then
|
|
// normal and expect a noping 2nd marshal.
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
DWORD mshlflags1 = (i==0) ? MSHLFLAGS_NORMAL : MSHLFLAGS_NOPING;
|
|
DWORD mshlflags2 = (i==0) ? MSHLFLAGS_NOPING : MSHLFLAGS_NORMAL;
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
0, 0, mshlflags1);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// verify the marshal format
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = VerifyOBJREFFormat(pStm, mshlflags1);
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
|
|
|
|
// marshal it again, with the opposite flags then check the value
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
0, 0, mshlflags2);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punkIn, 1);
|
|
|
|
// verify the marshal format
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = VerifyOBJREFFormat(pStm, mshlflags1);
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
|
|
// release the marshaled data
|
|
hres = CoDisconnectObject(punkIn, 0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoDisconnectObject failed\n")
|
|
OUTPUT (" - CoDisconnectObject OK.\n");
|
|
|
|
// reset the stream
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
|
|
|
|
// check CoGetStandardMarshal.
|
|
hres = CoGetStandardMarshal(IID_IUnknown, punkIn, 0, 0,
|
|
mshlflags1, &pIM);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoGetStandardMarshal failed\n")
|
|
OUTPUT (" - CoGetStandardMarshal OK.\n");
|
|
|
|
// Marshal the interface into the stream
|
|
hres = pIM->MarshalInterface(pStm, IID_IUnknown, punkIn,
|
|
0, 0, mshlflags2);
|
|
TEST_FAILED_EXIT(FAILED(hres), "pIM->MarshalInterface failed\n")
|
|
OUTPUT (" - pIM->MarshalInterface OK.\n");
|
|
|
|
// verify the marshal format
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
hres = VerifyOBJREFFormat(pStm, mshlflags1);
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
|
|
// release the IMarshal
|
|
pIM->Release();
|
|
|
|
// release the marshal data
|
|
hres = CoDisconnectObject(punkIn, 0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoDisconnectObject failed\n")
|
|
OUTPUT (" - CoDisconnectObject OK.\n");
|
|
|
|
// reset the stream
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
}
|
|
|
|
|
|
|
|
// marshal 3 objects, NORMAL, TABLEWEAK, and TABLESTRONG, then
|
|
// pass the stream to another apartment and unmarshal them.
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
punk[i] = GetTestUnk();
|
|
TEST_FAILED_EXIT((punk[i] == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punk[i], 1);
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punk[i],
|
|
0, 0, (i | MSHLFLAGS_NOPING));
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punk[i], 1);
|
|
}
|
|
|
|
// marshal one more object, NOPING
|
|
punk[i] = GetTestUnk();
|
|
TEST_FAILED_EXIT((punk[i] == NULL), "new CTestUnk failed\n")
|
|
VerifyObjRefCnt(punk[i], 1);
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punk[i],
|
|
0, 0, (MSHLFLAGS_NORMAL | MSHLFLAGS_NOPING));
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punk[i], 1);
|
|
|
|
|
|
// marshal a second interface on the same object as PING
|
|
hres = CoMarshalInterface(pStm, IID_IParseDisplayName, punk[i],
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punk[i], 2);
|
|
|
|
|
|
// pass one more interface that does custom marshaling delegating
|
|
// to standard marshaling and replacing the PING option with NOPING.
|
|
i++;
|
|
punk[i] = (IUnknown *) new CTestUnkMarshal();
|
|
TEST_FAILED_EXIT((punk[i] == NULL), "new CTestUnkMarshal failed\n")
|
|
VerifyObjRefCnt(punk[i], 1);
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punk[i],
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punk[i], 2);
|
|
|
|
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
for (i=0; i<6; i++)
|
|
{
|
|
// verify the marshal format
|
|
hres = VerifyOBJREFFormat(pStm, (i | MSHLFLAGS_NOPING));
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
}
|
|
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// create thread and wait for it to complete
|
|
npInfo.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
npInfo.pStm = pStm;
|
|
npInfo.hr = S_OK;
|
|
|
|
hThrd = CreateThread(NULL, 0, NoPingThread,
|
|
&npInfo, 0, &dwThrdId);
|
|
if (hThrd)
|
|
{
|
|
// wait for thread to register run to completetion. Note that
|
|
// we dont have to provide a message pump because with the NOPING
|
|
// flag set the other thread should never call back to get or release
|
|
// any references.
|
|
|
|
WaitForSingleObject(npInfo.hEvent, 0xffffffff);
|
|
Sleep(0);
|
|
CloseHandle(npInfo.hEvent);
|
|
|
|
// close the thread handle
|
|
CloseHandle(hThrd);
|
|
}
|
|
|
|
// cleanup the leftover objects.
|
|
for (i=0; i<5; i++)
|
|
{
|
|
hres = CoDisconnectObject(punk[i], 0);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoDisconnectObject failed\n")
|
|
OUTPUT (" - CoDisconnectObject OK.\n");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkOut)
|
|
{
|
|
ulRefCnt = punkOut->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkOut RefCnt not zero\n");
|
|
}
|
|
|
|
if (punkIn)
|
|
{
|
|
ulRefCnt = punkIn->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punkIn RefCnt not zero\n");
|
|
}
|
|
|
|
for (i=0; i<5; i++)
|
|
{
|
|
if (punk[i] != NULL)
|
|
{
|
|
ulRefCnt = punk[i]->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punk[i] RefCnt not zero\n");
|
|
}
|
|
}
|
|
|
|
return TestResult(RetVal, "TestNoPing");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Thread SubRoutine for testing NOPING.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall NoPingThread(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
IUnknown *punk = NULL;
|
|
ULONG i = 0;
|
|
|
|
NoPingThreadInfo *npInfo = (NoPingThreadInfo *) param;
|
|
OUTPUT (" - NoPingThread Start\n");
|
|
|
|
HRESULT hRes = CoInitializeEx(NULL, gInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "NoPingThread CoInitialize failed\n")
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
IStream *pStm = CreateMemStm(600, NULL);
|
|
if (pStm == NULL)
|
|
{
|
|
TEST_FAILED((pStm == NULL), "CreateMemStm failed\n")
|
|
hRes = E_OUTOFMEMORY;
|
|
}
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// unmarshal the interfaces
|
|
for (i=0; i<6; i++)
|
|
{
|
|
|
|
REFIID riid = (i==4) ? IID_IParseDisplayName : IID_IUnknown;
|
|
|
|
hRes = CoUnmarshalInterface(npInfo->pStm, riid, (void **)&punk);
|
|
TEST_FAILED(FAILED(hRes), "NoPingThread CoUnmarshalInterface failed\n")
|
|
OUTPUT(" - NoPingThread CoUnmarshalInterface done\n");
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
if (i==3)
|
|
{
|
|
// try remarshaling NOPING client as normal. Should end up
|
|
// as NOPING.
|
|
|
|
hRes = CoMarshalInterface(pStm, IID_IUnknown, punk,
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED(FAILED(hRes), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
|
|
// reset the stream seek ptr
|
|
hRes = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED(FAILED(hRes), "Seek on shared stream failed\n")
|
|
|
|
// verify the marshal format
|
|
hRes = VerifyOBJREFFormat(pStm, MSHLFLAGS_NOPING);
|
|
TEST_FAILED(FAILED(hRes), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
}
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
OUTPUT(" - NoPingThread Release done\n");
|
|
}
|
|
}
|
|
|
|
// uninit OLE
|
|
CoUninitialize();
|
|
}
|
|
|
|
if (pStm)
|
|
{
|
|
// release stream we created above
|
|
pStm->Release();
|
|
}
|
|
|
|
OUTPUT (" - NoPingThread Exit\n");
|
|
npInfo->hr = hRes;
|
|
SetEvent(npInfo->hEvent);
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// test marshaling between apartments in the same process using
|
|
// MSHLFLAGS_NORMAL, MSHLFLAGS_TABLEWEAK, and MSHLFLAGS_TABLESTRONG
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
typedef struct tagCrossThreadCallInfo
|
|
{
|
|
HANDLE hEvent;
|
|
IStream *pStm;
|
|
DWORD dwInitFlag;
|
|
DWORD dwThreadId;
|
|
HRESULT hr;
|
|
} CrossThreadCallInfo;
|
|
|
|
|
|
DWORD _stdcall CrossThreadCalls(void *param);
|
|
DWORD _stdcall CrossThreadLoops(void *param);
|
|
DWORD _stdcall CrossThreadActivate(void *param);
|
|
|
|
|
|
BOOL TestCrossThread(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
LPSTREAM pStm = NULL;
|
|
ULONG ulRefCnt, i, j;
|
|
IUnknown *punk[3] = {NULL, NULL, NULL};
|
|
IUnknown *pUnk;
|
|
ILoop *pLocalLoop = NULL;
|
|
CrossThreadCallInfo ctInfo;
|
|
DWORD dwThrdId = 0;
|
|
HANDLE hThrd;
|
|
DWORD mshlflags[3] = {MSHLFLAGS_NORMAL,
|
|
MSHLFLAGS_TABLEWEAK,
|
|
MSHLFLAGS_TABLESTRONG};
|
|
|
|
DWORD dwInitFlags[4] = {COINIT_APARTMENTTHREADED,
|
|
COINIT_APARTMENTTHREADED,
|
|
COINIT_MULTITHREADED,
|
|
COINIT_MULTITHREADED};
|
|
|
|
|
|
LARGE_INTEGER large_int;
|
|
LISet32(large_int, 0);
|
|
|
|
OUTPUT ("Starting TestCrossThread\n");
|
|
|
|
// Create a shared memory stream for the marshaled interface
|
|
pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
for (j=0; j<4; j++)
|
|
{
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
// marshal an interface NORMAL, TABLEWEAK and TABLESTRONG
|
|
// and unmarshal each in another apartment.
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
punk[i] = GetTestUnk();
|
|
TEST_FAILED_EXIT((punk[i] == NULL), "new CTestUnkCube failed\n")
|
|
VerifyObjRefCnt(punk[i], 1);
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_ICube, punk[i],
|
|
0, 0, mshlflags[i]);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(punk[i], 1);
|
|
}
|
|
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
hres = VerifyOBJREFFormat(pStm, mshlflags[i]);
|
|
TEST_FAILED_EXIT(FAILED(hres), "VerifyOBJREFFormat failed\n")
|
|
OUTPUT (" - VerifyOBJREFFormat OK.\n");
|
|
}
|
|
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
|
|
// create thread and wait for it to complete
|
|
ctInfo.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ctInfo.pStm = pStm;
|
|
ctInfo.dwInitFlag = dwInitFlags[j];
|
|
ctInfo.dwThreadId = GetCurrentThreadId();
|
|
ctInfo.hr = S_OK;
|
|
|
|
RunThread(&ctInfo, ctInfo.hEvent, CrossThreadCalls);
|
|
CloseHandle(ctInfo.hEvent);
|
|
|
|
|
|
// cleanup the leftover objects.
|
|
for (i=0; i<3; i++)
|
|
{
|
|
hres = CoDisconnectObject(punk[i], 0);
|
|
punk[i] = NULL;
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoDisconnectObject failed\n")
|
|
OUTPUT (" - CoDisconnectObject OK.\n");
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Now test out doing activation from different apartments.
|
|
// create thread and wait for it to complete
|
|
|
|
for (j=0; j<2; j++)
|
|
{
|
|
ctInfo.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ctInfo.pStm = NULL;
|
|
ctInfo.dwInitFlag = dwInitFlags[j];
|
|
ctInfo.dwThreadId = GetCurrentThreadId();
|
|
ctInfo.hr = S_OK;
|
|
|
|
RunThread(&ctInfo, ctInfo.hEvent, CrossThreadActivate);
|
|
CloseHandle(ctInfo.hEvent);
|
|
|
|
// create an interface
|
|
hres = CoCreateInstance(CLSID_LoopSrv, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ILoop, (void **)&pLocalLoop);
|
|
TEST_FAILED(FAILED(hres), "CoCreateInstance Second failed\n")
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
pLocalLoop->Release();
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Now test doing nested calls between apartments.
|
|
#if 0
|
|
for (j=0; j<2; j++)
|
|
{
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
pUnk = GetTestUnk();
|
|
TEST_FAILED_EXIT((pUnk == NULL), "new GetTestUnk failed\n")
|
|
VerifyObjRefCnt(pUnk, 1);
|
|
|
|
// Marshal the interface into the stream
|
|
hres = CoMarshalInterface(pStm, IID_ILoop, pUnk,
|
|
0, 0, MSHLFLAGS_NORMAL);
|
|
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK.\n");
|
|
VerifyRHRefCnt(pUnk, 1);
|
|
|
|
// reset the stream seek ptr
|
|
hres = pStm->Seek(large_int, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
|
|
|
|
ctInfo.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ctInfo.pStm = pStm;
|
|
ctInfo.dwInitFlag = dwInitFlags[j];
|
|
ctInfo.dwThreadId = GetCurrentThreadId();
|
|
ctInfo.hr = S_OK;
|
|
|
|
RunThread(&ctInfo, ctInfo.hEvent, CrossThreadLoops);
|
|
CloseHandle(ctInfo.hEvent);
|
|
|
|
pUnk->Release();
|
|
}
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
Cleanup:
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
|
|
// Dump interfaces we are done with
|
|
if (pStm)
|
|
{
|
|
ulRefCnt = pStm->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "Stream RefCnt not zero\n");
|
|
}
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (punk[i] != NULL)
|
|
{
|
|
ulRefCnt = punk[i]->Release();
|
|
TEST_FAILED(ulRefCnt != 0, "punk[i] RefCnt not zero\n");
|
|
}
|
|
}
|
|
|
|
return TestResult(RetVal, "TestCrossThread");
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Thread SubRoutine for testing CROSSTHREAD calls.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall CrossThreadCalls(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ICube *pCube = NULL;
|
|
IOleWindow *pIOW = NULL;
|
|
IAdviseSink *pIAS = NULL;
|
|
ULONG i = 0;
|
|
|
|
// get the execution parameters
|
|
CrossThreadCallInfo *ctInfo = (CrossThreadCallInfo *) param;
|
|
OUTPUT (" - CrossThreadCalls Start\n");
|
|
|
|
// initialize COM
|
|
HRESULT hRes = CoInitializeEx(NULL, ctInfo->dwInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CrossThreadCalls CoInitializeEx failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// unmarshal the interfaces
|
|
for (i=0; i<3; i++)
|
|
{
|
|
hRes = CoUnmarshalInterface(ctInfo->pStm, IID_ICube, (void **)&pCube);
|
|
TEST_FAILED(FAILED(hRes), "CrossThread CoUnmarshalInterface failed\n")
|
|
OUTPUT(" - CrossThread CoUnmarshalInterface done\n");
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// test a synchronous method call between apartments
|
|
// (also checks the lid & tid)
|
|
|
|
UUID lidCaller;
|
|
CoGetCurrentLogicalThreadId(&lidCaller);
|
|
hRes = pCube->SimpleCall(GetCurrentProcessId(),
|
|
GetCurrentThreadId(),
|
|
lidCaller);
|
|
TEST_FAILED(FAILED(hRes), "pCube->SimpleCall failed\n")
|
|
OUTPUT(" - Synchronous call done\n");
|
|
|
|
// test an input-sync method call between apartments
|
|
hRes = pCube->QueryInterface(IID_IOleWindow, (void **)&pIOW);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
HWND hWnd;
|
|
hRes = pIOW->GetWindow(&hWnd);
|
|
|
|
// input sync is only allowed between two apartment
|
|
// threaded apartments.
|
|
if (ctInfo->dwInitFlag == gInitFlag)
|
|
{
|
|
TEST_FAILED(FAILED(hRes), "pIOW->GetWindow failed\n");
|
|
}
|
|
else
|
|
{
|
|
TEST_FAILED(SUCCEEDED(hRes), "pIOW->GetWindow should have failed\n");
|
|
}
|
|
|
|
pIOW->Release();
|
|
OUTPUT(" - Input-Synchronous call done\n");
|
|
}
|
|
|
|
|
|
// test an async method call between apartments
|
|
hRes = pCube->QueryInterface(IID_IAdviseSink, (void **)&pIAS);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// no return code to check
|
|
pIAS->OnViewChange(1,2);
|
|
pIAS->Release();
|
|
OUTPUT(" - ASynchronous call done\n");
|
|
}
|
|
|
|
// release the object
|
|
pCube->Release();
|
|
pCube = NULL;
|
|
OUTPUT(" - CrossThread Calls and Release done\n");
|
|
}
|
|
}
|
|
|
|
// uninit OLE
|
|
CoUninitialize();
|
|
}
|
|
|
|
OUTPUT (" - CrossThreadCalls Exit\n");
|
|
ctInfo->hr = hRes;
|
|
|
|
// signal the other thread we are done.
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
PostThreadMessage(ctInfo->dwThreadId, WM_QUIT, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetEvent(ctInfo->hEvent);
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Thread SubRoutine for testing CROSSTHREAD activation
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall CrossThreadActivate(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ILoop *pLocalLoop = NULL;
|
|
|
|
// get the execution parameters
|
|
CrossThreadCallInfo *ctInfo = (CrossThreadCallInfo *) param;
|
|
OUTPUT (" - CrossThreadActivate Start\n");
|
|
|
|
// initialize COM
|
|
HRESULT hRes = CoInitializeEx(NULL, ctInfo->dwInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CrossThreadActivate CoInitializeEx failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// create an interface
|
|
hRes = CoCreateInstance(CLSID_LoopSrv, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_ILoop, (void **)&pLocalLoop);
|
|
TEST_FAILED(FAILED(hRes), "CoCreateInstance First failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
pLocalLoop->Release();
|
|
}
|
|
|
|
// uninit OLE
|
|
CoUninitialize();
|
|
}
|
|
|
|
OUTPUT (" - CrossThreadActivate Exit\n");
|
|
ctInfo->hr = hRes;
|
|
|
|
// signal the other thread we are done.
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
PostThreadMessage(ctInfo->dwThreadId, WM_QUIT, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetEvent(ctInfo->hEvent);
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Thread SubRoutine for testing CROSSTHREAD calls.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
DWORD _stdcall CrossThreadLoops(void *param)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
ILoop *pLoop = NULL;
|
|
IUnknown *punk = NULL;
|
|
ILoop *pLoopLocal = NULL;
|
|
|
|
// get the execution parameters
|
|
CrossThreadCallInfo *ctInfo = (CrossThreadCallInfo *) param;
|
|
OUTPUT (" - CrossThreadLoops Start\n");
|
|
|
|
// initialize COM
|
|
HRESULT hRes = CoInitializeEx(NULL, ctInfo->dwInitFlag);
|
|
TEST_FAILED(FAILED(hRes), "CrossThreadLoops CoInitializeEx failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
punk = GetTestUnk();
|
|
punk->QueryInterface(IID_ILoop, (void **)&pLoopLocal);
|
|
punk->Release();
|
|
|
|
// unmarshal the interface
|
|
hRes = CoUnmarshalInterface(ctInfo->pStm, IID_ILoop, (void **)&pLoop);
|
|
TEST_FAILED(FAILED(hRes), "CrossThreadLoop CoUnmarshalInterface failed\n")
|
|
OUTPUT(" - CrossThreadLoop CoUnmarshalInterface done\n");
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
// test nested synchronous method calls between apartments
|
|
|
|
hRes = pLoop->Init(pLoopLocal);
|
|
TEST_FAILED(FAILED(hRes), "pLoop->Init failed\n")
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = pLoop->Loop(5);
|
|
TEST_FAILED(FAILED(hRes), "pLoop->Loop failed\n")
|
|
|
|
hRes = pLoop->Uninit();
|
|
TEST_FAILED(FAILED(hRes), "pLoop->Uninit failed\n")
|
|
}
|
|
|
|
pLoop->Release();
|
|
pLoop = NULL;
|
|
|
|
OUTPUT(" - CrossThreadLoop Calls and Release done\n");
|
|
}
|
|
|
|
// uninit OLE
|
|
CoUninitialize();
|
|
}
|
|
|
|
OUTPUT (" - CrossThreadLoops Exit\n");
|
|
ctInfo->hr = hRes;
|
|
|
|
// signal the other thread we are done.
|
|
if (gInitFlag == COINIT_APARTMENTTHREADED)
|
|
{
|
|
PostThreadMessage(ctInfo->dwThreadId, WM_QUIT, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetEvent(ctInfo->hEvent);
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Test calling CoGetPSClsid and CoRegisterPSClsid
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestPSClsid(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes;
|
|
CLSID clsidOriginal, clsidNew;
|
|
|
|
OUTPUT ("Starting TestPSClsid\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// get the PSClsid that is currently registered for this interface.
|
|
|
|
hRes = CoGetPSClsid(IID_IViewObject, &clsidOriginal);
|
|
TEST_FAILED(FAILED(hRes), "Failed 1st CoGetPSClsid\n");
|
|
OUTPUT (" - Done 1st CoGetPSClsid\n");
|
|
|
|
// Set a new PSClsid for this interface for this process. Note that
|
|
// if we have used the interface before, we will get an error back,
|
|
// otherwise, this will succeed.
|
|
|
|
hRes = CoRegisterPSClsid(IID_IViewObject, CLSID_Balls);
|
|
TEST_FAILED(FAILED(hRes), "Failed 1st CoGRegisterPSClsid\n");
|
|
OUTPUT (" - Done 1st CoRegisterPSClsid\n");
|
|
|
|
// now get the PSClsid that is registered for this interface. This
|
|
// should match the value we just passed in.
|
|
|
|
hRes = CoGetPSClsid(IID_IViewObject, &clsidNew);
|
|
TEST_FAILED(FAILED(hRes), "Failed 2nd CoGetPSClsid\n");
|
|
OUTPUT (" - Done 2nd CoGetPSClsid\n");
|
|
|
|
if (memcmp(&clsidNew, &CLSID_Balls, sizeof(CLSID)))
|
|
{
|
|
TEST_FAILED(TRUE, "Failed Compare of CLSIDs\n");
|
|
}
|
|
|
|
// now try to register it again. This should fail since it has
|
|
// already been registered.
|
|
|
|
hRes = CoRegisterPSClsid(IID_IViewObject, clsidOriginal);
|
|
TEST_FAILED(FAILED(hRes), "Failed 2nd CoGRegisterPSClsid\n");
|
|
OUTPUT (" - Done 2nd CoRegisterPSClsid\n");
|
|
|
|
// now get the PSClsid that is registered for this interface. This
|
|
// should match the value we just passed in.
|
|
|
|
hRes = CoGetPSClsid(IID_IViewObject, &clsidNew);
|
|
TEST_FAILED(FAILED(hRes), "Failed 3rd CoGetPSClsid\n");
|
|
OUTPUT (" - Done 3rd CoGetPSClsid\n");
|
|
|
|
if (memcmp(&clsidNew, &clsidOriginal, sizeof(CLSID)))
|
|
{
|
|
TEST_FAILED(TRUE, "Failed 2nd Compare of CLSIDs\n");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
return TestResult(RetVal, "TestPSClsid");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// Test calling CoGetPSClsid for a LONG IID/PSCLSID pair.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestPSClsid2(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
CLSID clsidOriginal;
|
|
|
|
OUTPUT ("Starting TestPSClsid2\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// get the PSClsid that is currently registered for this interface.
|
|
hRes = CoGetPSClsid(IID_IViewObject, &clsidOriginal);
|
|
TEST_FAILED(FAILED(hRes), "Failed 1st CoGetPSClsid\n");
|
|
OUTPUT (" - Done 1st CoGetPSClsid\n");
|
|
|
|
if (!IsEqualGUID(clsidOriginal, CLSID_OLEPSFACTORY))
|
|
{
|
|
TEST_FAILED(FAILED(hRes), "CoGetPSClsid returned wrong value\n");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
return TestResult(RetVal, "TestPSClsid2");
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// TestGetIIDFromMI
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL TestGetIIDFromMI(void)
|
|
{
|
|
BOOL RetVal = TRUE;
|
|
HRESULT hres;
|
|
IUnknown *punkIn = NULL;
|
|
IID iid;
|
|
|
|
OUTPUT ("Starting TestGetIIDFromMI\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
ULARGE_INTEGER ulSeekEnd;
|
|
LARGE_INTEGER lSeekStart;
|
|
LISet32(lSeekStart, 0);
|
|
|
|
IStream *pStm = CreateMemStm(600, NULL);
|
|
TEST_FAILED_EXIT((pStm == NULL), "CreateMemStm failed\n")
|
|
VerifyObjRefCnt((IUnknown *)pStm, 1);
|
|
|
|
punkIn = GetTestUnk();
|
|
|
|
hres = CoMarshalInterface(pStm, IID_IUnknown, punkIn, 0, NULL, MSHLFLAGS_NORMAL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "CoMarshalInterface failed\n")
|
|
OUTPUT (" - CoMarshalInterface OK\n");
|
|
|
|
// go back to begining
|
|
hres = pStm->Seek(lSeekStart, STREAM_SEEK_SET, NULL);
|
|
TEST_FAILED_EXIT(FAILED(hres), "Seek on shared stream failed\n")
|
|
OUTPUT (" - Seek Start OK\n");
|
|
|
|
#if 0 // BUGBUG: RICKHI
|
|
// get the IID from the stream, and ensure it matches the IID we
|
|
// marshaled. Also, ensure the stream is left where it was. This
|
|
// is accomplished by calling CRMD on the stream.
|
|
|
|
hres = CoGetIIDFromMarshaledInterface(pStm, &iid);
|
|
TEST_FAILED(FAILED(hres), "CoGetIIDFromMarshaledInterface failed\n")
|
|
OUTPUT (" - CoGetIIDFromMarshaledInterface Done\n");
|
|
|
|
if (!IsEqualIID(IID_IUnknown, iid))
|
|
{
|
|
TEST_FAILED(TRUE, "IID read does not match IID marshaled\n")
|
|
}
|
|
#endif
|
|
// release the marshaled interface
|
|
hres = CoReleaseMarshalData(pStm);
|
|
TEST_FAILED(FAILED(hres), "CoReleaseMarshalData failed\n")
|
|
OUTPUT (" - CoReleaseMarshalData Done\n");
|
|
|
|
// ----------------------------------------------------------------------
|
|
Cleanup:
|
|
|
|
if (punkIn)
|
|
{
|
|
punkIn->Release();
|
|
punkIn = NULL;
|
|
}
|
|
|
|
OUTPUT (" - Test Complete. Doing Cleanup\n");
|
|
return TestResult(RetVal, "TestGetIIDFromMI");
|
|
}
|
|
|