summaryrefslogtreecommitdiffstats
path: root/private/oleauto/tests/disptest
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleauto/tests/disptest')
-rw-r--r--private/oleauto/tests/disptest/cbind.cpp393
-rw-r--r--private/oleauto/tests/disptest/cbstr.cpp313
-rw-r--r--private/oleauto/tests/disptest/ccollect.cpp422
-rw-r--r--private/oleauto/tests/disptest/cdatecnv.cpp491
-rw-r--r--private/oleauto/tests/disptest/cdisptst.def13
-rw-r--r--private/oleauto/tests/disptest/cdisptst.r329
-rw-r--r--private/oleauto/tests/disptest/cdisptst.rc87
-rw-r--r--private/oleauto/tests/disptest/cearly.cpp319
-rw-r--r--private/oleauto/tests/disptest/cinvex.cpp156
-rw-r--r--private/oleauto/tests/disptest/cinvref.cpp545
-rw-r--r--private/oleauto/tests/disptest/cinvsary.cpp641
-rw-r--r--private/oleauto/tests/disptest/cinvval.cpp571
-rw-r--r--private/oleauto/tests/disptest/clsid.h31
-rw-r--r--private/oleauto/tests/disptest/cnls.cpp421
-rw-r--r--private/oleauto/tests/disptest/csarray.cpp371
-rw-r--r--private/oleauto/tests/disptest/ctime.cpp266
-rw-r--r--private/oleauto/tests/disptest/cvariant.cpp1617
-rw-r--r--private/oleauto/tests/disptest/cwbstr.cpp320
-rw-r--r--private/oleauto/tests/disptest/disptest.cpp316
-rw-r--r--private/oleauto/tests/disptest/disptest.h63
-rw-r--r--private/oleauto/tests/disptest/guid.c56
-rw-r--r--private/oleauto/tests/disptest/macmain.cpp1447
-rw-r--r--private/oleauto/tests/disptest/macmain.h191
-rw-r--r--private/oleauto/tests/disptest/makefile552
-rw-r--r--private/oleauto/tests/disptest/makefile.mpw181
-rw-r--r--private/oleauto/tests/disptest/misc.cpp271
-rw-r--r--private/oleauto/tests/disptest/oleguids.c51
-rw-r--r--private/oleauto/tests/disptest/oleguids.h37
-rw-r--r--private/oleauto/tests/disptest/pch.cpp5
-rw-r--r--private/oleauto/tests/disptest/resource.h41
-rw-r--r--private/oleauto/tests/disptest/src2mac.mak228
-rw-r--r--private/oleauto/tests/disptest/suite.cpp590
-rw-r--r--private/oleauto/tests/disptest/timer.c29
-rw-r--r--private/oleauto/tests/disptest/tstsuite.h119
34 files changed, 11483 insertions, 0 deletions
diff --git a/private/oleauto/tests/disptest/cbind.cpp b/private/oleauto/tests/disptest/cbind.cpp
new file mode 100644
index 000000000..6b5a611cd
--- /dev/null
+++ b/private/oleauto/tests/disptest/cbind.cpp
@@ -0,0 +1,393 @@
+/***
+*cbind.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CBindSuite test object.
+*
+*Revision History:
+*
+* [00] 11-Nov-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+#include "clsid.h"
+
+
+extern OLECHAR FAR* g_szCSArray;
+extern OLECHAR FAR* g_szCDispTst;
+
+struct TEST {
+ HRESULT (*pfnTest)(void);
+ OLECHAR FAR* szName;
+};
+
+HRESULT BindTest1();
+HRESULT BindTest2();
+HRESULT BindTest3();
+HRESULT GetObject1();
+HRESULT GetObject2();
+HRESULT GetObject3();
+
+static TEST rgtest[] = {
+ { BindTest1, OLESTR("binding test #1") }
+ , { BindTest2, OLESTR("binding test #2") }
+ , { BindTest3, OLESTR("binding test #3") }
+ , { GetObject1, OLESTR("GetObject test #1") }
+ , { GetObject2, OLESTR("GetObject test #2") }
+ , { GetObject3, OLESTR("GetObject test #3") }
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CBindSuite)
+
+SUITE_IUNKNOWN_IMPL(CBindSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CBindSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Object binding"), pbstr);
+}
+
+STDMETHODIMP
+CBindSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("bind.log"), pbstr);
+}
+
+STDMETHODIMP
+CBindSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+CBindSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+/***
+*HRESULT CBindSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CBindSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CBindSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest();
+}
+
+// Create and isntance of our test and sample objects, QI them to
+// IDispatch, and then immediately release.
+//
+HRESULT
+BindTest1()
+{
+ IUnknown FAR* punk;
+ IDispatch FAR* pdisp;
+
+static struct {
+ const CLSID FAR* pclsid;
+ char FAR* psz;
+} rg[] = {
+#define DAT(X) {&X, #X}
+ DAT(CLSID_CPoly)
+ , DAT(CLSID_CPoly2)
+ , DAT(CLSID_CCalc)
+ , DAT(CLSID_SDispTst_CDispTst)
+#undef DAT
+};
+
+ for(int i = 0; i < DIM(rg); ++i){
+ DbPrintf("CoCreateInstance(%s)\n", rg[i].psz);
+ IfFailRet(
+ CoCreateInstance(
+ *rg[i].pclsid,
+ NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void FAR* FAR*)&punk));
+ DbPrintf(" QueryInterface(IID_IDispatch)\n");
+ IfFailRet(punk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp));
+ pdisp->Release();
+ punk->Release();
+ }
+ return NOERROR;
+}
+
+// bind to a new instance of the sdisptst application object, and
+// dump its typeinfos.
+
+HRESULT
+BindTest2()
+{
+ unsigned int u, ctinfo;
+ HRESULT hresult;
+ IDispatch FAR* pdisp;
+ ITypeInfo FAR* ptinfo;
+
+ IfFailGo(CreateObject(OLESTR("sdisptst.application"), &pdisp), LError0);
+
+ IfFailGo(pdisp->GetTypeInfoCount(&ctinfo), LError1);
+
+ for(u = 0; u < ctinfo; ++u){
+ IfFailGo(pdisp->GetTypeInfo(u, 0, &ptinfo), LError1);
+
+ // dump the type info
+ PrTi(ptinfo);
+ ptinfo->Release();
+ }
+
+LError1:;
+ pdisp->Release();
+
+LError0:;
+ return hresult;
+}
+
+// same as BindTest2 - but dump the typeinfo for dspcalc2.
+//
+HRESULT
+BindTest3()
+{
+ unsigned int u, ctinfo;
+ HRESULT hresult;
+ IDispatch FAR* pdisp;
+ ITypeInfo FAR* ptinfo;
+
+ IfFailGo(CreateObject(OLESTR("Dspcalc2.Application"), &pdisp), LError0);
+
+ IfFailGo(pdisp->GetTypeInfoCount(&ctinfo), LError1);
+
+ for(u = 0; u < ctinfo; ++u){
+ IfFailGo(pdisp->GetTypeInfo(u, 0, &ptinfo), LError1);
+
+ // dump the type info
+ PrTi(ptinfo);
+ ptinfo->Release();
+ }
+
+LError1:;
+ pdisp->Release();
+
+LError0:;
+ return hresult;
+}
+
+// Test GetActiveObject()
+HRESULT
+GetObject1()
+{
+ HRESULT hresult;
+ IUnknown FAR* punk;
+ IDispatch FAR* pdispApp;
+ IDispatch FAR* pdispCDispTst;
+
+ VARIANT varResult;
+ VARIANTARG rgvarg[1];
+ DISPID rgdispid[1];
+ DISPPARAMS dispparams;
+ OLECHAR FAR* rgszNames[1];
+
+#if OE_WIN16
+ // make sure the server is running first
+ if(!WinExec("sdisptst", SW_NORMAL))
+ return RESULT(E_UNEXPECTED);
+#endif
+
+ // get the active application object
+ IfFailGo(
+ GetActiveObject(CLSID_SDispTst_CAppObject, NULL, &punk),
+ LError0);
+
+ IfFailGo(
+ punk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdispApp),
+ LError1);
+
+ // invoke the NewCDispTst method on the application object to
+ // create an instance of the CDispTst object.
+
+ rgszNames[0] = OLESTR("newcdisptst");
+ IfFailGo(
+ pdispApp->GetIDsOfNames(
+ IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, rgdispid),
+ LError2);
+
+ dispparams.cArgs = 1;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgvarg = rgvarg;
+ pdispCDispTst = NULL;
+ V_VT(&rgvarg[0]) = VT_BYREF | VT_DISPATCH;
+ V_DISPATCHREF(&rgvarg[0]) = &pdispCDispTst;
+ VariantInit(&varResult);
+ IfFailGo(
+ DoInvoke(pdispApp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError2);
+
+ // invoke CDispTst::Hello(), just to make sure this is really working
+
+ rgszNames[0] = OLESTR("hello");
+ IfFailGo(
+ pdispCDispTst->GetIDsOfNames(
+ IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, rgdispid),
+ LError2);
+
+ dispparams.cArgs = 0;
+ dispparams.cNamedArgs = 0;
+ IfFailGo(
+ DoInvoke(pdispCDispTst, rgdispid[0], &dispparams, NULL, NULL, NULL),
+ LError3);
+
+ hresult = NOERROR;
+
+LError3:;
+ pdispCDispTst->Release();
+
+LError2:;
+ pdispApp->Release();
+
+LError1:;
+ punk->Release();
+
+LError0:;
+ return hresult;
+}
+
+HRESULT
+GetObject2()
+{
+ HRESULT hresult;
+ IUnknown FAR* punkCalcGet;
+ IDispatch FAR* pdispCalcGet;
+ IDispatch FAR* pdispCalcCreate;
+
+ DISPID rgdispid[1];
+ DISPPARAMS dispparams;
+ OLECHAR FAR* rgszNames[1];
+
+ // make sure the server is running
+ DbPrintf("CreateObject(\"Dispcalc.Application\",)\n");
+ IfFailGo(CreateObject(OLESTR("Dispcalc.Application"), &pdispCalcCreate),
+ LError0);
+
+#ifdef _MAC
+ // REVIEW: currently a problem with GetActiveObj on the mac
+ IfFailGo(pdispCalcCreate->QueryInterface(IID_IUnknown, (void FAR* FAR*) &punkCalcGet), LError0);
+#else
+ // get the active application object
+ DbPrintf("GetActiveObject(CLSID_CCalc,)\n");
+ IfFailGo(GetActiveObject(CLSID_CCalc, NULL, &punkCalcGet), LError1);
+#endif
+
+ DbPrintf("QueryInterface(IID_IDispatch,)\n");
+ IfFailGo(
+ punkCalcGet->QueryInterface(
+ IID_IDispatch, (void FAR* FAR*)&pdispCalcGet), LError2);
+
+ // REVIEW: set accum on the create version, and get the accum on
+ // the get version - then check to see that its the same value
+
+ DbPrintf("GetIDsOfNames(\"quit\",)\n");
+ rgszNames[0] = OLESTR("quit");
+ IfFailGo(
+ pdispCalcGet->GetIDsOfNames(IID_NULL, rgszNames, 1, 0, rgdispid),
+ LError3);
+
+ DbPrintf("Invoke(\"quit\",)\n");
+ dispparams.cArgs = 0;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgvarg = NULL;
+ IfFailGo(
+ DoInvoke(pdispCalcGet, rgdispid[0], &dispparams, NULL, NULL, NULL),
+ LError3);
+
+ hresult = NOERROR;
+
+LError3:;
+ pdispCalcGet->Release();
+
+LError2:;
+ punkCalcGet->Release();
+
+LError1:;
+#if !defined(WIN32) // BUGBUG: ole32.dll GPF is channel code...
+ // cause and identity table assertion to occur
+ pdispCalcCreate->Release();
+#endif
+
+LError0:;
+ return hresult;
+}
+
+
+// test repeatedly getting and releasing an active object
+
+HRESULT
+GetObject3()
+{
+ int i;
+ HRESULT hresult;
+ IUnknown FAR* punk;
+ IDispatch FAR* pdisp;
+
+ punk = NULL;
+ pdisp = NULL;
+
+ // make sure the server is running
+ hresult = CreateObject(OLESTR("Dispcalc.Application"), &pdisp);
+ if(hresult != NOERROR)
+ goto LError0;
+
+ // the calculator stays in memory until the quit method is invoked
+ pdisp->Release();
+ pdisp = NULL;
+
+ for(i = 0; i < 10; ++i){
+ // get the active application object
+ IfFailGo(GetActiveObject(CLSID_CCalc, NULL, &punk), LError0);
+
+ IfFailGo(
+ punk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp),
+ LError0);
+
+ punk->Release();
+ punk = NULL;
+
+ pdisp->Release();
+ pdisp = NULL;
+ }
+
+LError0:;
+ if(pdisp!=NULL)
+ pdisp->Release();
+ if(punk!=NULL)
+ punk->Release();
+
+ return hresult;
+}
+
diff --git a/private/oleauto/tests/disptest/cbstr.cpp b/private/oleauto/tests/disptest/cbstr.cpp
new file mode 100644
index 000000000..a0d2689ee
--- /dev/null
+++ b/private/oleauto/tests/disptest/cbstr.cpp
@@ -0,0 +1,313 @@
+/***
+*cbstr.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CBstrSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <limits.h>
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+
+struct TEST {
+ HRESULT (*pfnTest)(void);
+ OLECHAR FAR* szName;
+};
+
+HRESULT BstrLimits(void);
+HRESULT BstrOleprog5(void);
+HRESULT BstrOleprog8(void);
+HRESULT BstrOleprog65(void);
+HRESULT BstrOleprog234(void);
+
+static TEST rgtest[] = {
+ { BstrOleprog5, OLESTR("raid!oleprog#5") }
+#if !OE_MAC
+ , { BstrOleprog8, OLESTR("raid!oleprog#8") }
+#endif
+ , { BstrOleprog65, OLESTR("raid!oleprog#65") }
+ , { BstrOleprog234, OLESTR("raid!oleprog#234") }
+ , { BstrLimits, OLESTR("Bstr limits") }
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CBstrSuite)
+
+SUITE_IUNKNOWN_IMPL(CBstrSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CBstrSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("BSTR API"), pbstr);
+}
+
+STDMETHODIMP
+CBstrSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("bstrapi.log"), pbstr);
+}
+
+STDMETHODIMP
+CBstrSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+CBstrSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ *pbstr = SysAllocString(rgtest[iTest].szName);
+ return NOERROR;
+}
+
+/***
+*HRESULT CBstrSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CBstrSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CBstrSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest();
+}
+
+HRESULT
+BstrLimits()
+{
+ unsigned long u;
+ BSTR bstr;
+
+#if OE_WIN32 /* { */
+
+
+static unsigned long s2M = 2097152;
+static unsigned long INCREMENT = 262144;
+
+ DbPrintf("SysAllocStringLen()\n");
+
+ DbPrintf("linear increasing...\n");
+ for(u = 1; u < s2M; u+=INCREMENT){
+ DbPrintf("%lu\n", u);
+ bstr = SysAllocStringLen(NULL, (unsigned int)u);
+ IfWin(Yield());
+ if(bstr == NULL)
+ break;
+ SysFreeString(bstr);
+ }
+ DbPrintf("max len = %lu\n", u-1);
+
+ DbPrintf("linear decreasing...\n");
+ for(u = s2M; u > 0; u-=INCREMENT){
+ DbPrintf("%lu\n", u);
+ bstr = SysAllocStringLen(NULL, (unsigned int)u);
+ IfWin(Yield());
+ if(bstr == NULL)
+ break;
+ SysFreeString(bstr);
+ }
+ DbPrintf("max len = %lu\n", u);
+
+ return NOERROR;
+
+#else
+
+#if OE_MAC
+static unsigned long s64k = 64000;
+#else
+static unsigned long s64k = UINT_MAX;
+#endif
+ DbPrintf("SysAllocStringLen()\n");
+
+ DbPrintf("linear increasing...\n");
+ for(u = s64k-(1024*4); u < s64k; ++u){
+ if((u%1024) == 0){
+ DbPrintf("%lu\n", u);
+ }
+ bstr = SysAllocStringLen(NULL, (unsigned int)u);
+ IfWin(Yield());
+ if(bstr == NULL)
+ break;
+ SysFreeString(bstr);
+ }
+ DbPrintf("max len = %lu\n", u-1);
+
+ DbPrintf("linear decreasing...\n");
+ for(u = s64k; u > 0; --u){
+ bstr = SysAllocStringLen(NULL, (unsigned int)u);
+ IfWin(Yield());
+ if(bstr != NULL){
+ SysFreeString(bstr);
+ break;
+ }
+ }
+ DbPrintf("max len = %lu\n", u);
+
+ return NOERROR;
+
+#endif /* } */
+}
+
+
+// regression test for raid!oleprog:5
+//
+HRESULT
+BstrOleprog5()
+{
+ unsigned int len;
+ BSTR bstr;
+static OLECHAR a_string[] = OLESTR("a string");
+static OLECHAR another_string[] = OLESTR("another (longer) string");
+
+ bstr = SysAllocString(a_string);
+ if(bstr == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLen(bstr);
+#if (defined(WIN32) && !defined(UNICODE))
+ if(len != (unsigned int)wcslen(a_string))
+#else
+ if(len != STRLEN(a_string))
+#endif
+ return RESULT(E_FAIL);
+
+ if(!SysReAllocString(&bstr, another_string))
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLen(bstr);
+#if (defined(WIN32) && !defined(UNICODE))
+ if(len != (unsigned int)wcslen(another_string))
+#else
+ if(len != STRLEN(another_string))
+#endif
+ return RESULT(E_FAIL);
+
+ SysFreeString(bstr);
+
+ return NOERROR;
+}
+
+// regression test for raid!oleprog:8
+//
+HRESULT
+BstrOleprog8()
+{
+ unsigned int len;
+ HRESULT hresult;
+ BSTR bstr1, bstr2;
+#define LARGE_BSTR_SIZE 64300
+
+ if((bstr1 = SysAllocStringLen(NULL, LARGE_BSTR_SIZE)) == NULL){
+ hresult = RESULT(E_OUTOFMEMORY);
+ goto LError0;
+ }
+
+ if((bstr2 = SysAllocString(OLESTR("hello world"))) == NULL){
+ hresult = RESULT(E_OUTOFMEMORY);
+ goto LError1;
+ }
+
+ if((len = SysStringLen(bstr1)) != LARGE_BSTR_SIZE){
+ hresult = RESULT(E_FAIL);
+ goto LError2;
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ SysFreeString(bstr1);
+
+LError1:;
+ SysFreeString(bstr2);
+
+LError0:;
+ return hresult;
+
+#undef LARGE_BSTR_SIZE
+}
+
+// regression test for raid!oleprog:8
+//
+// SysAllocString of a string containing an embedded '\0' stops
+// copying at the '\0';
+//
+HRESULT
+BstrOleprog65()
+{
+ BSTR bstr;
+ HRESULT hresult;
+ static OLECHAR sz_embedded_null[] =
+ OLESTR("a string \0 with an embedded null");
+
+
+ bstr = SysAllocStringLen(sz_embedded_null, SIZEOFCH(sz_embedded_null));
+
+ hresult = (MEMCMP(bstr, sz_embedded_null, sizeof(sz_embedded_null)) == 0)
+ ? NOERROR
+ : RESULT(E_UNEXPECTED);
+
+ SysFreeString(bstr);
+
+ return hresult;
+}
+
+// regression test for raid!oleprog:234
+//
+// make sure we are properly handling Reallocing a bstr thats Null.
+//
+HRESULT
+BstrOleprog234()
+{
+ unsigned int len;
+ BSTR bstr;
+ static OLECHAR szHooHa[] = OLESTR("HooHa");
+
+ bstr = NULL;
+ if(!SysReAllocString(&bstr, szHooHa))
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLen(bstr);
+#if (defined(WIN32) && !defined(UNICODE))
+ if(len != (unsigned int)wcslen(szHooHa))
+#else
+ if(len != STRLEN(szHooHa))
+#endif
+ return RESULT(E_FAIL);
+
+ SysFreeString(bstr);
+
+ return NOERROR;
+}
+
diff --git a/private/oleauto/tests/disptest/ccollect.cpp b/private/oleauto/tests/disptest/ccollect.cpp
new file mode 100644
index 000000000..91aa5d101
--- /dev/null
+++ b/private/oleauto/tests/disptest/ccollect.cpp
@@ -0,0 +1,422 @@
+/***
+*ccollect.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CCollectionSuite test object.
+*
+*Revision History:
+*
+* [00] 06-Dec-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+
+#include <math.h>
+
+#include "tstsuite.h"
+#include "disphelp.h"
+#include "clsid.h"
+#include "crempoly.h"
+
+ASSERTDATA
+
+
+extern OLECHAR FAR* g_CPoly;
+
+
+HRESULT CollectionTest0(void);
+HRESULT CollectionTest1(void);
+
+static struct TEST {
+ HRESULT (*pfnTest)(void);
+ OLECHAR FAR* szName;
+} rgtest[] = {
+ { CollectionTest0, OLESTR("collection test #0") }
+ , { CollectionTest1, OLESTR("collection test #1") }
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CCollectionSuite)
+
+SUITE_IUNKNOWN_IMPL(CCollectionSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CCollectionSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Collections"), pbstr);
+}
+
+STDMETHODIMP
+CCollectionSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("collect.log"), pbstr);
+}
+
+STDMETHODIMP
+CCollectionSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+
+ return NOERROR;
+}
+
+
+STDMETHODIMP
+CCollectionSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+
+/***
+*HRESULT CCollectionSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CCollectionSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CCollectionSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest();
+}
+
+
+HRESULT
+DoInvokeName(
+ IDispatch FAR* pdisp,
+ OLECHAR FAR* szMethod,
+ VARIANT FAR* pvarResult,
+ DISPPARAMS FAR* pdispparams)
+{
+ DISPID dispid;
+ OLECHAR FAR* rgsz[1];
+ DISPPARAMS dispparams;
+
+ if(pdispparams == NULL){
+ pdispparams = &dispparams;
+ pdispparams->cArgs = 0;
+ pdispparams->rgvarg = NULL;
+ pdispparams->cNamedArgs = 0;
+ pdispparams->rgdispidNamedArgs = NULL;
+ }
+
+ rgsz[0] = szMethod;
+ IfFailRet(
+ pdisp->GetIDsOfNames(
+ IID_NULL, rgsz, 1, LOCALE_SYSTEM_DEFAULT, &dispid));
+
+ return DoInvoke(pdisp, dispid, pdispparams, pvarResult, NULL, NULL);
+}
+
+
+HRESULT
+VtIs(VARIANT FAR* pvar, VARTYPE vt)
+{
+ return (V_VT(pvar) != vt) ? RESULT(E_INVALIDARG) : NOERROR;
+}
+
+struct oledisp_point { short x,y; };
+
+static struct oledisp_point rgptTriangle[] = {
+ {50, 0},
+ {0, 100},
+ {100, 100}
+};
+
+static struct oledisp_point rgptSquare[] = {
+ {0, 0},
+ {0, 100},
+ {100, 100},
+ {100, 0},
+};
+
+static struct oledisp_point rgptOctagon[] = {
+ {25, 0},
+ {75, 0},
+ {100, 25},
+ {100, 75},
+ {75, 100},
+ {25, 100},
+ {0, 75},
+ {0, 25}
+};
+
+struct oledisp_shape {
+ struct oledisp_point ptOrigin;
+ unsigned int cPoints;
+ struct oledisp_point FAR* rgpt;
+} g_rgshape[] = {
+ {{100, 50}, DIM(rgptTriangle), rgptTriangle},
+ {{200, 50}, DIM(rgptSquare), rgptSquare},
+ {{300, 50}, DIM(rgptOctagon), rgptOctagon}
+};
+
+
+HRESULT
+BuildShape(CRemPoly FAR* ppoly, struct oledisp_shape FAR* pshape)
+{
+ unsigned int i;
+
+ IfFailRet(ppoly->SetWidth(1));
+ IfFailRet(ppoly->set_red(0));
+ IfFailRet(ppoly->set_green(0));
+ IfFailRet(ppoly->set_blue(0));
+ IfFailRet(ppoly->SetXOrigin((short)pshape->ptOrigin.x));
+ IfFailRet(ppoly->SetYOrigin((short)pshape->ptOrigin.y));
+ for(i = 0; i < pshape->cPoints; ++i)
+ IfFailRet(
+ ppoly->AddPoint((short)pshape->rgpt[i].x, (short)pshape->rgpt[i].y));
+
+ return NOERROR;
+}
+
+static struct {
+ short red, green, blue;
+} g_rgrgbColors[] = {
+#if OE_MAC
+ { 0, 0, 0}
+ , { 0, 0, 0x7fff}
+ , { 0, 0x7fff, 0}
+ , {0x7fff, 0, 0}
+ , {0x7fff, 0, 0x7fff}
+ , {0x7fff, 0x7fff, 0}
+ , {0x7fff, 0x7fff, 0x7fff}
+ , { 0, 0, 0xffff}
+ , { 0, 0xffff, 0}
+ , {0xffff, 0, 0}
+ , {0xffff, 0, 0xffff}
+ , {0xffff, 0xffff, 0}
+#else
+ { 0, 0, 0}
+ , { 0, 0, 127}
+ , { 0, 127, 0}
+ , {127, 0, 0}
+ , {127, 0, 127}
+ , {127, 127, 0}
+ , {127, 127, 127}
+ , { 0, 0, 255}
+ , { 0, 255, 0}
+ , {255, 0, 0}
+ , {255, 0, 255}
+ , {255, 255, 0}
+#endif
+};
+
+HRESULT
+MoveShape(CRemPoly FAR* ppoly)
+{
+ short s;
+ int i, ix;
+ HRESULT hresult;
+ unsigned long celtFetched;
+ IDispatch FAR* pdisp;
+ IEnumVARIANT FAR* penum;
+ DISPPARAMS dispparams;
+ VARIANT varX, varY, varElt;
+
+ double delta_rads;
+
+
+ // get an enumerator for the points we just added.
+ //
+ IfFailGo(ppoly->EnumPoints(&penum), LError0);
+
+ // degrees -> radians
+ delta_rads = ((double)20.0 * 3.14159) / 180.0;
+
+ for(i = 0; i < 15; ++i){
+ IfFailGo(penum->Reset(), LError1);
+
+ VariantInit(&varElt);
+ while((hresult = penum->Next(1, &varElt, &celtFetched)) == NOERROR){
+ // make sure we got what we expected.
+ //
+ ASSERT(celtFetched == 1);
+ IfFailGo(VtIs(&varElt, VT_DISPATCH), LError1);
+
+ pdisp = V_DISPATCH(&varElt);
+ V_VT(&varElt) = VT_EMPTY;
+
+ // get the X and Y coordinates
+
+ VariantInit(&varX);
+ IfFailGo(DoInvokeName(pdisp, OLESTR("getx"), &varX, NULL), LError2);
+ IfFailGo(VtIs(&varX, VT_I2), LError3);
+
+ VariantInit(&varY);
+ IfFailGo(DoInvokeName(pdisp, OLESTR("gety"), &varY, NULL), LError3);
+ IfFailGo(VtIs(&varY, VT_I2), LError4);
+
+ // rotate the point
+
+ double x = (double)V_I2(&varX);
+ double y = (double)V_I2(&varY);
+ double radius = sqrt((x*x) + (y*y));
+ double theta = ((x == 0.0) && (y == 0.0) ? 0.0 : atan2(y, x))
+ + delta_rads;
+
+ V_I2(&varX) = (short)(radius * cos(theta));
+ V_I2(&varY) = (short)(radius * sin(theta));
+
+ // set the new X and Y coordinates
+
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = &varX;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ IfFailGo(DoInvokeName(pdisp, OLESTR("setx"), NULL, &dispparams), LError4);
+
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = &varY;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ IfFailGo(DoInvokeName(pdisp, OLESTR("sety"), NULL, &dispparams), LError4);
+
+ VariantClear(&varY);
+ VariantClear(&varX);
+
+ pdisp->Release();
+ pdisp = NULL;
+ }
+
+ if(HRESULT_FAILED(hresult))
+ goto LError1;
+
+ ASSERT(GetScode(hresult) == S_FALSE);
+
+ IfFailGo(ppoly->SetWidth(i), LError1);
+
+ IfFailGo(ppoly->GetXOrigin(&s), LError1);
+ IfFailGo(ppoly->SetXOrigin(i + i + s), LError1);
+
+ IfFailGo(ppoly->GetYOrigin(&s), LError1);
+ IfFailGo(ppoly->SetYOrigin(i + i + s), LError1);
+
+ ix = i % DIM(g_rgrgbColors);
+ IfFailGo(ppoly->set_red(g_rgrgbColors[i].red), LError1);
+ IfFailGo(ppoly->set_green(g_rgrgbColors[i].green), LError1);
+ IfFailGo(ppoly->set_blue(g_rgrgbColors[i].blue), LError1);
+
+ IfFailGo(ppoly->Draw(), LError1);
+
+ IfWin(Yield());
+ }
+
+ penum->Release();
+
+ return NOERROR;
+
+
+LError4:;
+ VariantClear(&varY);
+
+LError3:;
+ VariantClear(&varX);
+
+LError2:;
+ pdisp->Release();
+
+LError1:;
+ penum->Release();
+
+LError0:;
+ return hresult;
+}
+
+
+HRESULT
+CollectionTest1()
+{
+ int i, j;
+ HRESULT hresult;
+ CRemPoly FAR* ppoly[2];
+
+ for(i = 0; i < DIM(ppoly); ++i)
+ ppoly[i] = NULL;
+
+ IfFailGo(CRemPoly::Create(OLESTR("SPoly.Application"), &ppoly[0]), LError0);
+ IfFailGo(CRemPoly::Create(OLESTR("SPoly2.Application"), &ppoly[1]), LError0);
+
+ for(j = 0; j < DIM(g_rgshape); ++j)
+ {
+ for(i = 0; i < DIM(ppoly); ++i)
+ IfFailGo(BuildShape(ppoly[i], &g_rgshape[j]), LError0);
+
+ for(i = 0; i < DIM(ppoly); ++i){
+ IfFailGo(ppoly[i]->Draw(), LError0);
+ IfFailGo(MoveShape(ppoly[i]), LError0);
+ }
+
+ for(i = 0; i < DIM(ppoly); ++i)
+ IfFailGo(ppoly[i]->Reset(), LError0);
+ }
+
+ hresult = NOERROR;
+
+LError0:;
+ for(i = 0; i < DIM(ppoly); ++i)
+ if(ppoly[i] != NULL)
+ ppoly[i]->Release();
+
+ return hresult;
+}
+
+
+HRESULT
+CollectionTest0()
+{
+ HRESULT hresult;
+ CRemPoly FAR* ppoly;
+ IEnumVARIANT FAR* penum;
+ IEnumVARIANT FAR* penumClone;
+
+ IfFailGo(CRemPoly::Create(OLESTR("SPoly.Application"), &ppoly), LError0);
+
+ ppoly->AddPoint(0, 0);
+ ppoly->AddPoint(0, 50);
+ ppoly->AddPoint(50, 0);
+ ppoly->AddPoint(50, 50);
+ ppoly->Draw();
+
+ IfFailGo(ppoly->EnumPoints(&penum), LError1);
+
+ IfFailGo(penum->Clone(&penumClone), LError2);
+
+ hresult = NOERROR;
+
+ penumClone->Release();
+
+LError2:;
+ penum->Release();
+
+LError1:;
+ ppoly->Release();
+
+LError0:;
+ return hresult;
+}
+
diff --git a/private/oleauto/tests/disptest/cdatecnv.cpp b/private/oleauto/tests/disptest/cdatecnv.cpp
new file mode 100644
index 000000000..70ebdd436
--- /dev/null
+++ b/private/oleauto/tests/disptest/cdatecnv.cpp
@@ -0,0 +1,491 @@
+/***
+*cdatecnv.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CDateCoersionSuite. This suite tests date/time
+* coersions - primarrily date<->bstr.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include "disptest.h"
+#include "tstsuite.h"
+
+
+static LCID rglcid[] = {
+ 0
+ , 0x040c
+ , 0x0407
+ , 0x0409
+ , 0x0809
+ , 0x0c09
+ , 0x1009
+ , 0x1409
+ , 0x0406
+ , 0x0413
+ , 0x0813
+ , 0x040b
+ , 0x080c
+ , 0x0c0c
+ , 0x100c
+ , 0x0807
+ , 0x0c07
+ , 0x0410
+ , 0x0810
+ , 0x040a
+ , 0x080a
+ , 0x0c0a
+ , 0x041d
+ , 0x0414
+ , 0x0416
+ , 0x0816
+ , 0x0405
+ , 0x040e
+ , 0x0415
+ , 0x041b
+ , 0x0419
+};
+
+static OLECHAR FAR* rgpszSimpleDate[] =
+{
+ OLESTR("1-7-66")
+ , OLESTR("1.20")
+ , OLESTR("1-7-100")
+ , OLESTR("1-7-1966")
+ , OLESTR("01-7-66")
+ , OLESTR("01-07-66")
+ , OLESTR("01-07-0100")
+ , OLESTR("01-07-1966")
+ , OLESTR("1/7/66")
+ , OLESTR("1/7/100")
+ , OLESTR("1/7/1966")
+ , OLESTR("1-7/66")
+ , OLESTR("1-7/100")
+ , OLESTR("1-7/1966")
+ , OLESTR("1/7-66")
+ , OLESTR("1/7-100")
+ , OLESTR("1/7-1966")
+ , OLESTR("1-7-66")
+ , OLESTR("1-7-100")
+ , OLESTR("1-7-1966")
+ , OLESTR("1 - 7 - 66")
+ , OLESTR("1 - 7 - 100")
+ , OLESTR("1 - 7 - 1966")
+ , OLESTR(" 1/7/1966")
+ , OLESTR("1/7/1966 ")
+ , OLESTR(" 1 / 07 / 66 ")
+ , OLESTR("\t1\t/\t07\t/\t66\t")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszShortMonth[] =
+{
+ OLESTR("jan 10, 22")
+ , OLESTR("feb 03, 1999")
+ , OLESTR("mar 31, 1945")
+ , OLESTR("apr 1, 2002")
+ , OLESTR("may 15, 2020")
+ , OLESTR("jun 08, 1978")
+ , OLESTR("jul 30 1492")
+ , OLESTR("aug 12 1010")
+ , OLESTR("sep 3 1877")
+ , OLESTR(" oct 4, 1214")
+ , OLESTR("nov 12 1313 ")
+ , OLESTR(" dec 7, 1942 ")
+ , OLESTR("10 jan 22")
+ , OLESTR("03 feb 1999")
+ , OLESTR("31, mar 1945")
+ , OLESTR("1, apr 2002")
+ , OLESTR("15, may 2020")
+ , OLESTR("08 jun, 1978")
+ , OLESTR("30 jul 1492")
+ , OLESTR("12 aug 1010")
+ , OLESTR(" 3 sep 1877")
+ , OLESTR("004 oct, 1214")
+ , OLESTR("12 nov 1313 ")
+ , OLESTR("7, dec, 1942 ")
+ , OLESTR("\t7\t,\tdec\t,\t1942\t")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszLongMonth[] =
+{
+ OLESTR("january 10, 22")
+ , OLESTR("february 03, 1999")
+ , OLESTR("march 31, 1945")
+ , OLESTR("april 1, 2002")
+ , OLESTR("may 15, 2020")
+ , OLESTR("june 08, 1978")
+ , OLESTR("july 30 1492")
+ , OLESTR("august 12 1010")
+ , OLESTR("september 3 1877")
+ , OLESTR(" october 4, 1214")
+ , OLESTR("november 12 1313 ")
+ , OLESTR(" december 7, 1942 ")
+ , OLESTR("10 January 22")
+ , OLESTR("03 February 1999")
+ , OLESTR("31, March 1945")
+ , OLESTR("1, April 2002")
+ , OLESTR("15, May 2020")
+ , OLESTR("08 June, 1978")
+ , OLESTR("30 JULY 1492")
+ , OLESTR("12 AugUST 1010")
+ , OLESTR(" 3 SePtEmBeR 1877")
+ , OLESTR("004 OCTOBER, 1214")
+ , OLESTR("12 NOVembER 1313 ")
+ , OLESTR("7, DeceMBeR, 1942 ")
+ , OLESTR("\t7,\tDeceMBeR,\t1942\t")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszPartialDate[] =
+{
+ OLESTR("1-10")
+ , OLESTR("2-99")
+ , OLESTR("mar 15")
+ , OLESTR("15 april")
+ , OLESTR("may 45")
+ , OLESTR("99 JUN")
+ , OLESTR(" 1/20")
+ , OLESTR(" 12-15 ")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszSimpleTime[] = {
+ OLESTR("0:0:0")
+ , OLESTR("0:0:0 am")
+ , OLESTR("0:0:0 pm")
+ , OLESTR("1:0:0")
+ , OLESTR("1:0:0 am")
+ , OLESTR("1:0:0 pm")
+ , OLESTR("11:0:0")
+ , OLESTR("11:0:0 am")
+ , OLESTR("11:0:0 pm")
+ , OLESTR("12:0:0")
+ , OLESTR("12:0:0 am")
+ , OLESTR("12:0:0 pm")
+ , OLESTR("13:0:0")
+ , OLESTR("23:0:0")
+ , OLESTR("1:2:3")
+ , OLESTR("01:2:3")
+ , OLESTR("1:02:3")
+ , OLESTR("01:2:03")
+ , OLESTR("01:02:03")
+ , OLESTR("1.2.3")
+ , OLESTR("01.2.3")
+ , OLESTR("1.02.3")
+ , OLESTR("01.2.03")
+ , OLESTR("01.02.03")
+ , OLESTR("1.2.3 am")
+ , OLESTR("01.2.3 am")
+ , OLESTR("1.02.3 am")
+ , OLESTR("01.2.03 am")
+ , OLESTR("01.02.03 am")
+ , OLESTR("1.2.3 pm")
+ , OLESTR("01.2.3 pm")
+ , OLESTR("1.02.3 pm")
+ , OLESTR("01.2.03 pm")
+ , OLESTR("01.02.03 pm")
+ , OLESTR("1.2.3 a")
+ , OLESTR("01.2.3 a")
+ , OLESTR("1.02.3 a")
+ , OLESTR("01.2.03 a")
+ , OLESTR("01.02.03 a")
+ , OLESTR("1.2.3 p")
+ , OLESTR("01.2.3 p")
+ , OLESTR("1.02.3 p")
+ , OLESTR("01.2.03 p")
+ , OLESTR("01.02.03 p")
+ , OLESTR(" 1. 2. 3 ")
+ , OLESTR(" 01. 2. 3 am ")
+ , OLESTR(" 1.02: 3 p ")
+ , OLESTR(" 01: 2.03 pm ")
+ , OLESTR(" 01:02:03 p ")
+ , OLESTR(" 25:0 ")
+ , OLESTR("1.61 p")
+ , OLESTR("1.2.99")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszPartialTime[] = {
+ OLESTR("1 a")
+ , OLESTR("2 am")
+ , OLESTR("3 p ")
+ , OLESTR("04 pm")
+ , OLESTR("5:50")
+ , OLESTR("6:6 a")
+ , OLESTR("7:7 am")
+ , OLESTR("08:08 p")
+ , OLESTR("09:09 pm")
+ , OLESTR("10:10")
+ , OLESTR("11:11 ")
+ , OLESTR(" 12:12")
+ , OLESTR(" 13:13 ")
+ , OLESTR("14.14")
+ , OLESTR("15.15 ")
+ , OLESTR(" 16.16")
+ , OLESTR(" 17.17 ")
+ , OLESTR("18:18")
+ , OLESTR("19:19 ")
+ , OLESTR(" 20:20")
+ , OLESTR(" 21.21 ")
+ , OLESTR("22.22")
+ , OLESTR("23.59 ")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszDateTime[] = {
+ OLESTR("1-7-66 12:14:00")
+ , OLESTR("1/7/1966 12:14")
+ , OLESTR("1/7 12:14")
+ , OLESTR("jan 7, 1966 12:14 am")
+ , OLESTR("jan 7 12:14")
+ , OLESTR("january 7 1993 1:20 pm")
+ , OLESTR("feb 18, 2002 23:59:50")
+ , OLESTR("mar 12 1 am")
+ , OLESTR("apr 30 45 2 a")
+ , OLESTR("may/7, 1475 10.02")
+ , OLESTR("1 7 5 am")
+ , OLESTR("7 jan 1966 12:14 am")
+ , OLESTR("17 jan 12:14")
+ , OLESTR("7 january 1993 1:20 pm")
+ , OLESTR("18 feb, 2002 23:59:50")
+ , OLESTR("12 mar 1 am")
+ , OLESTR("30 apr 45 2 a")
+ , OLESTR("7/may, 1475 10.02")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszTimeDate[] = {
+ OLESTR("12:14:00 1-7-66")
+ , OLESTR("12:14 1/7/1966")
+ , OLESTR("12:14 1/7")
+ , OLESTR("12:14 am jan 7, 1966")
+ , OLESTR("12:14:00 jan 7")
+ , OLESTR("1:20 pm january 7 1993")
+ , OLESTR("23.59:50 feb 18, 2002")
+ , OLESTR("1 am mar 12")
+ , OLESTR("2 a apr 30 45")
+ , OLESTR("10.02 may/7, 1475 ")
+ , OLESTR("5 am 1 7")
+ , OLESTR(" 12:14 am 7 jan 1966 ")
+ , OLESTR("02.04 17 jan")
+ , OLESTR("1.20 pm 7 january 1993")
+ , OLESTR("23:59.50 18 feb, 2002")
+ , OLESTR("1 am 12 mar ")
+ , OLESTR(" 2 a 30 apr 45")
+ , OLESTR(" 10.02 7/may, 1475 ")
+ , NULL
+};
+
+// the following date strings are invalid formats and should generate errors
+
+static OLECHAR FAR* rgpszErrors[] = {
+ OLESTR("")
+ , OLESTR(" ")
+ , OLESTR("\t")
+ , OLESTR("1")
+ , OLESTR("33/33")
+ , OLESTR("1-2-3-4")
+ , OLESTR("1-2-3 4")
+ , OLESTR("1-2 3 4")
+ , OLESTR("1 2 3 4")
+ , OLESTR("1/2/3/4")
+ , OLESTR("1/2/3 4")
+ , OLESTR("1/2 3 4")
+ , OLESTR("1 2 3 4")
+ , OLESTR("1/")
+ , OLESTR("1-")
+ , OLESTR("-1")
+ , OLESTR("/1")
+ , OLESTR("jan")
+ , OLESTR("august")
+ , OLESTR("1:")
+ , OLESTR(":1")
+ , OLESTR("1:.2")
+ , OLESTR("1.2.3.4")
+ , OLESTR("1 am 2")
+ , OLESTR("2 p 3.3")
+ , OLESTR("1-7-66 2:20 pm 1-7-66")
+ , OLESTR("2:20 1-7 2 pm")
+ , OLESTR("25 p")
+ , OLESTR("1.60")
+ , OLESTR("1.2.60")
+ , NULL
+};
+
+static OLECHAR FAR* rgpszBugs[] = {
+ OLESTR("1993-04-01")
+ , OLESTR("2:30:30 5:40:") // error
+ , OLESTR("2:30:30p")
+ , OLESTR("2/3/4 3.4.5")
+ , OLESTR("13.13.13")
+ , OLESTR("1,2,3")
+ , OLESTR("March 23, 1900")
+ , OLESTR("September 2000")
+ , OLESTR("1/68")
+ , OLESTR("3/13")
+ , OLESTR("3/31")
+ , OLESTR("3/32")
+ , OLESTR("2.3.4 3.4.5") // error
+ , OLESTR("1993-02-01")
+ , OLESTR("1993/2/28")
+ , NULL
+};
+
+static OLECHAR FAR* FAR* rgprgszTests[] = {
+ rgpszBugs
+ , rgpszSimpleDate
+ , rgpszShortMonth
+ , rgpszLongMonth
+ , rgpszPartialDate
+ , rgpszSimpleTime
+ , rgpszPartialTime
+ , rgpszDateTime
+ , rgpszTimeDate
+ , rgpszErrors
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CDateCoersionSuite)
+
+SUITE_IUNKNOWN_IMPL(CDateCoersionSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CDateCoersionSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Date Coersions"), pbstr);
+}
+
+STDMETHODIMP
+CDateCoersionSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("bstrdate.log"), pbstr);
+}
+
+STDMETHODIMP
+CDateCoersionSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rglcid);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CDateCoersionSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ TCHAR rgch[32];
+
+ if(iTest >= DIM(rglcid))
+ return RESULT(E_INVALIDARG);
+
+ SPRINTF(rgch, TSTR("(lcid=0x%lx) bstr->date"), rglcid[iTest]);
+ *pbstr = SysAllocString(WIDESTRING(rgch));
+ return NOERROR;
+}
+
+// run a single set of date->bstr coersion tests
+HRESULT
+DoDateOfBstr(LCID lcid, int index)
+{
+ int i;
+ HRESULT hresult;
+ VARIANT varBstr, varDate;
+ OLECHAR FAR* FAR* rgpsz, FAR* psz;
+
+ rgpsz = rgprgszTests[index];
+
+ for(i = 0; rgpsz[i] != NULL; ++i){
+
+ psz = rgpsz[i];
+
+ VariantInit(&varBstr);
+ VariantInit(&varDate);
+
+ V_VT(&varBstr) = VT_BSTR;
+ if((V_BSTR(&varBstr) = SysAllocString(psz)) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ DbPrintf("\"%Fs\" =>", STRING(V_BSTR(&varBstr)));
+
+ hresult = VariantChangeTypeEx(&varDate, &varBstr, lcid, 0, VT_DATE);
+
+ if(hresult != NOERROR){
+
+ DbPrintf(" [%Fs]", DbSzOfScode(GetScode(hresult)));
+
+ }else{
+
+ DbPrintf(" %g => ", V_DATE(&varDate));
+
+ VariantClear(&varBstr);
+
+ hresult = VariantChangeTypeEx(&varBstr, &varDate, lcid, 0, VT_BSTR);
+
+ if(hresult != NOERROR){
+
+ DbPrintf(" [%Fs]", DbSzOfScode(GetScode(hresult)));
+
+ }else{
+
+ DbPrintf(" \"%Fs\"", STRING(V_BSTR(&varBstr)));
+
+ }
+ }
+
+ DbPrintf("\n");
+
+ VariantClear(&varDate);
+ VariantClear(&varBstr);
+ }
+
+ return NOERROR;
+}
+
+// run all of the bstr-date coersion tests for a given locale
+HRESULT
+DateOfBstr(LCID lcid)
+{
+ int i;
+
+ for(i = 0; i < DIM(rgprgszTests); ++i){
+ IfFailRet(DoDateOfBstr(lcid, i));
+ }
+ return NOERROR;
+}
+
+/***
+*HRESULT CDateCoersionSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CDateCoersionSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CDateCoersionSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rglcid))
+ return RESULT(E_INVALIDARG);
+
+ return DateOfBstr(rglcid[iTest]);
+}
+
diff --git a/private/oleauto/tests/disptest/cdisptst.def b/private/oleauto/tests/disptest/cdisptst.def
new file mode 100644
index 000000000..632886c5f
--- /dev/null
+++ b/private/oleauto/tests/disptest/cdisptst.def
@@ -0,0 +1,13 @@
+NAME DispTest
+
+EXETYPE WINDOWS
+
+CODE PRELOAD MOVEABLE DISCARDABLE
+
+DATA PRELOAD MOVEABLE MULTIPLE
+
+HEAPSIZE 1024
+STACKSIZE 16384
+
+;EXPORTS
+; MainWndProc @1
diff --git a/private/oleauto/tests/disptest/cdisptst.r b/private/oleauto/tests/disptest/cdisptst.r
new file mode 100644
index 000000000..a20ae22f6
--- /dev/null
+++ b/private/oleauto/tests/disptest/cdisptst.r
@@ -0,0 +1,329 @@
+#ifdef _PPCMAC
+include "cfrg.rsc";
+#endif
+
+#include "systypes.r"
+#include "types.r"
+#include "macmain.h"
+
+resource 'vers' (1) {
+ 0x02, 0x00, release, 0x00,
+ verUS,
+ "1.02",
+ "1.02, Copyright \251 1993 Microsoft."
+};
+
+/* we use an MBAR resource to conveniently load all the menus */
+
+resource 'MBAR' (rMenuBar, preload) {
+ { mApple, mFile, mEdit, mSuite, mOptions };
+};
+
+
+resource 'MENU' (mApple, preload) {
+ mApple, textMenuProc,
+ 0b1111111111111111111111111111101,
+ enabled, apple,
+ {
+ "About CDispTst\311",
+ noicon, nokey, nomark, plain;
+ "-",
+ noicon, nokey, nomark, plain
+ }
+};
+
+resource 'MENU' (mFile, preload) {
+ mFile, textMenuProc,
+ 0b0000000000000000000100000000000,
+ enabled, "File",
+ {
+ "New",
+ noicon, "N", nomark, plain;
+ "Open",
+ noicon, "O", nomark, plain;
+ "-",
+ noicon, nokey, nomark, plain;
+ "Close",
+ noicon, "W", nomark, plain;
+ "Save",
+ noicon, "S", nomark, plain;
+ "Save As\311",
+ noicon, nokey, nomark, plain;
+ "Revert",
+ noicon, nokey, nomark, plain;
+ "-",
+ noicon, nokey, nomark, plain;
+ "Page Setup\311",
+ noicon, nokey, nomark, plain;
+ "Print\311",
+ noicon, nokey, nomark, plain;
+ "-",
+ noicon, nokey, nomark, plain;
+ "Quit",
+ noicon, "Q", nomark, plain
+ }
+};
+
+resource 'MENU' (mEdit, preload) {
+ mEdit, textMenuProc,
+ 0b0000000000000000000000000000000,
+ enabled, "Edit",
+ {
+ "Undo",
+ noicon, "Z", nomark, plain;
+ "-",
+ noicon, nokey, nomark, plain;
+ "Cut",
+ noicon, "X", nomark, plain;
+ "Copy",
+ noicon, "C", nomark, plain;
+ "Paste",
+ noicon, "V", nomark, plain;
+ "Clear",
+ noicon, nokey, nomark, plain
+ }
+};
+
+resource 'MENU' (mSuite, preload) {
+ mSuite, textMenuProc,
+ 0b0000000000000000000111111111111,
+ enabled, "Suite",
+ {
+ "Bstr API",
+ noicon, nokey, nomark, plain;
+ "Time API",
+ noicon, nokey, nomark, plain;
+ "Date Coersions",
+ noicon, nokey, nomark, plain;
+ "Variant API",
+ noicon, nokey, nomark, plain;
+ "SafeArray API",
+ noicon, nokey, nomark, plain;
+ "NLS API",
+ noicon, nokey, nomark, plain;
+ "Binding",
+ noicon, nokey, nomark, plain;
+ "Invoke ByVal",
+ noicon, nokey, nomark, plain;
+ "Invoke ByRef",
+ noicon, nokey, nomark, plain;
+ "Invoke Array",
+ noicon, nokey, nomark, plain;
+ "Invoke Excepinfo",
+ noicon, nokey, nomark, plain;
+ "Collections",
+ noicon, nokey, nomark, plain
+ }
+};
+
+resource 'MENU' (mOptions, preload) {
+ mOptions, textMenuProc,
+ 0b0000000000000000000000000000011,
+ enabled, "Options",
+ {
+ "Clear",
+ noicon, "C", nomark, plain;
+ "Debugger",
+ noicon, nokey, nomark, plain
+ }
+};
+
+
+/* this ALRT and DITL are used as an About screen */
+
+resource 'ALRT' (rAboutAlert, purgeable) {
+ {40, 20, 160, 296}, rAboutAlert, {
+ OK, visible, silent;
+ OK, visible, silent;
+ OK, visible, silent;
+ OK, visible, silent
+ };
+};
+
+resource 'DITL' (rAboutAlert, purgeable) {
+ { /* array DITLarray: 5 elements */
+ /* [1] */
+ {88, 184, 108, 264},
+ Button {
+ enabled,
+ "OK"
+ },
+ /* [2] */
+ {8, 8, 24, 274},
+ StaticText {
+ disabled,
+ "IDispatch Test Application"
+ },
+ /* [3] */
+ {32, 8, 48, 237},
+ StaticText {
+ disabled,
+ "Copyright \251 1993 Microsoft"
+ },
+ /* [4] */
+ {56, 8, 72, 136},
+ StaticText {
+ disabled,
+ "Brought to you by:"
+ },
+ /* [5] */
+ {80, 24, 112, 167},
+ StaticText {
+ disabled,
+ "The Ole Automation Team"
+ }
+ }
+};
+
+
+/* this ALRT and DITL are used as an error screen */
+
+resource 'ALRT' (rUserAlert, purgeable) {
+ {40, 20, 150, 260},
+ rUserAlert,
+ { /* array: 4 elements */
+ /* [1] */
+ OK, visible, silent,
+ /* [2] */
+ OK, visible, silent,
+ /* [3] */
+ OK, visible, silent,
+ /* [4] */
+ OK, visible, silent
+ }
+};
+
+
+resource 'DITL' (rUserAlert, purgeable) {
+ { /* array DITLarray: 3 elements */
+ /* [1] */
+ {80, 150, 100, 230},
+ Button {
+ enabled,
+ "OK"
+ },
+ /* [2] */
+ {10, 60, 60, 230},
+ StaticText {
+ disabled,
+ "Error. ^0."
+ },
+ /* [3] */
+ {8, 8, 40, 40},
+ Icon {
+ disabled,
+ 2
+ }
+ }
+};
+
+
+resource 'WIND' (rDocWindow, preload, purgeable) {
+ {64, 60, 314, 460},
+ zoomDocProc, invisible, goAway, 0x0, "untitled"
+};
+
+
+resource 'CNTL' (rVScroll, preload, purgeable) {
+ {-1, 385, 236, 401},
+ 0, visible, 0, 0, scrollBarProc, 0, ""
+};
+
+
+resource 'CNTL' (rHScroll, preload, purgeable) {
+ {235, -1, 251, 386},
+ 0, visible, 0, 0, scrollBarProc, 0, ""
+};
+
+resource 'STR#' (kErrStrings, purgeable) {
+ {
+ "You must run on 512Ke or later";
+ "Application Memory Size is too small";
+ "Not enough memory to run CDispTst";
+ "Not enough memory to do Cut";
+ "Cannot do Cut";
+ "Cannot do Copy";
+ "Cannot exceed 32,000 characters with Paste";
+ "Not enough memory to do Paste";
+ "Cannot create window";
+ "Cannot exceed 32,000 characters";
+ "Cannot do Paste"
+ }
+};
+
+resource 'SIZE' (-1) {
+ dontSaveScreen,
+ acceptSuspendResumeEvents,
+ enableOptionSwitch,
+ canBackground,
+ multiFinderAware,
+ backgroundAndForeground,
+ dontGetFrontClicks,
+ ignoreChildDiedEvents,
+ is32BitCompatible,
+ isHighLevelEventAware,
+ localAndRemoteHLEvents,
+ reserved,
+ reserved,
+ reserved,
+ reserved,
+ reserved,
+ kPrefSize * 1024,
+ kMinSize * 1024
+};
+
+
+type 'MOOT' as 'STR ';
+
+
+resource 'MOOT' (0) {
+ "MultiFinder-Aware TextEdit Sample Application"
+};
+
+
+resource 'BNDL' (128) {
+ 'MOOT',
+ 0,
+ {
+ 'ICN#',
+ {
+ 0, 128
+ },
+ 'FREF',
+ {
+ 0, 128
+ }
+ }
+};
+
+
+resource 'FREF' (128) {
+ 'APPL',
+ 0,
+ ""
+};
+
+
+resource 'ICN#' (128) {
+ { /* array: 2 elements */
+ /* [1] */
+ $"04 30 40 00 0A 50 A0 00 0B 91 10 02 08 22 08 03"
+ $"12 24 04 05 20 28 02 09 40 10 01 11 80 0C 00 A1"
+ $"80 03 FF C2 7E 00 FF 04 01 00 7F 04 03 00 1E 08"
+ $"04 E0 00 0C 08 E0 00 0A 10 E0 00 09 08 C0 00 06"
+ $"04 87 FE 04 02 88 01 04 01 88 00 84 00 88 00 44"
+ $"00 88 00 44 00 88 00 C4 01 10 01 88 02 28 03 10"
+ $"01 C4 04 E0 00 02 08 00 73 BF FB EE 4C A2 8A 2A"
+ $"40 AA AA EA 52 AA AA 24 5E A2 8A EA 73 BE FB 8E",
+ /* [2] */
+ $"04 30 40 00 0E 70 E0 00 0F F1 F0 02 0F E3 F8 03"
+ $"1F E7 FC 07 3F EF FE 0F 7F FF FF 1F FF FF FF BF"
+ $"FF FF FF FE 7F FF FF FC 01 FF FF FC 03 FF FF F8"
+ $"07 FF FF FC 0F FF FF FE 1F FF FF FF 0F FF FF FE"
+ $"07 FF FF FC 03 FF FF FC 01 FF FF FC 00 FF FF FC"
+ $"00 FF FF FC 00 FF FF FC 01 FF FF F8 03 EF FF F0"
+ $"01 C7 FC E0 00 03 F8 00 73 BF FB EE 7F BE FB EE"
+ $"7F BE FB EE 7F BE FB E4 7F BE FB EE 73 BE FB 8E"
+ }
+};
+
diff --git a/private/oleauto/tests/disptest/cdisptst.rc b/private/oleauto/tests/disptest/cdisptst.rc
new file mode 100644
index 000000000..848ccda54
--- /dev/null
+++ b/private/oleauto/tests/disptest/cdisptst.rc
@@ -0,0 +1,87 @@
+/***
+*cdisptst.rc
+*
+* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* Resource script for cdisptst.exe
+*
+*
+*Revision History:
+*
+* [00] 27-Apr-93 bradlo: Created (added header).
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#ifdef _MAC
+# include <wlm.h>
+#else
+# include <windows.h>
+#endif
+#include "resource.h"
+
+#include "assert.dlg"
+
+SUITEDLG DIALOG DISCARDABLE 0, 0, 177, 114
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Executing..."
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "Cancel",IDCANCEL,65,91,47,17
+ LTEXT "",IDD_SUITE_NAME,17,20,145,8
+ LTEXT "",IDD_SUITE_TESTNAME,17,42,145,8
+ LTEXT "",IDD_SUITE_GUAGE,16,58,145,12
+ CTEXT "",IDD_SUITE_PERCENT,78,75,20,9
+ LTEXT "Suite:",1002,17,11,20,8
+ LTEXT "Test:",1003,17,33,20,8
+END
+
+AboutBox DIALOG 22, 17, 144, 75
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About IDispatch Test App"
+BEGIN
+ CTEXT "Microsoft Windows" -1, 0, 5, 144, 8
+ CTEXT "IDispatch Test Application" -1, 0, 14, 144, 8
+ CTEXT "Version 1.0" -1, 0, 34, 144, 8
+ DEFPUSHBUTTON "OK" IDOK, 53, 59, 32, 14, WS_GROUP
+END
+
+
+DISPTESTMENU MENU DISCARDABLE
+BEGIN
+ MENUITEM "All", IDM_ALL
+ POPUP "Suite"
+ BEGIN
+ MENUITEM "Bstr API", IDM_SUITE_BSTR
+ MENUITEM "Time API", IDM_SUITE_TIME
+ MENUITEM "Date Coersions", IDM_SUITE_DATECNV
+ MENUITEM "Variant API", IDM_SUITE_VARIANT
+ MENUITEM "SafeArray API", IDM_SUITE_SAFEARRAY
+ MENUITEM "NLS API", IDM_SUITE_NLS
+ MENUITEM "Binding", IDM_SUITE_BIND
+ MENUITEM "Invoke ByVal", IDM_SUITE_INVOKE_BYVAL
+ MENUITEM "Invoke ByRef", IDM_SUITE_INVOKE_BYREF
+ MENUITEM "Invoke Multiple", IDM_SUITE_INVOKE_MULTIPLE, GRAYED
+ MENUITEM "Invoke Array", IDM_SUITE_INVOKE_SAFEARRAY
+ MENUITEM "Invoke Excepinfo", IDM_SUITE_INVOKE_EXCEPINFO
+ MENUITEM "Collections", IDM_SUITE_COLLECTION
+#if VBA2
+ MENUITEM "Early binding", IDM_SUITE_EARLY
+#endif
+
+ END
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Named", IDM_OPTIONS_NAMED
+ MENUITEM "Trace", IDM_OPTIONS_TRACE
+ MENUITEM "MultiThread", IDM_OPTIONS_MULTITHREAD
+ END
+ POPUP "Help"
+ BEGIN
+ MENUITEM "About IDispatch Test App...", IDM_HELP_ABOUT
+
+ END
+END
diff --git a/private/oleauto/tests/disptest/cearly.cpp b/private/oleauto/tests/disptest/cearly.cpp
new file mode 100644
index 000000000..17671f7c4
--- /dev/null
+++ b/private/oleauto/tests/disptest/cearly.cpp
@@ -0,0 +1,319 @@
+/***
+*cearly.cpp
+*
+* Copyright (C) 1994, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CEarlySuite test object.
+*
+*Revision History:
+*
+* [00] 30-Jun-94 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include "disptest.h"
+#include "tstsuite.h"
+#include "clsid.h"
+#include "dualtst.h"
+
+ASSERTDATA
+
+HRESULT Properties(IDualTst FAR* pdual);
+HRESULT Methods0(IDualTst FAR* pdual);
+HRESULT Methods1(IDualTst FAR* pdual);
+HRESULT ErrorInfo(IDualTst FAR* pdual);
+
+struct TEST{
+ HRESULT (*pfnTest)(IDualTst FAR*);
+ OLECHAR FAR* szName;
+};
+
+#if OE_WIN32
+# define TESTCASE(X) X, L#X
+#else
+# define TESTCASE(X) X, #X
+#endif
+
+
+static TEST rgtest[] =
+{
+ { TESTCASE(Properties) }
+ , { TESTCASE(Methods0) }
+ , { TESTCASE(Methods1) }
+ , { TESTCASE(ErrorInfo) }
+};
+
+SUITE_CONSTRUCTION_IMPL(CEarlySuite)
+
+SUITE_IUNKNOWN_IMPL(CEarlySuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CEarlySuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Early"), pbstr);
+}
+
+STDMETHODIMP
+CEarlySuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("early.log"), pbstr);
+}
+
+STDMETHODIMP
+CEarlySuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CEarlySuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ TCHAR *szFmt;
+ TCHAR buf[128];
+
+ szFmt = TSTR("Early binding - Universal marshaler");
+
+ SPRINTF(buf, szFmt, STRING(rgtest[iTest].szName));
+ *pbstr = SysAllocString(WIDESTRING(buf));
+ return NOERROR;
+}
+
+/***
+*HRESULT CEarlySuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CEarlySuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CEarlySuite::DoTest(unsigned int iTest)
+{
+ HRESULT hresult;
+ IDualTst FAR* pdual;
+ IDispatch FAR* pdisp;
+
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_FAIL);
+
+ pdisp = NULL;
+ pdual =NULL;
+
+ IfFailGo(CreateObject(OLESTR("sdisptst.cdualtst"), &pdisp), Error);
+ IfFailGo(pdisp->QueryInterface(IID_IDualTst, (void FAR* FAR*)&pdual), Error);
+ IfFailGo(rgtest[iTest].pfnTest(pdual), Error);
+
+ hresult = NOERROR;
+
+Error:;
+ if(pdisp != NULL)
+ pdisp->Release();
+ if(pdual != NULL)
+ pdual->Release();
+ return hresult;
+}
+
+HRESULT
+Properties(IDualTst FAR* pdual)
+{
+ unsigned char ui1;
+ short i2;
+ long i4;
+ float r4;
+ double r8;
+ CY cy;
+ DATE date;
+ BSTR bstr;
+ VARIANT var;
+ IDispatch FAR* pdisp;
+ HRESULT hresult;
+
+ bstr = NULL;
+ pdisp = NULL;
+ VariantInit(&var);
+
+ IfFailGo(pdual->get_ui1(&ui1), Error);
+ IfFailGo(pdual->put_ui1(ui1+1), Error);
+
+ IfFailGo(pdual->get_i2(&i2), Error);
+ IfFailGo(pdual->put_i2(i2+1), Error);
+
+ IfFailGo(pdual->get_i4(&i4), Error);
+ IfFailGo(pdual->put_i4(i4+1), Error);
+
+ IfFailGo(pdual->get_r4(&r4), Error);
+ IfFailGo(pdual->put_r4(r4+(float)1.0), Error);
+
+ IfFailGo(pdual->get_r8(&r8), Error);
+ IfFailGo(pdual->put_r8(r8+1.0), Error);
+
+ IfFailGo(pdual->get_cy(&cy), Error);
+ cy.Hi += 1;
+ cy.Lo += 1;
+ IfFailGo(pdual->put_cy(cy), Error);
+
+ IfFailGo(pdual->get_date(&date), Error);
+ IfFailGo(pdual->put_date(date+1.0), Error);
+
+ IfFailGo(pdual->get_bstr(&bstr), Error);
+ IfFailGo(pdual->put_bstr(bstr), Error);
+
+ IfFailGo(pdual->get_disp(&pdisp), Error);
+ IfFailGo(pdual->putref_disp(pdisp), Error);
+ IfFailGo(pdual->putref_disp(NULL), Error);
+
+ IfFailGo(pdual->get_var(&var), Error);
+ VariantClear(&var);
+ V_VT(&var) = VT_I2;
+ V_I2(&var) = 42;
+ IfFailGo(pdual->putref_var(var), Error);
+
+ hresult = NOERROR;
+
+Error:;
+ if(pdisp != NULL)
+ pdisp->Release();
+ SysFreeString(bstr);
+ VariantClear(&var);
+ return hresult;
+}
+
+HRESULT
+Methods0(IDualTst FAR* pdual)
+{
+ CY cy;
+ BSTR bstr;
+ VARIANT var;
+ IDispatch FAR* pdisp;
+ HRESULT hresult;
+
+ bstr = NULL;
+ pdisp = NULL;
+ VariantInit(&var);
+ MEMSET(&cy, 0, sizeof(cy));
+
+ IfFailRet(pdual->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp));
+ bstr = SysAllocString(OLESTR("A string!"));
+
+ IfFailGo(pdual->m0(41, 42, 43, 4.2, 4.3, cy, 4.4, bstr, pdisp, var), Error);
+ IfFailGo(pdual->putref_disp(NULL), Error); // cleanup cycle
+
+ hresult = NOERROR;
+
+Error:;
+ if(pdisp != NULL)
+ pdisp->Release();
+ SysFreeString(bstr);
+ VariantClear(&var);
+ return hresult;
+}
+
+HRESULT
+Methods1(IDualTst FAR* pdual)
+{
+ unsigned char ui1 = 0;
+ short i2 = 0;
+ long i4 = 0;
+ float r4 = 0;
+ double r8 = 0;
+ CY cy;
+ DATE date = 0;
+ BSTR bstr;
+ VARIANT var;
+ IDispatch FAR* pdisp;
+ HRESULT hresult;
+
+ cy.Hi = 0;
+ cy.Lo = 0;
+ bstr = NULL;
+ pdisp = NULL;
+ VariantInit(&var);
+
+ IfFailGo(pdual->m1(&ui1, &i2, &i4, &r4, &r8, &cy, &date, &bstr, &pdisp, &var), Error);
+ IfFailGo(pdual->m1(&ui1, &i2, &i4, &r4, &r8, &cy, &date, &bstr, &pdisp, &var), Error);
+ hresult = NOERROR;
+
+Error:;
+ if(pdisp != NULL)
+ pdisp->Release();
+ SysFreeString(bstr);
+ VariantClear(&var);
+ return hresult;
+}
+
+HRESULT
+ErrorInfo(IDualTst FAR* pdual)
+{
+ HRESULT hresult;
+ IErrorInfo FAR* perrinfo;
+ unsigned long dwHelpContext;
+ BSTR bstrSource, bstrDescription, bstrHelpFile;
+#if OE_WIN32
+ char rgchTemp[128]; //Unicode-to-ansi conversion buffer
+#endif
+
+ perrinfo = NULL;
+ bstrSource = SysAllocString(OLESTR("foobar - (source)"));
+ bstrDescription = SysAllocString(OLESTR("a foo type bar (description)"));
+ bstrHelpFile = SysAllocString(OLESTR("foobar.hlp"));
+
+ hresult = pdual->raise(42, bstrSource, bstrDescription, 13, bstrHelpFile);
+
+ SysFreeString(bstrSource);
+ SysFreeString(bstrDescription);
+ SysFreeString(bstrHelpFile);
+ bstrSource = NULL;
+ bstrDescription = NULL;
+ bstrHelpFile = NULL;
+
+ DbPrintf("hresult=0x%lx\n", GetScode(hresult));
+ if(GetErrorInfo(0L, &perrinfo) == NOERROR){
+ perrinfo->GetSource(&bstrSource);
+ perrinfo->GetDescription(&bstrDescription);
+ perrinfo->GetHelpFile(&bstrHelpFile);
+ perrinfo->GetHelpContext(&dwHelpContext);
+#if OE_WIN32
+ WideCharToMultiByte(CP_ACP, 0, bstrSource, SysStringLen(bstrSource)+1,
+ rgchTemp, sizeof(rgchTemp), NULL, NULL);
+ DbPrintf("Source=\"%Fs\"\n", rgchTemp);
+ WideCharToMultiByte(CP_ACP, 0, bstrDescription, SysStringLen(bstrDescription)+1,
+ rgchTemp, sizeof(rgchTemp), NULL, NULL);
+ DbPrintf("Description=\"%Fs\"\n", rgchTemp);
+ WideCharToMultiByte(CP_ACP, 0, bstrHelpFile, SysStringLen(bstrHelpFile)+1,
+ rgchTemp, sizeof(rgchTemp), NULL, NULL);
+ DbPrintf("HelpFile=\"%Fs\"\n", rgchTemp);
+#else
+ DbPrintf("Source=\"%Fs\"\n", bstrSource);
+ DbPrintf("Description=\"%Fs\"\n", bstrDescription);
+ DbPrintf("HelpFile=\"%Fs\"\n", bstrHelpFile);
+#endif
+ DbPrintf("HelpContext=%ld\n", dwHelpContext);
+ }else{
+ DbPrintf("No error info!\n");
+ }
+
+ hresult = NOERROR;
+
+ if(perrinfo != NULL)
+ perrinfo->Release();
+ SysFreeString(bstrSource);
+ SysFreeString(bstrDescription);
+ SysFreeString(bstrHelpFile);
+ return hresult;
+}
diff --git a/private/oleauto/tests/disptest/cinvex.cpp b/private/oleauto/tests/disptest/cinvex.cpp
new file mode 100644
index 000000000..d17f86294
--- /dev/null
+++ b/private/oleauto/tests/disptest/cinvex.cpp
@@ -0,0 +1,156 @@
+/***
+*cinvex.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CInvokeExcepinfoSuite test object. The
+* purpose of this object is to drive testing of the EXCEPINFO
+* remoting support.
+*
+*Revision History:
+*
+* [00] 02-Dec-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+
+extern OLECHAR FAR* g_szCExcepinfo;
+
+struct TEST{
+ HRESULT (*pfnTest)(int);
+ NAMEDESC namedesc;
+ OLECHAR FAR* szName;
+};
+
+OLECHAR FAR* rgszExcepinfo0[] = { OLESTR("excepinfo0") };
+OLECHAR FAR* rgszExcepinfo1[] = { OLESTR("excepinfo1") };
+OLECHAR FAR* rgszExcepinfo2[] = { OLESTR("excepinfo2") };
+
+HRESULT DefExcepinfoTest(int iTest);
+HRESULT DefExcepinfoTestW(int iTest);
+
+static TEST rgtest[] =
+{
+ { DefExcepinfoTest,
+ {rgszExcepinfo0, DIM(rgszExcepinfo0)},
+ OLESTR("excepinfo-0")
+ },
+
+ { DefExcepinfoTest,
+ {rgszExcepinfo1, DIM(rgszExcepinfo1)},
+ OLESTR("excepinfo-1")
+ },
+
+ { DefExcepinfoTest,
+ {rgszExcepinfo2, DIM(rgszExcepinfo2)},
+ OLESTR("excepinfo-2")
+ },
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CInvokeExcepinfoSuite)
+
+SUITE_IUNKNOWN_IMPL(CInvokeExcepinfoSuite)
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+CInvokeExcepinfoSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Invoke Excepinfo"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeExcepinfoSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("invex.log"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeExcepinfoSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CInvokeExcepinfoSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_FAIL);
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+HRESULT
+DefExcepinfoTest(int iTest)
+{
+ HRESULT hresult;
+ EXCEPINFO excepinfo;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ DISPPARAMS dispparams;
+
+
+ IfFailGo(CreateObject(g_szCExcepinfo, &pdisp), LError0);
+
+ IfFailGo(
+ GetDISPIDs(pdisp, &rgtest[iTest].namedesc, &rgdispid),
+ LError1);
+
+ dispparams.cArgs = 0;
+ dispparams.cNamedArgs = 0;
+
+ excepinfo.bstrSource = NULL;
+ excepinfo.bstrHelpFile = NULL;
+ excepinfo.bstrDescription = NULL;
+ hresult = DoInvoke(pdisp, rgdispid[0], &dispparams, NULL, &excepinfo, NULL);
+ if(GetScode(hresult) != DISP_E_EXCEPTION)
+ goto LError2;
+
+ DbPrExcepinfo(&excepinfo);
+
+ SysFreeString(excepinfo.bstrSource);
+ SysFreeString(excepinfo.bstrDescription);
+ SysFreeString(excepinfo.bstrHelpFile);
+
+ hresult = NOERROR;
+
+LError2:;
+ delete rgdispid;
+
+LError1:;
+ pdisp->Release();
+
+LError0:;
+ return hresult;
+}
+
+/***
+*HRESULT CInvokeExcepinfoSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CInvokeExcepinfoSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CInvokeExcepinfoSuite::DoTest(unsigned int iTest)
+{
+ IfFailRet(rgtest[iTest].pfnTest(iTest));
+
+ return NOERROR;
+}
+
diff --git a/private/oleauto/tests/disptest/cinvref.cpp b/private/oleauto/tests/disptest/cinvref.cpp
new file mode 100644
index 000000000..ca10f566d
--- /dev/null
+++ b/private/oleauto/tests/disptest/cinvref.cpp
@@ -0,0 +1,545 @@
+/***
+*cinvref.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CInvokeByRefSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+
+extern OLECHAR FAR* g_szCDispTst;
+
+struct TEST{
+ HRESULT (*pfnTest)(IDispatch FAR*, int, int);
+ NAMEDESC namedesc;
+ OLECHAR FAR* szName;
+ VARTYPE vt;
+};
+
+#if VBA2
+OLECHAR FAR* rgszUI1Ref[] = { OLESTR("ui1ref"), OLESTR("pbval") };
+OLECHAR FAR* rgszUI1RefC[] = { OLESTR("ui1refC"), OLESTR("pbval") };
+#endif //VBA2
+OLECHAR FAR* rgszI2Ref[] = { OLESTR("i2ref"), OLESTR("psval") };
+OLECHAR FAR* rgszI2RefC[] = { OLESTR("i2refC"), OLESTR("psval") };
+OLECHAR FAR* rgszI4Ref[] = { OLESTR("i4ref"), OLESTR("plval") };
+OLECHAR FAR* rgszI4RefC[] = { OLESTR("i4refC"), OLESTR("plval") };
+OLECHAR FAR* rgszR4Ref[] = { OLESTR("r4ref"), OLESTR("pfltval") };
+OLECHAR FAR* rgszR4RefC[] = { OLESTR("r4refC"), OLESTR("pfltval") };
+OLECHAR FAR* rgszR8Ref[] = { OLESTR("r8ref"), OLESTR("pdblval") };
+OLECHAR FAR* rgszR8RefC[] = { OLESTR("r8refC"), OLESTR("pdblval") };
+OLECHAR FAR* rgszCyRef[] = { OLESTR("cyref"), OLESTR("pcyval") };
+OLECHAR FAR* rgszCyRefC[] = { OLESTR("cyrefC"), OLESTR("pcyval") };
+OLECHAR FAR* rgszBstrRef[] = { OLESTR("bstrref"), OLESTR("pbstr") };
+OLECHAR FAR* rgszBstrRefC[] = { OLESTR("bstrrefC"), OLESTR("pbstr") };
+OLECHAR FAR* rgszWBstrRef[] = { OLESTR("wbstrref"), OLESTR("pwbstr") };
+OLECHAR FAR* rgszWBstrRefC[] = { OLESTR("wbstrrefC"), OLESTR("pwbstr") };
+OLECHAR FAR* rgszDateRef[] = { OLESTR("dateref"), OLESTR("pdate") };
+OLECHAR FAR* rgszDateRefC[] = { OLESTR("daterefC"), OLESTR("pdate") };
+OLECHAR FAR* rgszErrorRef[] = { OLESTR("scoderef"), OLESTR("pscode") };
+OLECHAR FAR* rgszErrorRefC[] = { OLESTR("scoderefC"), OLESTR("pscode") };
+OLECHAR FAR* rgszBoolRef[] = { OLESTR("boolref"), OLESTR("pbool") };
+OLECHAR FAR* rgszBoolRefC[] = { OLESTR("boolrefC"), OLESTR("pbool") };
+OLECHAR FAR* rgszDispRef[] = { OLESTR("dispref"), OLESTR("ppdisp") };
+
+HRESULT DefByRefTest(IDispatch FAR*, int, int);
+HRESULT DispByRefTest(IDispatch FAR*, int, int);
+
+#if OE_WIN32
+#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, L#Y
+#else
+#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, #Y
+#endif
+
+static TEST rgtest[] =
+{
+ // UNDONE: move this back to the end once its debugged
+ { TESTCASE(DispByRefTest, DispRef), VT_DISPATCH}
+
+ , { TESTCASE(DefByRefTest, I2Ref), VT_I2}
+ , { TESTCASE(DefByRefTest, I2RefC), VT_I2}
+#if VBA2
+ , { TESTCASE(DefByRefTest, UI1Ref), VT_UI1}
+ , { TESTCASE(DefByRefTest, UI1RefC), VT_UI1}
+#endif //VBA2
+ , { TESTCASE(DefByRefTest, I4Ref), VT_I4}
+ , { TESTCASE(DefByRefTest, I4RefC), VT_I4}
+ , { TESTCASE(DefByRefTest, R4Ref), VT_R4}
+ , { TESTCASE(DefByRefTest, R8Ref), VT_R8}
+#if OE_WIN32 && 0
+ , { TESTCASE(DefByRefTest, R4RefC), VT_R4}
+ , { TESTCASE(DefByRefTest, R8RefC), VT_R8}
+#endif
+ , { TESTCASE(DefByRefTest, CyRef), VT_CY}
+ , { TESTCASE(DefByRefTest, CyRefC), VT_CY}
+ , { TESTCASE(DefByRefTest, DateRef), VT_DATE}
+#if OE_WIN32 && 0
+ , { TESTCASE(DefByRefTest, DateRefC), VT_DATE}
+#endif
+ , { TESTCASE(DefByRefTest, BstrRef), VT_BSTR}
+ , { TESTCASE(DefByRefTest, BstrRefC), VT_BSTR}
+ , { TESTCASE(DefByRefTest, ErrorRef), VT_ERROR}
+ , { TESTCASE(DefByRefTest, ErrorRefC), VT_ERROR}
+ , { TESTCASE(DefByRefTest, BoolRef), VT_BOOL}
+ , { TESTCASE(DefByRefTest, BoolRefC), VT_BOOL}
+
+ // REVIEW: needs tests for ByRef IUnknown and IDispatch
+};
+
+SUITE_CONSTRUCTION_IMPL(CInvokeByRefSuite)
+
+SUITE_IUNKNOWN_IMPL(CInvokeByRefSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CInvokeByRefSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Invoke ByRef"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeByRefSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("invref.log"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeByRefSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CInvokeByRefSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ TCHAR *szFmt;
+ TCHAR buf[128];
+
+#if HC_MPW
+ szFmt = "IDispatch::Invoke(%s)";
+#else
+ szFmt = TSTR("IDispatch::Invoke(%Fs)");
+#endif
+
+ SPRINTF(buf, szFmt, STRING(rgtest[iTest].szName));
+ *pbstr = SysAllocString(WIDESTRING(buf));
+ return NOERROR;
+}
+
+#define VT_MAXSIZE VT_UI1 + 1
+
+VARIANT g_varRefMem[VT_MAXSIZE];
+VARIANTARG g_vargRef[VT_MAXSIZE];
+
+static HRESULT
+init()
+{
+ int i;
+ CY cy;
+ VARIANT FAR* pvarRef;
+ VARIANTARG FAR* pvarg;
+
+ for(i = 0; i < DIM(g_vargRef); ++i){
+ V_VT(&g_vargRef[i]) = VT_EMPTY;
+ V_VT(&g_varRefMem[i]) = VT_EMPTY;
+ }
+
+#define VAR_MAKE_BYREF(TYPE, VALUE) \
+ pvarRef = &g_varRefMem[VT_ ## TYPE]; \
+ pvarg = &g_vargRef[VT_ ## TYPE]; \
+ V_VT(pvarRef) = VT_ ## TYPE; \
+ V_ ## TYPE ## (pvarRef) = VALUE; \
+ V_VT(pvarg) = VT_ ## TYPE | VT_BYREF; \
+ V_BYREF(pvarg) = &V_NONE(pvarRef);
+
+#if VBA2
+ VAR_MAKE_BYREF(UI1, 41);
+#endif //VBA2
+
+ VAR_MAKE_BYREF(I2, 42);
+
+ VAR_MAKE_BYREF(I4, 43L);
+
+ VAR_MAKE_BYREF(R4, (float) 42.42);
+
+ VAR_MAKE_BYREF(R8, 43.43);
+
+ cy.Hi=107, cy.Lo=66;
+ VAR_MAKE_BYREF(CY, cy);
+
+ VAR_MAKE_BYREF(DATE, 107.66);
+
+ VAR_MAKE_BYREF(BSTR, SysAllocString(OLESTR("a binary string")));
+
+ VAR_MAKE_BYREF(ERROR, S_OK);
+
+ VAR_MAKE_BYREF(BOOL, -1);
+
+ return NOERROR;
+
+#undef VAR_MAKE_BYREF
+}
+
+static HRESULT
+clear()
+{
+ int i;
+
+ for(i = 0; i < DIM(g_vargRef); ++i)
+ IfFailRet(VariantClearAll(&g_vargRef[i]));
+
+ return NOERROR;
+}
+
+HRESULT
+DefByRefTest(IDispatch FAR* pdisp, int iTest, int fNamed)
+{
+ VARTYPE vt;
+ unsigned int uArgErr;
+ VARIANT varResult;
+ DISPID FAR* rgdispid;
+ DISPPARAMS dispparams;
+ HRESULT hresult, hresultTmp;
+ VARIANTARG vargExpected, vargExpectedRef;
+
+
+ vt = rgtest[iTest].vt;
+ ASSERT(vt < DIM(g_vargRef));
+
+ IfFailGo(init(), LError0);
+ ASSERT((V_VT(&g_vargRef[vt]) & VT_BYREF) != 0);
+
+ IfFailGo(
+ GetDISPIDs(pdisp, &rgtest[iTest].namedesc, &rgdispid),
+ LError1);
+
+ // build a variant for the expected out parameter.
+ //
+ VariantInit(&vargExpected);
+
+ MEMCPY(&vargExpectedRef, &g_varRefMem[vt], sizeof(vargExpectedRef));
+
+ V_VT(&vargExpectedRef) = vt;
+
+ // update the in value in the same way we expect the callee to...
+ //
+ switch(vt){
+#if VBA2
+ case VT_UI1:
+ ++V_UI1(&vargExpectedRef);
+ break;
+#endif //VBA2
+ case VT_I2:
+ ++V_I2(&vargExpectedRef);
+ break;
+ case VT_I4:
+ ++V_I4(&vargExpectedRef);
+ break;
+ case VT_R4:
+ V_R4(&vargExpectedRef) += (float)1.0;
+ break;
+ case VT_R8:
+ case VT_DATE:
+ V_R8(&vargExpectedRef) += 1.0;
+ break;
+ case VT_CY:
+ ++V_CY(&vargExpectedRef).Hi;
+ ++V_CY(&vargExpectedRef).Lo;
+ break;
+ case VT_BSTR:
+ V_BSTR(&vargExpectedRef) = SysAllocString(V_BSTR(&vargExpectedRef));
+#if OE_WIN32
+ _wcsupr(V_BSTR(&vargExpectedRef));
+#else
+ STRUPR(V_BSTR(&vargExpectedRef));
+#endif
+ break;
+ case VT_ERROR:
+ V_ERROR(&vargExpectedRef) = E_FAIL;
+ break;
+ case VT_BOOL:
+ V_BOOL(&vargExpectedRef) = 0;
+ break;
+ default:
+ ASSERT(UNREACHED);
+ break;
+ }
+
+ V_VT(&vargExpected) = VT_BYREF | vt;
+ V_BYREF(&vargExpected) = &V_NONE(&vargExpectedRef);
+
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = &g_vargRef[rgtest[iTest].vt];
+ if(fNamed){
+ dispparams.cNamedArgs = 1;
+ dispparams.rgdispidNamedArgs = &rgdispid[1];
+ }else{
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ }
+
+ uArgErr = 0;
+ VariantInit(&varResult);
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, &uArgErr),
+ LError2);
+
+ if(V_VT(&varResult) != VT_ERROR
+ || V_ERROR(&varResult) != NOERROR
+ || !VariantCompare(&dispparams.rgvarg[0], &vargExpected))
+ {
+ hresult = RESULT(E_FAIL);
+ goto LError2;
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ hresultTmp = VariantClear(&varResult);
+ ASSERT(hresultTmp == NOERROR);
+
+ hresultTmp = VariantClearAll(&dispparams.rgvarg[0]);
+ ASSERT(hresultTmp == NOERROR);
+
+ hresultTmp = VariantClearAll(&vargExpected);
+ ASSERT(hresultTmp == NOERROR);
+
+ delete rgdispid;
+
+LError1:;
+ hresultTmp = clear();
+ ASSERT(hresultTmp == NOERROR);
+
+LError0:;
+ return hresult;
+}
+
+/***
+*HRESULT CInvokeByRefSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CInvokeByRefSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CInvokeByRefSuite::DoTest(unsigned int iTest)
+{
+ HRESULT hresult;
+ IDispatch FAR* pdisp;
+#if OE_WIN32 && 0
+ IDispatchW FAR* pdispW;
+#endif
+
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_FAIL);
+
+ pdisp = NULL;
+
+ IfFailRet(CreateObject(g_szCDispTst, &pdisp));
+ IfFailGo(rgtest[iTest].pfnTest(pdisp, iTest, FALSE), LError0);
+ IfFailGo(rgtest[iTest].pfnTest(pdisp, iTest, TRUE), LError0);
+
+ hresult = NOERROR;
+
+LError0:;
+ if(pdisp != NULL)
+ pdisp->Release();
+
+ return hresult;
+}
+
+
+//
+// A little do-nothing IDispatch object
+//
+
+class CNopDisp : public IDispatch
+{
+public:
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(unsigned long, AddRef)(void);
+ STDMETHOD_(unsigned long, Release)(void);
+
+ STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo);
+
+ STDMETHOD(GetTypeInfo)(unsigned int itinfo,
+ LCID lcid,
+ ITypeInfo FAR* FAR* pptinfo);
+
+ STDMETHOD(GetIDsOfNames)(REFIID riid,
+ OLECHAR FAR* FAR* rgszNames,
+ unsigned int cNames,
+ LCID lcid,
+ DISPID FAR* rgdispid);
+
+ STDMETHOD(Invoke)(DISPID dispidMember,
+ REFIID riid,
+ LCID lcid,
+ unsigned short wFlags,
+ DISPPARAMS FAR* pdispparams,
+ VARIANT FAR* pvarResult,
+ EXCEPINFO FAR* pexcepinfo,
+ unsigned int FAR* puArgErr);
+
+ CNopDisp();
+
+private:
+ unsigned long m_cRefs;
+};
+
+CNopDisp::CNopDisp()
+{
+ m_cRefs = 1;
+}
+
+STDMETHODIMP
+CNopDisp::QueryInterface(REFIID riid, void FAR* FAR* ppv)
+{
+ if(riid == IID_IUnknown || riid == IID_IDispatch){
+ *ppv = this;
+ }else{
+ *ppv = NULL;
+ return RESULT(E_NOINTERFACE);
+ }
+ ++m_cRefs;
+ return NOERROR;
+}
+
+STDMETHODIMP_(unsigned long)
+CNopDisp::AddRef()
+{
+ return ++m_cRefs;
+}
+
+STDMETHODIMP_(unsigned long)
+CNopDisp::Release()
+{
+ if(--m_cRefs == 0){
+ delete this;
+ return 0;
+ }
+ return m_cRefs;
+}
+
+STDMETHODIMP
+CNopDisp::GetTypeInfoCount(unsigned int FAR* pctinfo)
+{
+ *pctinfo = 0;
+ return NOERROR;
+}
+
+STDMETHODIMP
+CNopDisp::GetTypeInfo(unsigned int itinfo,
+ LCID lcid,
+ ITypeInfo FAR* FAR* pptinfo)
+{
+ return RESULT(DISP_E_BADINDEX); // we dont return any
+}
+
+STDMETHODIMP
+CNopDisp::GetIDsOfNames(REFIID riid,
+ OLECHAR FAR* FAR* rgszNames,
+ unsigned int cNames,
+ LCID lcid,
+ DISPID FAR* rgdispid)
+{
+ return RESULT(DISP_E_UNKNOWNNAME); // because there are no names
+}
+
+STDMETHODIMP
+CNopDisp::Invoke(DISPID dispidMember,
+ REFIID riid,
+ LCID lcid,
+ unsigned short wFlags,
+ DISPPARAMS FAR* pdispparams,
+ VARIANT FAR* pvarResult,
+ EXCEPINFO FAR* pexcepinfo,
+ unsigned int FAR* puArgErr)
+{
+ return RESULT(DISP_E_MEMBERNOTFOUND); // because there are no members
+}
+
+
+
+// Tests passing a ByRef IDispatch*
+HRESULT
+DispByRefTest(IDispatch FAR* pdisp, int unused1, int unused2)
+{
+ DISPID dispid;
+ HRESULT hresult;
+ VARIANTARG varg;
+ VARIANT varResult;
+ unsigned int uArgErr = 0;
+ DISPPARAMS dispparams;
+ OLECHAR FAR* rgszNames[1];
+ IDispatch FAR* pdispLocal;
+
+ pdispLocal = NULL;
+
+ if((pdispLocal = new CNopDisp()) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ rgszNames[0] = OLESTR("dispref");
+ IfFailGo(pdisp->GetIDsOfNames(IID_NULL,
+ rgszNames, 1,
+ LOCALE_USER_DEFAULT,
+ &dispid), Error);
+
+
+ V_VT(&varg) = VT_BYREF | VT_DISPATCH;
+ V_DISPATCHREF(&varg) = &pdispLocal;
+
+ dispparams.cArgs = 1;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgvarg = &varg;
+ dispparams.rgdispidNamedArgs = NULL;
+
+ VariantInit(&varResult);
+
+ IfFailGo(DoInvoke(pdisp,
+ dispid,
+ &dispparams,
+ &varResult,
+ NULL,
+ &uArgErr), Error);
+
+ if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR){
+ hresult = RESULT(E_FAIL);
+ goto Error;
+ }
+
+ hresult = NOERROR;
+
+Error:;
+ if(pdispLocal != NULL)
+ pdispLocal->Release();
+ return hresult;
+}
+
+
diff --git a/private/oleauto/tests/disptest/cinvsary.cpp b/private/oleauto/tests/disptest/cinvsary.cpp
new file mode 100644
index 000000000..d9a24bd74
--- /dev/null
+++ b/private/oleauto/tests/disptest/cinvsary.cpp
@@ -0,0 +1,641 @@
+/***
+*cinvsary.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CInvokeSafeArraySuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+
+#if VBA2
+static OLECHAR FAR* rgszUI1SafeArray[] = {OLESTR("ui1safearray"), OLESTR("psa")};
+#endif //VBA2
+static OLECHAR FAR* rgszI2SafeArray[] = {OLESTR("i2safearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszI4SafeArray[] = {OLESTR("i4safearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszR4SafeArray[] = {OLESTR("r4safearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszR8SafeArray[] = {OLESTR("r8safearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszCySafeArray[] = {OLESTR("cysafearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszDateSafeArray[] = {OLESTR("datesafearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszBstrSafeArray[] = {OLESTR("bstrsafearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszScodeSafeArray[] = {OLESTR("scodesafearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszBoolSafeArray[] = {OLESTR("boolsafearray"), OLESTR("psa")};
+static OLECHAR FAR* rgszVarSafeArray[] = {OLESTR("varsafearray"), OLESTR("psa")};
+// REVIEW: DispSafeArray() ?
+
+#if VBA2
+static OLECHAR FAR* rgszUI1SafeArrayRef[] = {OLESTR("ui1safearrayref"), OLESTR("psa")};
+#endif //VBA2
+static OLECHAR FAR* rgszI2SafeArrayRef[] = {OLESTR("i2safearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszI4SafeArrayRef[] = {OLESTR("i4safearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszR4SafeArrayRef[] = {OLESTR("r4safearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszR8SafeArrayRef[] = {OLESTR("r8safearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszCySafeArrayRef[] = {OLESTR("cysafearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszDateSafeArrayRef[] = {OLESTR("datesafearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszBstrSafeArrayRef[] = {OLESTR("bstrsafearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszScodeSafeArrayRef[] = {OLESTR("scodesafearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszBoolSafeArrayRef[] = {OLESTR("boolsafearrayref"), OLESTR("psa")};
+static OLECHAR FAR* rgszVarSafeArrayRef[] = {OLESTR("varsafearrayref"), OLESTR("psa")};
+
+#if VBA2
+static OLECHAR FAR* rgszUI1SafeArrayErase[] = {OLESTR("ui1safearrayerase"), OLESTR("psa")};
+#endif //VBA2
+static OLECHAR FAR* rgszI2SafeArrayErase[] = {OLESTR("i2safearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszI4SafeArrayErase[] = {OLESTR("i4safearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszR4SafeArrayErase[] = {OLESTR("r4safearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszR8SafeArrayErase[] = {OLESTR("r8safearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszCySafeArrayErase[] = {OLESTR("cysafearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszDateSafeArrayErase[] = {OLESTR("datesafearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszBstrSafeArrayErase[] = {OLESTR("bstrsafearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszScodeSafeArrayErase[] = {OLESTR("scodesafearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszBoolSafeArrayErase[] = {OLESTR("boolsafearrayerase"), OLESTR("psa")};
+static OLECHAR FAR* rgszVarSafeArrayErase[] = {OLESTR("varsafearrayerase"), OLESTR("psa")};
+
+#if VBA2
+static OLECHAR FAR* rgszUI1SafeArrayAlloc[] = {OLESTR("ui1safearrayalloc"), OLESTR("psa")};
+#endif //VBA2
+static OLECHAR FAR* rgszI2SafeArrayAlloc[] = {OLESTR("i2safearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszI4SafeArrayAlloc[] = {OLESTR("i4safearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszR4SafeArrayAlloc[] = {OLESTR("r4safearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszR8SafeArrayAlloc[] = {OLESTR("r8safearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszCySafeArrayAlloc[] = {OLESTR("cysafearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszDateSafeArrayAlloc[] = {OLESTR("datesafearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszBstrSafeArrayAlloc[] = {OLESTR("bstrsafearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszScodeSafeArrayAlloc[] = {OLESTR("scodesafearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszBoolSafeArrayAlloc[] = {OLESTR("boolsafearrayalloc"), OLESTR("psa")};
+static OLECHAR FAR* rgszVarSafeArrayAlloc[] = {OLESTR("varsafearrayalloc"), OLESTR("psa")};
+
+extern OLECHAR FAR* g_szCSArray;
+
+// REVIEW: DispSafeArrayRef() ?
+
+struct TEST {
+ HRESULT (*pfnTest)(TEST FAR* ptinfo);
+ NAMEDESC namedesc;
+ OLECHAR FAR* szName; // test name
+ VARTYPE vt;
+};
+
+HRESULT DefSafeArrayTest(TEST FAR* ptinfo);
+HRESULT EraseSafeArrayTest(TEST FAR* ptinfo);
+HRESULT AllocSafeArrayTest(TEST FAR* ptinfo);
+HRESULT SafeArrayCalleeRedim(TEST FAR* ptinfoDummy);
+HRESULT SafeArrayReturn(TEST FAR* ptinfoDummy);
+
+#if OE_WIN32
+#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, L#Y
+#else
+#define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, #Y
+#endif
+
+static TEST rgtest[] =
+{
+ {TESTCASE(DefSafeArrayTest, I2SafeArray), VT_I2}
+#if VBA2
+ , {TESTCASE(DefSafeArrayTest, UI1SafeArray), VT_UI1}
+#endif //VBA2
+ , {TESTCASE(DefSafeArrayTest, I4SafeArray), VT_I4}
+ , {TESTCASE(DefSafeArrayTest, R4SafeArray), VT_R4}
+ , {TESTCASE(DefSafeArrayTest, R8SafeArray), VT_R8}
+ , {TESTCASE(DefSafeArrayTest, CySafeArray), VT_CY}
+ , {TESTCASE(DefSafeArrayTest, DateSafeArray), VT_DATE}
+ , {TESTCASE(DefSafeArrayTest, BstrSafeArray), VT_BSTR}
+ , {TESTCASE(DefSafeArrayTest, ScodeSafeArray), VT_ERROR}
+ , {TESTCASE(DefSafeArrayTest, BoolSafeArray), VT_BOOL}
+ , {TESTCASE(DefSafeArrayTest, VarSafeArray), VT_VARIANT}
+
+ , {TESTCASE(DefSafeArrayTest, I2SafeArrayRef), VT_BYREF|VT_I2}
+#if VBA2
+ , {TESTCASE(DefSafeArrayTest, UI1SafeArrayRef), VT_BYREF|VT_UI1}
+#endif //VBA2
+ , {TESTCASE(DefSafeArrayTest, I4SafeArrayRef), VT_BYREF|VT_I4}
+ , {TESTCASE(DefSafeArrayTest, R4SafeArrayRef), VT_BYREF|VT_R4}
+ , {TESTCASE(DefSafeArrayTest, R8SafeArrayRef), VT_BYREF|VT_R8}
+ , {TESTCASE(DefSafeArrayTest, CySafeArrayRef), VT_BYREF|VT_CY}
+ , {TESTCASE(DefSafeArrayTest, DateSafeArrayRef), VT_BYREF|VT_DATE}
+ , {TESTCASE(DefSafeArrayTest, BstrSafeArrayRef), VT_BYREF|VT_BSTR}
+ , {TESTCASE(DefSafeArrayTest, ScodeSafeArrayRef), VT_BYREF|VT_ERROR}
+ , {TESTCASE(DefSafeArrayTest, BoolSafeArrayRef), VT_BYREF|VT_BOOL}
+ , {TESTCASE(DefSafeArrayTest, VarSafeArrayRef), VT_BYREF|VT_VARIANT}
+
+ , {SafeArrayCalleeRedim, {NULL, 0}, OLESTR("SafeArray callee redim"), 0}
+ , {SafeArrayReturn, {NULL, 0}, OLESTR("SafeArray return"), 0}
+
+ , {TESTCASE(EraseSafeArrayTest, I2SafeArrayErase), VT_BYREF|VT_I2}
+#if VBA2
+ , {TESTCASE(EraseSafeArrayTest, UI1SafeArrayErase), VT_BYREF|VT_UI1}
+#endif //VBA2
+ , {TESTCASE(EraseSafeArrayTest, I4SafeArrayErase), VT_BYREF|VT_I4}
+ , {TESTCASE(EraseSafeArrayTest, R4SafeArrayErase), VT_BYREF|VT_R4}
+ , {TESTCASE(EraseSafeArrayTest, R8SafeArrayErase), VT_BYREF|VT_R8}
+ , {TESTCASE(EraseSafeArrayTest, CySafeArrayErase), VT_BYREF|VT_CY}
+ , {TESTCASE(EraseSafeArrayTest, DateSafeArrayErase),VT_BYREF|VT_DATE}
+ , {TESTCASE(EraseSafeArrayTest, BstrSafeArrayErase),VT_BYREF|VT_BSTR}
+ , {TESTCASE(EraseSafeArrayTest, ScodeSafeArrayErase),VT_BYREF|VT_ERROR}
+ , {TESTCASE(EraseSafeArrayTest, BoolSafeArrayErase),VT_BYREF|VT_BOOL}
+ , {TESTCASE(EraseSafeArrayTest, VarSafeArrayErase), VT_BYREF|VT_VARIANT}
+
+ , {TESTCASE(AllocSafeArrayTest, I2SafeArrayAlloc), VT_BYREF|VT_I2}
+#if VBA2
+ , {TESTCASE(AllocSafeArrayTest, UI1SafeArrayAlloc), VT_BYREF|VT_UI1}
+#endif //VBA2
+ , {TESTCASE(AllocSafeArrayTest, I4SafeArrayAlloc), VT_BYREF|VT_I4}
+ , {TESTCASE(AllocSafeArrayTest, R4SafeArrayAlloc), VT_BYREF|VT_R4}
+ , {TESTCASE(AllocSafeArrayTest, R8SafeArrayAlloc), VT_BYREF|VT_R8}
+ , {TESTCASE(AllocSafeArrayTest, CySafeArrayAlloc), VT_BYREF|VT_CY}
+ , {TESTCASE(AllocSafeArrayTest, DateSafeArrayAlloc),VT_BYREF|VT_DATE}
+ , {TESTCASE(AllocSafeArrayTest, BstrSafeArrayAlloc),VT_BYREF|VT_BSTR}
+ , {TESTCASE(AllocSafeArrayTest, ScodeSafeArrayAlloc),VT_BYREF|VT_ERROR}
+ , {TESTCASE(AllocSafeArrayTest, BoolSafeArrayAlloc),VT_BYREF|VT_BOOL}
+ , {TESTCASE(AllocSafeArrayTest, VarSafeArrayAlloc), VT_BYREF|VT_VARIANT}
+};
+
+static SARRAYDESC
+rgsarraydesc[] =
+{
+ {0, {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{2,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{1024,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{2,0}, {2,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{32,0}, {32,0}, {0,0}, {0,0}, {0,0}}}
+ , {3, {{2,0}, {2,0}, {2,0}, {0,0}, {0,0}}}
+ , {3, {{10,0}, {10,0}, {10,0}, {0,0}, {0,0}}}
+ , {4, {{2,0}, {2,0}, {2,0}, {2,0}, {0,0}}}
+ , {4, {{6,0}, {6,0}, {6,0}, {6,0}, {0,0}}}
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CInvokeSafeArraySuite)
+
+SUITE_IUNKNOWN_IMPL(CInvokeSafeArraySuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CInvokeSafeArraySuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Invoke SafeArray"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeSafeArraySuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("invsary.log"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeSafeArraySuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CInvokeSafeArraySuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return BuildBstr(
+ pbstr,
+ rgtest[iTest].szName);
+}
+
+/***
+*HRESULT CInvokeSafeArraySuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CInvokeSafeArraySuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CInvokeSafeArraySuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ IfFailRet(rgtest[iTest].pfnTest(&rgtest[iTest]));
+ return NOERROR;
+}
+
+HRESULT
+DefSafeArrayTest(TEST FAR* ptinfo)
+{
+ long ofs;
+ unsigned long rcnt;
+ int i, fNames;
+ HRESULT hresult;
+ VARTYPE vt, vtBase;
+ VARIANT varResult;
+ SAFEARRAY FAR* psa;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ VARIANTARG rgvarg[1];
+ DISPPARAMS dispparams;
+ SARRAYDESC FAR* psadesc;
+
+
+ // REVIEW : This is really ugly! The use of templates or abstract
+ // classes would be much cleaner.
+
+ vt = ptinfo->vt;
+ vtBase = vt & ~VT_BYREF;
+
+ // if this is a ByRef array test then the "identity offset" is 1,
+ // because we know that all ByRef methods that we invoke add 1
+ // to each element of their given array. (this is how the test
+ // is defined).
+ //
+ ofs = (vt & VT_BYREF) ? 1 : 0;
+
+ IfFailRet(CreateObject(g_szCSArray, &pdisp));
+ IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
+
+ VariantInit(&varResult);
+ for(fNames = 0; fNames <= 1; ++fNames)
+ {
+ for(i = 0; i < DIM(rgsarraydesc); ++i)
+ {
+ psadesc = &rgsarraydesc[i];
+
+ if(psadesc->cDims == 0){
+ psa = NULL;
+ }else{
+ IfFailGo(SafeArrayCreateIdentity(vtBase, psadesc, &psa), LError2);
+ }
+
+ V_VT(rgvarg) = VT_ARRAY | vt;
+ if(vt & VT_BYREF){
+ V_ARRAYREF(rgvarg) = &psa;
+ }else{
+ V_ARRAY(rgvarg) = psa;
+ }
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = rgvarg;
+
+ if(fNames){
+ dispparams.cNamedArgs = 1;
+ dispparams.rgdispidNamedArgs = &rgdispid[1];
+ }else{
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ }
+
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError2);
+
+ if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
+ hresult = RESULT(E_FAIL);
+
+ VariantClear(&varResult);
+
+ if(HRESULT_FAILED(hresult))
+ goto LError2;
+ if(psa != NULL){
+ IfFailGo(SafeArrayValidateIdentity(vtBase, psa, ofs), LError2);
+ IfFailGo(SafeArrayDestroy(psa), LError2);
+ }
+ }
+ }
+
+ hresult = NOERROR;
+
+
+LError2:;
+ delete rgdispid;
+
+LError1:;
+ rcnt = pdisp->Release();
+ //ASSERT(rcnt == 0);
+ return hresult;
+}
+
+// Call ByRef SafeArray methods where the callee erases the given array
+//
+HRESULT
+EraseSafeArrayTest(TEST FAR* ptinfo)
+{
+ int i, fNames;
+ HRESULT hresult;
+ unsigned long rcnt;
+ VARTYPE vt, vtBase;
+ VARIANT varResult;
+ SAFEARRAY FAR* psa;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ VARIANTARG rgvarg[1];
+ DISPPARAMS dispparams;
+ SARRAYDESC FAR* psadesc;
+
+ vt = ptinfo->vt;
+ vtBase = vt & ~VT_BYREF;
+
+ IfFailRet(CreateObject(g_szCSArray, &pdisp));
+ IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
+
+ VariantInit(&varResult);
+ for(fNames = 0; fNames <= 1; ++fNames)
+ {
+ for(i = 0; i < DIM(rgsarraydesc); ++i)
+ {
+ psadesc = &rgsarraydesc[i];
+
+ if(psadesc->cDims == 0){
+ psa = NULL;
+ }else{
+ IfFailGo(SafeArrayCreateIdentity(vtBase, psadesc, &psa), LError2);
+ }
+
+ ASSERT((vt & VT_BYREF) != 0);
+ V_VT(rgvarg) = VT_ARRAY | vt;
+ V_ARRAYREF(rgvarg) = &psa;
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = rgvarg;
+
+ if(fNames){
+ dispparams.cNamedArgs = 1;
+ dispparams.rgdispidNamedArgs = &rgdispid[1];
+ }else{
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ }
+
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError2);
+
+ if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
+ hresult = RESULT(E_FAIL);
+
+ VariantClear(&varResult);
+
+ if(HRESULT_FAILED(hresult))
+ goto LError2;
+
+ // These methods are supposed to erase the passed array
+ if(*V_ARRAYREF(&dispparams.rgvarg[0]) != NULL){
+ hresult = RESULT(E_FAIL);
+ goto LError2;
+ }
+ }
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ delete rgdispid;
+
+LError1:;
+ rcnt = pdisp->Release();
+ //ASSERT(rcnt == 0);
+ return hresult;
+}
+
+// Call ByRef SafeArray methods where the callee erases the given array
+//
+HRESULT
+AllocSafeArrayTest(TEST FAR* ptinfo)
+{
+ unsigned long rcnt;
+ int i, fNames;
+ HRESULT hresult;
+ VARTYPE vt, vtBase;
+ VARIANT varResult;
+ SAFEARRAY FAR* psa;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ VARIANTARG rgvarg[1];
+ DISPPARAMS dispparams;
+ SARRAYDESC FAR* psadesc;
+
+ vt = ptinfo->vt;
+ vtBase = vt & ~VT_BYREF;
+
+ IfFailRet(CreateObject(g_szCSArray, &pdisp));
+ IfFailGo(GetDISPIDs(pdisp, &ptinfo->namedesc, &rgdispid), LError1);
+
+ VariantInit(&varResult);
+ for(fNames = 0; fNames <= 1; ++fNames)
+ {
+ for(i = 0; i < DIM(rgsarraydesc); ++i)
+ {
+ psadesc = &rgsarraydesc[i];
+
+ ASSERT((vt & VT_BYREF) != 0);
+
+ psa = NULL;
+ V_VT(rgvarg) = VT_ARRAY | vt;
+ V_ARRAYREF(rgvarg) = &psa;
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = rgvarg;
+
+ if(fNames){
+ dispparams.cNamedArgs = 1;
+ dispparams.rgdispidNamedArgs = &rgdispid[1];
+ }else{
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ }
+
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError2);
+
+ if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
+ hresult = RESULT(E_FAIL);
+
+ VariantClear(&varResult);
+
+ if(HRESULT_FAILED(hresult))
+ goto LError2;
+
+ // These methods are supposed to allocate an array, and return
+ // via the out param.
+ psa = *V_ARRAYREF(&dispparams.rgvarg[0]);
+ if(psa == NULL){
+ hresult = RESULT(E_FAIL);
+ goto LError2;
+ }
+ IfFailGo(SafeArrayValidateIdentity(vtBase, psa, 0L), LError2);
+ IfFailGo(SafeArrayDestroy(psa), LError2);
+ }
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ delete rgdispid;
+
+LError1:;
+ rcnt = pdisp->Release();
+ //ASSERT(rcnt == 0);
+ return hresult;
+}
+
+HRESULT
+SafeArrayCalleeRedim(TEST FAR* ptinfoDummy)
+{
+ int i;
+ unsigned long rcnt;
+ VARTYPE vt;
+ HRESULT hresult;
+ SAFEARRAY FAR* psa;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ VARIANTARG rgvarg[2];
+ DISPPARAMS dispparams;
+ VARIANT varResult;
+ SARRAYDESC FAR* psadesc;
+static OLECHAR FAR* rgszNames[] = {OLESTR("safearrayredim"), OLESTR("vt"), OLESTR("ppsa")};
+static NAMEDESC namedesc = {rgszNames, DIM(rgszNames)};
+
+ UNUSED(ptinfoDummy);
+
+ vt = VT_VARIANT;
+
+ IfFailRet(CreateObject(g_szCSArray, &pdisp));
+ IfFailGo(GetDISPIDs(pdisp, &namedesc, &rgdispid), LError1);
+
+ VariantInit(&varResult);
+
+ for(i = 0; i < DIM(rgsarraydesc); ++i){
+ psadesc = &rgsarraydesc[i];
+
+ if(psadesc->cDims == 0) // ignore this one
+ continue;
+
+ IfFailGo(SafeArrayCreateIdentity(vt, psadesc, &psa), LError2);
+
+ V_VT(&rgvarg[0]) = VT_ARRAY | VT_BYREF | vt;
+ V_ARRAYREF(&rgvarg[0]) = &psa;
+
+ V_VT(&rgvarg[1]) = VT_I2;
+ V_I2(&rgvarg[1]) = vt;
+
+ dispparams.cArgs = 2;
+ dispparams.rgvarg = rgvarg;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError2);
+
+ if(V_VT(&varResult) != VT_ERROR || V_ERROR(&varResult) != NOERROR)
+ hresult = RESULT(E_FAIL);
+
+ VariantClear(&varResult);
+
+ if(HRESULT_FAILED(hresult))
+ goto LError2;
+ IfFailGo(SafeArrayValidateIdentity(vt, psa, 0L), LError2);
+ IfFailGo(SafeArrayDestroy(psa), LError2);
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ delete rgdispid;
+
+LError1:;
+ rcnt = pdisp->Release();
+ //ASSERT(rcnt == 0);
+ return hresult;
+}
+
+// test invoking a method that returns a SafeArray
+HRESULT
+SafeArrayReturn(TEST FAR* ptinfoDummy)
+{
+ unsigned long rcnt;
+ VARTYPE vt;
+ NAMEDESC namedesc;
+ SARRAYDESC sadesc;
+ VARIANT varResult;
+ SAFEARRAY FAR* psa;
+ DISPID FAR* rgdispid;
+ IDispatch FAR* pdisp;
+ VARIANTARG rgvarg[2];
+ DISPPARAMS dispparams;
+ HRESULT hresult, hrTmp;
+
+static OLECHAR FAR* rgszNames[] = {OLESTR("i2safearrayret"), OLESTR("var")};
+
+ UNUSED(ptinfoDummy);
+
+ namedesc.rgszNames = rgszNames;
+ namedesc.cNames = DIM(rgszNames);
+
+ sadesc.cDims = 1;
+ sadesc.rgsabound[0].lLbound = 0;
+ sadesc.rgsabound[0].cElements = 2;
+
+ vt = VT_I2;
+ psa = NULL;
+ rgdispid = NULL;
+ VariantInit(&varResult);
+
+ IfFailGo(CreateObject(g_szCSArray, &pdisp), LError0);
+ IfFailGo(GetDISPIDs(pdisp, &namedesc, &rgdispid), LError0);
+
+ IfFailGo(SafeArrayCreateIdentity(vt, &sadesc, &psa), LError0);
+
+ V_VT(&rgvarg[0]) = VT_ARRAY | vt;
+ V_ARRAY(&rgvarg[0]) = psa;
+
+ dispparams.cArgs = 1;
+ dispparams.rgvarg = rgvarg;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+
+ IfFailGo(DoInvoke(pdisp, rgdispid[0], &dispparams,
+ &varResult, NULL, NULL),
+ LError0);
+ if(V_VT(&varResult) != (VT_ARRAY | VT_I2)){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+
+ IfFailGo(SafeArrayValidateIdentity(vt, psa, 0L), LError0);
+
+ hresult = NOERROR;
+
+LError0:;
+ VariantClear(&varResult);
+
+ if(psa != NULL){
+ hrTmp = SafeArrayDestroy(psa);
+ ASSERT(hrTmp == NOERROR);
+ }
+
+ if(pdisp != NULL){
+ rcnt = pdisp->Release();
+ //ASSERT(rcnt == 0);
+ }
+ if(rgdispid != NULL)
+ delete rgdispid;
+
+ return hresult;
+}
diff --git a/private/oleauto/tests/disptest/cinvval.cpp b/private/oleauto/tests/disptest/cinvval.cpp
new file mode 100644
index 000000000..3ec3245eb
--- /dev/null
+++ b/private/oleauto/tests/disptest/cinvval.cpp
@@ -0,0 +1,571 @@
+/***
+*cinvval.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CInvokeByValSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+extern OLECHAR FAR* g_szCDispTst;
+
+struct TEST{
+ HRESULT (*pfnTest)(IDispatch FAR*, int, int);
+ NAMEDESC namedesc;
+ OLECHAR FAR* szName;
+};
+
+OLECHAR FAR* rgszHello[] = { OLESTR("hello") };
+#if VBA2
+OLECHAR FAR* rgszUI1[] = { OLESTR("ui1"), OLESTR("bval") };
+OLECHAR FAR* rgszUI1C[] = { OLESTR("ui1C"), OLESTR("bval") };
+#endif //VBA2
+OLECHAR FAR* rgszI2[] = { OLESTR("i2"), OLESTR("sval") };
+OLECHAR FAR* rgszI2C[] = { OLESTR("i2C"), OLESTR("sval") };
+OLECHAR FAR* rgszI4[] = { OLESTR("i4"), OLESTR("lval") };
+OLECHAR FAR* rgszI4C[] = { OLESTR("i4C"), OLESTR("lval") };
+OLECHAR FAR* rgszR4[] = { OLESTR("r4"), OLESTR("fltval") };
+OLECHAR FAR* rgszR4C[] = { OLESTR("r4C"), OLESTR("fltval") };
+OLECHAR FAR* rgszR8[] = { OLESTR("r8"), OLESTR("dblval") };
+OLECHAR FAR* rgszR8C[] = { OLESTR("r8C"), OLESTR("dblval") };
+OLECHAR FAR* rgszCy[] = { OLESTR("cy"), OLESTR("cyval") };
+OLECHAR FAR* rgszCyC[] = { OLESTR("cyC"), OLESTR("cyval") };
+OLECHAR FAR* rgszDate[] = { OLESTR("date"), OLESTR("date") };
+OLECHAR FAR* rgszDateC[] = { OLESTR("dateC"), OLESTR("date") };
+OLECHAR FAR* rgszBstr[] = { OLESTR("bstr"), OLESTR("bstr") };
+OLECHAR FAR* rgszBstrC[] = { OLESTR("bstrC"), OLESTR("bstr") };
+OLECHAR FAR* rgszScode[] = { OLESTR("scode"), OLESTR("scode") };
+OLECHAR FAR* rgszScodeC[] = { OLESTR("scodeC"), OLESTR("scode") };
+OLECHAR FAR* rgszBool[] = { OLESTR("bool"), OLESTR("bool") };
+OLECHAR FAR* rgszBoolC[] = { OLESTR("boolC"), OLESTR("bool") };
+OLECHAR FAR* rgszVariant[] = { OLESTR("var"), OLESTR("varg") };
+OLECHAR FAR* rgszVariantC[] = { OLESTR("varC"), OLESTR("varg") };
+OLECHAR FAR* rgszDispatch[] = { OLESTR("NewCDispTst") };
+OLECHAR FAR* rgszDispatchC[]= { OLESTR("NewCDispTstC") };
+
+OLECHAR FAR* rgszStdI2I4R4R8[] = {
+ OLESTR("stdI2I4R4R8")
+#if VBA2
+ , OLESTR("bval")
+#endif //VBA2
+ , OLESTR("sval")
+ , OLESTR("lval")
+ , OLESTR("fltval")
+ , OLESTR("dblval")
+};
+OLECHAR FAR* rgszAltI2I4R4R8[] = {
+ OLESTR("altI2I4R4R8")
+#if VBA2
+ , OLESTR("bval")
+#endif //VBA2
+ , OLESTR("sval")
+ , OLESTR("lval")
+ , OLESTR("fltval")
+ , OLESTR("dblval")
+};
+
+OLECHAR FAR* rgszStdAll[] = {
+ OLESTR("stdall")
+#if VBA2
+ , OLESTR("bval")
+#endif //VBA2
+ , OLESTR("sval")
+ , OLESTR("lval")
+ , OLESTR("fltval")
+ , OLESTR("dblval")
+ , OLESTR("cyval")
+ , OLESTR("date")
+ , OLESTR("bstr")
+ , OLESTR("sc")
+ , OLESTR("bool")
+};
+OLECHAR FAR* rgszAltAll[] = {
+ OLESTR("altall")
+#if VBA2
+ , OLESTR("bval")
+#endif //VBA2
+ , OLESTR("sval")
+ , OLESTR("lval")
+ , OLESTR("fltval")
+ , OLESTR("dblval")
+ , OLESTR("cyval")
+ , OLESTR("date")
+ , OLESTR("bstr")
+ , OLESTR("sc")
+ , OLESTR("bool")
+};
+
+HRESULT InvokeByValHello(IDispatch FAR*, int, int);
+HRESULT InvokeByValDefault(IDispatch FAR*, int, int);
+HRESULT InvokeByValDisp(IDispatch FAR*, int, int);
+
+#if OE_WIN32
+# define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, L#Y
+#else
+# define TESTCASE(X,Y) X, {rgsz ## Y, DIM( rgsz ## Y)}, #Y
+#endif
+
+
+static TEST rgtest[] =
+{
+ { TESTCASE(InvokeByValHello,Hello) }
+#if VBA2
+ , { TESTCASE(InvokeByValDefault,UI1) }
+ , { TESTCASE(InvokeByValDefault,UI1C) }
+#endif //VBA2
+ , { TESTCASE(InvokeByValDefault,I2) }
+ , { TESTCASE(InvokeByValDefault,I2C) }
+ , { TESTCASE(InvokeByValDefault,I4) }
+ , { TESTCASE(InvokeByValDefault,I4C) }
+#if !OE_WIN16
+ , { TESTCASE(InvokeByValDefault,R4) }
+#endif
+ , { TESTCASE(InvokeByValDefault,R4C) }
+
+#if !OE_WIN16
+ , { TESTCASE(InvokeByValDefault,R8) }
+#endif
+ , { TESTCASE(InvokeByValDefault,R8C) }
+
+ , { TESTCASE(InvokeByValDefault,Cy) }
+ , { TESTCASE(InvokeByValDefault,CyC) }
+#if !OE_WIN16
+ , { TESTCASE(InvokeByValDefault,Date) }
+#endif
+
+ , { TESTCASE(InvokeByValDefault,DateC) }
+
+ , { TESTCASE(InvokeByValDefault,Bstr) }
+ , { TESTCASE(InvokeByValDefault,BstrC) }
+
+ , { TESTCASE(InvokeByValDefault,Scode) }
+ , { TESTCASE(InvokeByValDefault,ScodeC) }
+ , { TESTCASE(InvokeByValDefault,Bool) }
+ , { TESTCASE(InvokeByValDefault,BoolC) }
+ , { TESTCASE(InvokeByValDefault,Variant) }
+ , { TESTCASE(InvokeByValDefault,VariantC) }
+ , { TESTCASE(InvokeByValDisp,Dispatch) }
+ , { TESTCASE(InvokeByValDisp,DispatchC) }
+
+ , { TESTCASE(InvokeByValDefault,StdI2I4R4R8) }
+ , { TESTCASE(InvokeByValDefault,AltI2I4R4R8) }
+ , { TESTCASE(InvokeByValDefault,StdAll) }
+ , { TESTCASE(InvokeByValDefault,AltAll) }
+};
+
+SUITE_CONSTRUCTION_IMPL(CInvokeByValSuite)
+
+SUITE_IUNKNOWN_IMPL(CInvokeByValSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+STDMETHODIMP
+CInvokeByValSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Invoke ByVal"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeByValSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("invval.log"), pbstr);
+}
+
+STDMETHODIMP
+CInvokeByValSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+
+ return NOERROR;
+}
+
+STDMETHODIMP
+CInvokeByValSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ TCHAR *szFmt;
+ TCHAR buf[128];
+
+ szFmt = TSTR("IDispatch::Invoke(%Fs)");
+
+ SPRINTF(buf, szFmt, STRING(rgtest[iTest].szName));
+ *pbstr = SysAllocString(WIDESTRING(buf));
+ return NOERROR;
+}
+
+/***
+*HRESULT CInvokeByValSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CInvokeByValSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CInvokeByValSuite::DoTest(unsigned int iTest)
+{
+ HRESULT hresult;
+ IDispatch FAR* pdisp;
+
+
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_FAIL);
+
+ pdisp = NULL;
+
+ IfFailRet(CreateObject(g_szCDispTst, &pdisp));
+ IfFailGo(rgtest[iTest].pfnTest(pdisp, iTest, FALSE), LError0);
+ IfFailGo(rgtest[iTest].pfnTest(pdisp, iTest, TRUE), LError0);
+
+ hresult = NOERROR;
+
+LError0:;
+ if(pdisp != NULL)
+ pdisp->Release();
+
+ return hresult;
+}
+
+
+#if VBA2
+VARIANTARG g_rgvarg[21];
+#else //VBA2
+VARIANTARG g_rgvarg[20];
+#endif //VBA2
+
+static HRESULT
+init()
+{
+ VARIANTARG FAR* pvarg;
+
+ pvarg = g_rgvarg;
+
+ V_VT(pvarg) = VT_EMPTY;
+ pvarg++;
+
+ V_VT(pvarg) = VT_NULL;
+ pvarg++;
+
+#if VBA2
+ V_VT(pvarg) = VT_UI1; V_UI1(pvarg) = 41;
+ pvarg++;
+#endif //VBA2
+
+ V_VT(pvarg) = VT_I2; V_I2(pvarg) = 42;
+ pvarg++;
+
+ V_VT(pvarg) = VT_I4; V_I4(pvarg) = 43L;
+ pvarg++;
+
+ V_VT(pvarg) = VT_R4; V_R4(pvarg) = 42.42;
+ pvarg++;
+
+ V_VT(pvarg) = VT_R8; V_R8(pvarg) = 43.43;
+ pvarg++;
+
+ V_VT(pvarg) = VT_CY; V_CY(pvarg).Hi = 0; V_CY(pvarg).Lo = 6;
+ pvarg++;
+
+ V_VT(pvarg) = VT_CY; V_CY(pvarg).Hi = 107; V_CY(pvarg).Lo = 66;
+ pvarg++;
+
+ V_VT(pvarg) = VT_DATE; V_DATE(pvarg) = 0.6;
+ pvarg++;
+
+ V_VT(pvarg) = VT_DATE; V_DATE(pvarg) = 107.66;
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(OLESTR("binary string"));
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(NULL);
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(OLESTR("42"));
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(OLESTR("43.43"));
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(OLESTR("#TRUE#"));
+ pvarg++;
+
+ V_VT(pvarg) = VT_BSTR; V_BSTR(pvarg) = SysAllocString(OLESTR("#FALSE#"));
+ pvarg++;
+
+ V_VT(pvarg) = VT_ERROR; V_ERROR(pvarg) = S_OK;
+ pvarg++;
+
+ V_VT(pvarg) = VT_ERROR; V_ERROR(pvarg) = E_FAIL;
+ pvarg++;
+
+ V_VT(pvarg) = VT_BOOL; V_BOOL(pvarg) = 0;
+ pvarg++;
+
+ V_VT(pvarg) = VT_BOOL; V_BOOL(pvarg) = -1;
+ pvarg++;
+
+ ASSERT(pvarg == &g_rgvarg[DIM(g_rgvarg)]);
+
+ return NOERROR;
+}
+
+static HRESULT
+clear()
+{
+ VARIANTARG FAR* pvarg;
+
+ for(pvarg = g_rgvarg; pvarg < &g_rgvarg[DIM(g_rgvarg)]; ++pvarg){
+ IfFailRet(VariantClear(pvarg));
+ }
+
+ return NOERROR;
+}
+
+HRESULT
+InvokeByValDefault(IDispatch FAR* pdisp, int iTest, int fNamed)
+{
+ unsigned int uArgErr;
+ int i, j, cArgs;
+ NAMEDESC FAR* pnd;
+ VARIANT varResult;
+ DISPID FAR* rgdispid;
+ DISPPARAMS dispparams;
+ HRESULT hresult, hresultTmp;
+
+
+ pnd = &rgtest[iTest].namedesc;
+ hresult = GetDISPIDs(pdisp, pnd, &rgdispid);
+
+ if(HRESULT_FAILED(hresult)){
+#if OE_WIN32
+// when doing 16/32 interop, 3 tests aren't available when talking to a
+// 16-bit server. No easy away to tell, so if we get the right error
+// on the right 3 tests, we'll pretend it worked. Baselines will catch
+// us if there's a problem doing 32-32.
+ SCODE sc = GetScode(hresult);
+ if (sc == DISP_E_UNKNOWNNAME) {
+ if (!wcsicmp(OLESTR("r4"), pnd->rgszNames[0])
+ || !wcsicmp(OLESTR("r8"), pnd->rgszNames[0])
+ || !wcsicmp(OLESTR("date"), pnd->rgszNames[0])) {
+ return NOERROR; // pretend we worked
+ }
+ }
+#endif //OE_WIN32
+ return hresult;
+ }
+
+ cArgs = pnd->cNames - 1;
+
+ dispparams.cArgs = cArgs;
+ dispparams.rgvarg = NULL;
+ if(!fNamed){
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+ }else{
+ dispparams.cNamedArgs = cArgs;
+ dispparams.rgdispidNamedArgs = &rgdispid[1];
+ }
+
+ if(cArgs > 0){
+ if((dispparams.rgvarg = new FAR VARIANT [cArgs]) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+ for(j = 0; j < cArgs; ++j)
+ VariantInit(&dispparams.rgvarg[j]);
+ }
+
+ init();
+
+ for(i = 0; i < DIM(g_rgvarg); ++i){
+
+ if(i > 0 && V_VT(&g_rgvarg[i]) == VT_EMPTY)
+ continue;
+
+ for(j = 0; j < cArgs; ++j){
+ IfFailGo(VariantCopy(&dispparams.rgvarg[j], &g_rgvarg[i]), LError0);
+ }
+
+ uArgErr = 0;
+ MEMSET(&varResult, -1, sizeof(varResult));
+ VariantInit(&varResult);
+
+ hresult = DoInvoke(
+ pdisp, rgdispid[0], &dispparams, &varResult, NULL, &uArgErr);
+
+ for(j = 0; j < cArgs; ++j){
+ hresultTmp = VariantClear(&dispparams.rgvarg[j]);
+ ASSERT(hresultTmp == NOERROR);
+ }
+
+ hresultTmp = VariantClear(&varResult);
+ ASSERT(hresultTmp == NOERROR);
+
+ if(HRESULT_FAILED(hresult)){
+ SCODE sc = GetScode(hresult);
+ if (sc != E_NOTIMPL
+ && sc != DISP_E_OVERFLOW
+ && sc != DISP_E_TYPEMISMATCH)
+ goto LError0;
+ }
+ }
+
+ hresult = NOERROR;
+
+LError0:;
+ if(dispparams.rgvarg != NULL)
+ delete dispparams.rgvarg;
+
+ hresultTmp = clear();
+ ASSERT(hresultTmp == NOERROR);
+
+ delete rgdispid;
+
+ return hresult;
+}
+
+HRESULT
+InvokeByValHello(IDispatch FAR* pdisp, int iTest, int fNamed)
+{
+ HRESULT hresult;
+ DISPID FAR* rgdispid;
+ DISPPARAMS dispparams;
+
+ UNUSED(fNamed);
+
+ IfFailRet(
+ GetDISPIDs(
+ pdisp, &rgtest[iTest].namedesc, &rgdispid));
+
+ dispparams.cArgs = 0;
+ dispparams.cNamedArgs = 0;
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, NULL, NULL, NULL),
+ LError0);
+
+ hresult = NOERROR;
+
+LError0:;
+ delete rgdispid;
+
+ return hresult;
+}
+
+HRESULT
+InvokeByValDisp(IDispatch FAR* pdisp, int iTest, int fNamed)
+{
+ HRESULT hresult;
+ VARIANT varResult;
+ DISPID dispidMember;
+ DISPID FAR* rgdispid;
+ DISPPARAMS dispparams;
+ OLECHAR FAR* rgszNames[1];
+
+ IUnknown FAR* punk;
+ IDispatch FAR* pdisp0, FAR* pdisp1;
+
+ UNUSED(fNamed);
+
+ hresult = NOERROR;
+
+ IfFailRet(
+ GetDISPIDs(pdisp, &rgtest[iTest].namedesc, &rgdispid));
+
+ dispparams.cArgs = 0;
+ dispparams.rgvarg = NULL;
+ dispparams.cNamedArgs = 0;
+ dispparams.rgdispidNamedArgs = NULL;
+
+ MEMSET(&varResult, -1, sizeof(varResult));
+ VariantInit(&varResult);
+
+ IfFailGo(
+ DoInvoke(pdisp, rgdispid[0], &dispparams, &varResult, NULL, NULL),
+ LError0);
+
+ if(V_VT(&varResult) != VT_DISPATCH){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+
+ /* check out the IDispatch* we got back */
+
+ // QI to IUnknown and back
+
+ pdisp0 = V_DISPATCH(&varResult);
+ pdisp0->AddRef();
+
+ hresult = VariantClear(&varResult);
+ ASSERT(!HRESULT_FAILED(hresult));
+
+ hresult = pdisp0->QueryInterface(IID_IUnknown, (void FAR* FAR*)&punk);
+ DbPrintf("QueryInterface(IUnknown) => %s\n",
+ DbSzOfScode(GetScode(hresult)));
+ if(HRESULT_FAILED(hresult))
+ goto LError1;
+
+ hresult = punk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp1);
+ DbPrintf("QueryInterface(IDispatch) => %s\n",
+ DbSzOfScode(GetScode(hresult)));
+ if(HRESULT_FAILED(hresult))
+ goto LError2;
+
+ /* invoke Hello() method on pdisp0 and pdisp1 */
+
+ dispparams.cArgs = 0;
+ dispparams.cNamedArgs = 0;
+
+ rgszNames[0] = OLESTR("hello");
+
+ IfFailGo(
+ pdisp0->GetIDsOfNames(
+ IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispidMember),
+ LError3);
+
+ IfFailGo(
+ DoInvoke(pdisp0, dispidMember, &dispparams, NULL, NULL, NULL), LError3);
+
+ IfFailGo(
+ pdisp1->GetIDsOfNames(
+ IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispidMember),
+ LError3);
+
+ IfFailGo(
+ DoInvoke(pdisp1, dispidMember, &dispparams, NULL, NULL, NULL), LError3);
+
+ hresult = NOERROR;
+
+LError3:
+ pdisp1->Release();
+
+LError2:
+ punk->Release();
+
+LError1:
+ pdisp0->Release();
+
+LError0:;
+ delete rgdispid;
+
+ return hresult;
+}
diff --git a/private/oleauto/tests/disptest/clsid.h b/private/oleauto/tests/disptest/clsid.h
new file mode 100644
index 000000000..9a62d1290
--- /dev/null
+++ b/private/oleauto/tests/disptest/clsid.h
@@ -0,0 +1,31 @@
+/***
+*clsid.h
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+`* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file defines the CLSIDs referenced by the IDispatch test app.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+DEFINE_OLEGUID(IID_ITestSuite, 0x00020440, 0, 0);
+
+DEFINE_OLEGUID(CLSID_CPoly, 0x00020462, 0, 0);
+DEFINE_OLEGUID(CLSID_CPoint, 0x00020463, 0, 0);
+
+DEFINE_OLEGUID(CLSID_CPoly2, 0x00020464, 0, 0);
+DEFINE_OLEGUID(CLSID_CPoint2, 0x00020465, 0, 0);
+
+DEFINE_OLEGUID(CLSID_CCalc, 0x00020467, 0, 0);
+
+DEFINE_OLEGUID(CLSID_SDispTst_CSArray, 0x00020461, 0, 0);
+DEFINE_OLEGUID(CLSID_SDispTst_CDispTst, 0x00020460, 0, 0);
+DEFINE_OLEGUID(CLSID_SDispTst_CExcepinfo, 0x00020466, 0, 0);
+DEFINE_OLEGUID(CLSID_SDispTst_CAppObject, 0x00020468, 0, 0);
+
+#if VBA2
+DEFINE_OLEGUID(IID_IDualTst, 0x00020475, 0, 0);
+#endif
diff --git a/private/oleauto/tests/disptest/cnls.cpp b/private/oleauto/tests/disptest/cnls.cpp
new file mode 100644
index 000000000..540300f85
--- /dev/null
+++ b/private/oleauto/tests/disptest/cnls.cpp
@@ -0,0 +1,421 @@
+/***
+*cnls.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CNlsSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+
+struct TEST {
+ HRESULT (*pfnTest)(LCID);
+ OLECHAR FAR* szName;
+ LCID lcid;
+};
+
+HRESULT DumpNlsInfo(LCID lcid);
+HRESULT NlsAPIRaid28(LCID ignore);
+HRESULT NlsAPIRaid418(LCID ignore);
+HRESULT OB4589(LCID ignore);
+HRESULT NlsCurrentLCID(LCID ignore);
+
+#if !defined(WIN32)
+#define NLSTEST(X) { DumpNlsInfo, OLESTR("lcid = ") #X, X }
+#endif
+static TEST rgtest[] = {
+#if defined(WIN32)
+ { DumpNlsInfo, OLESTR("lcid = 0x0409"), 0x0409}
+ , { NlsCurrentLCID, OLESTR("CurrentLcid"), 0 }
+#else //WIN32
+ NLSTEST(0x040c)
+ , NLSTEST(0x0407)
+ , NLSTEST(0x0409)
+ , NLSTEST(0x0809)
+ , NLSTEST(0x0c09)
+ , NLSTEST(0x1009)
+ , NLSTEST(0x1409)
+ , NLSTEST(0x0406)
+ , NLSTEST(0x0413)
+ , NLSTEST(0x0813)
+ , NLSTEST(0x040b)
+ , NLSTEST(0x080c)
+ , NLSTEST(0x0c0c)
+ , NLSTEST(0x100c)
+ , NLSTEST(0x0807)
+ , NLSTEST(0x0c07)
+ , NLSTEST(0x0410)
+ , NLSTEST(0x0810)
+ , NLSTEST(0x040a)
+ , NLSTEST(0x080a)
+ , NLSTEST(0x0c0a)
+ , NLSTEST(0x041d)
+ , NLSTEST(0x0414)
+ , NLSTEST(0x0416)
+ , NLSTEST(0x0816)
+ , NLSTEST(0x0405)
+ , NLSTEST(0x040e)
+ , NLSTEST(0x0415)
+ , NLSTEST(0x041b)
+ , NLSTEST(0x0419)
+ , NLSTEST(0x0403)
+ , NLSTEST(0x0408)
+ , NLSTEST(0x040f)
+ , NLSTEST(0x041f)
+ , NLSTEST(0x0814)
+ , NLSTEST(0x1809)
+// BIDI locales
+ , NLSTEST(0x040d)
+ , NLSTEST(0x0401)
+ , NLSTEST(0x0801)
+ , NLSTEST(0x0c01)
+ , NLSTEST(0x1001)
+ , NLSTEST(0x1401)
+ , NLSTEST(0x1801)
+ , NLSTEST(0x1c01)
+ , NLSTEST(0x2001)
+ , NLSTEST(0x2401)
+ , NLSTEST(0x2801)
+ , NLSTEST(0x2c01)
+ , NLSTEST(0x3001)
+ , NLSTEST(0x3401)
+ , NLSTEST(0x3801)
+ , NLSTEST(0x3C01)
+ , NLSTEST(0x4001)
+ , NLSTEST(0x0429)
+
+// DBCS locales
+ , NLSTEST(0x0404)
+ , NLSTEST(0x0804)
+ , NLSTEST(0x0411)
+ , NLSTEST(0x0412)
+
+ , { NlsCurrentLCID, OLESTR("CurrentLcid"), 0 }
+
+ // regression tests
+ , { NlsAPIRaid28, OLESTR("raid:oleprog#28"), 0 }
+ , { NlsAPIRaid418, OLESTR("raid:oleprog#418"), 0 }
+ , { OB4589, OLESTR("raid:ob#4589"), 0 }
+#endif //WIN32
+};
+#undef NLSTEST
+
+
+SUITE_CONSTRUCTION_IMPL(CNlsSuite)
+
+SUITE_IUNKNOWN_IMPL(CNlsSuite)
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+CNlsSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("NLS API"), pbstr);
+}
+
+STDMETHODIMP
+CNlsSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("nlsapi.log"), pbstr);
+}
+
+STDMETHODIMP
+CNlsSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CNlsSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+/***
+*HRESULT CNlsSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CNlsSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CNlsSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest(rgtest[iTest].lcid);
+}
+
+#define LCINIT(X) {X, #X}
+static struct {
+ LCTYPE lctype;
+ char FAR* szLctype;
+} rglctype[] = {
+ LCINIT(LOCALE_ILANGUAGE) /* language id */
+ , LCINIT(LOCALE_SLANGUAGE) /* localized name of language */
+ , LCINIT(LOCALE_SENGLANGUAGE) /* English name of language */
+ , LCINIT(LOCALE_SABBREVLANGNAME) /* abbreviated language name */
+ , LCINIT(LOCALE_SNATIVELANGNAME) /* native name of language */
+ , LCINIT(LOCALE_ICOUNTRY) /* country code */
+ , LCINIT(LOCALE_SCOUNTRY) /* localized name of country */
+ , LCINIT(LOCALE_SENGCOUNTRY) /* English name of country */
+ , LCINIT(LOCALE_SABBREVCTRYNAME) /* abbreviated country name */
+ , LCINIT(LOCALE_SNATIVECTRYNAME) /* native name of country */
+ , LCINIT(LOCALE_IDEFAULTLANGUAGE) /* default language id */
+ , LCINIT(LOCALE_IDEFAULTCOUNTRY) /* default country code */
+ , LCINIT(LOCALE_IDEFAULTCODEPAGE) /* default code page */
+ , LCINIT(LOCALE_SLIST) /* list item separator */
+ , LCINIT(LOCALE_IMEASURE) /* 0 = metric, 1 = US */
+ , LCINIT(LOCALE_SDECIMAL) /* decimal separator */
+ , LCINIT(LOCALE_STHOUSAND) /* thousand separator */
+ , LCINIT(LOCALE_SGROUPING) /* digit grouping */
+ , LCINIT(LOCALE_IDIGITS) /* number of fractional digits */
+ , LCINIT(LOCALE_ILZERO) /* leading zeros for decimal */
+ , LCINIT(LOCALE_SNATIVEDIGITS) /* native ascii 0-9 */
+ , LCINIT(LOCALE_SCURRENCY) /* local monetary symbol */
+ , LCINIT(LOCALE_SINTLSYMBOL) /* intl monetary symbol */
+ , LCINIT(LOCALE_SMONDECIMALSEP) /* monetary decimal separator */
+ , LCINIT(LOCALE_SMONTHOUSANDSEP) /* monetary thousand separator */
+ , LCINIT(LOCALE_SMONGROUPING) /* monetary grouping */
+ , LCINIT(LOCALE_ICURRDIGITS) /* # local monetary digits */
+ , LCINIT(LOCALE_IINTLCURRDIGITS) /* # intl monetary digits */
+ , LCINIT(LOCALE_ICURRENCY) /* positive currency mode */
+ , LCINIT(LOCALE_INEGCURR) /* negative currency mode */
+ , LCINIT(LOCALE_SDATE) /* date separator */
+ , LCINIT(LOCALE_STIME) /* time separator */
+ , LCINIT(LOCALE_SSHORTDATE) /* short date-time separator */
+ , LCINIT(LOCALE_SLONGDATE) /* long date-time separator */
+ , LCINIT(LOCALE_IDATE) /* short date format ordering */
+ , LCINIT(LOCALE_ILDATE) /* long date format ordering */
+ , LCINIT(LOCALE_ITIME) /* time format specifier */
+ , LCINIT(LOCALE_ICENTURY) /* century format specifier */
+ , LCINIT(LOCALE_ITLZERO) /* leading zeros in time field */
+ , LCINIT(LOCALE_IDAYLZERO) /* leading zeros in day field */
+ , LCINIT(LOCALE_IMONLZERO) /* leading zeros in month field */
+ , LCINIT(LOCALE_S1159) /* AM designator */
+ , LCINIT(LOCALE_S2359) /* PM designator */
+ , LCINIT(LOCALE_SDAYNAME1) /* long name for Monday */
+ , LCINIT(LOCALE_SDAYNAME2) /* long name for Tuesday */
+ , LCINIT(LOCALE_SDAYNAME3) /* long name for Wednesday */
+ , LCINIT(LOCALE_SDAYNAME4) /* long name for Thursday */
+ , LCINIT(LOCALE_SDAYNAME5) /* long name for Friday */
+ , LCINIT(LOCALE_SDAYNAME6) /* long name for Saturday */
+ , LCINIT(LOCALE_SDAYNAME7) /* long name for Sunday */
+ , LCINIT(LOCALE_SABBREVDAYNAME1) /* abbreviated name for Monday */
+ , LCINIT(LOCALE_SABBREVDAYNAME2) /* abbreviated name for Tuesday */
+ , LCINIT(LOCALE_SABBREVDAYNAME3) /* abbreviated name for Wednesday */
+ , LCINIT(LOCALE_SABBREVDAYNAME4) /* abbreviated name for Thursday */
+ , LCINIT(LOCALE_SABBREVDAYNAME5) /* abbreviated name for Friday */
+ , LCINIT(LOCALE_SABBREVDAYNAME6) /* abbreviated name for Saturday */
+ , LCINIT(LOCALE_SABBREVDAYNAME7) /* abbreviated name for Sunday */
+ , LCINIT(LOCALE_SMONTHNAME1) /* long name for January */
+ , LCINIT(LOCALE_SMONTHNAME2) /* long name for February */
+ , LCINIT(LOCALE_SMONTHNAME3) /* long name for March */
+ , LCINIT(LOCALE_SMONTHNAME4) /* long name for April */
+ , LCINIT(LOCALE_SMONTHNAME5) /* long name for May */
+ , LCINIT(LOCALE_SMONTHNAME6) /* long name for June */
+ , LCINIT(LOCALE_SMONTHNAME7) /* long name for July */
+ , LCINIT(LOCALE_SMONTHNAME8) /* long name for August */
+ , LCINIT(LOCALE_SMONTHNAME9) /* long name for September */
+ , LCINIT(LOCALE_SMONTHNAME10) /* long name for October */
+ , LCINIT(LOCALE_SMONTHNAME11) /* long name for November */
+ , LCINIT(LOCALE_SMONTHNAME12) /* long name for December */
+ , LCINIT(LOCALE_SABBREVMONTHNAME1) /* abbreviated name for January */
+ , LCINIT(LOCALE_SABBREVMONTHNAME2) /* abbreviated name for February */
+ , LCINIT(LOCALE_SABBREVMONTHNAME3) /* abbreviated name for March */
+ , LCINIT(LOCALE_SABBREVMONTHNAME4) /* abbreviated name for April */
+ , LCINIT(LOCALE_SABBREVMONTHNAME5) /* abbreviated name for May */
+ , LCINIT(LOCALE_SABBREVMONTHNAME6) /* abbreviated name for June */
+ , LCINIT(LOCALE_SABBREVMONTHNAME7) /* abbreviated name for July */
+ , LCINIT(LOCALE_SABBREVMONTHNAME8) /* abbreviated name for August */
+ , LCINIT(LOCALE_SABBREVMONTHNAME9) /* abbreviated name for September */
+ , LCINIT(LOCALE_SABBREVMONTHNAME10) /* abbreviated name for October */
+ , LCINIT(LOCALE_SABBREVMONTHNAME11) /* abbreviated name for November */
+ , LCINIT(LOCALE_SABBREVMONTHNAME12) /* abbreviated name for December */
+ , LCINIT(LOCALE_SPOSITIVESIGN) /* positive sign */
+ , LCINIT(LOCALE_SNEGATIVESIGN) /* negative sign */
+ , LCINIT(LOCALE_IPOSSIGNPOSN) /* positive sign position */
+ , LCINIT(LOCALE_INEGSIGNPOSN) /* negative sign position */
+ , LCINIT(LOCALE_IPOSSYMPRECEDES) /* mon sym precedes pos amt */
+ , LCINIT(LOCALE_IPOSSEPBYSPACE) /* mon sym sep by space from pos */
+ , LCINIT(LOCALE_INEGSYMPRECEDES) /* mon sym precedes neg amt */
+ , LCINIT(LOCALE_INEGSEPBYSPACE) /* mon sym sep by space from neg */
+ , LCINIT(LOCALE_IFIRSTDAYOFWEEK)
+ , LCINIT(LOCALE_IFIRSTWEEKOFYEAR)
+ , LCINIT(LOCALE_IDEFAULTANSICODEPAGE)
+ , LCINIT(LOCALE_INEGNUMBER)
+ , LCINIT(LOCALE_STIMEFORMAT)
+ , LCINIT(LOCALE_ITIMEMARKPOSN)
+ , LCINIT(LOCALE_ICALENDARTYPE)
+ , LCINIT(LOCALE_IOPTIONALCALENDAR)
+ , LCINIT(LOCALE_SMONTHNAME13)
+ , LCINIT(LOCALE_SABBREVMONTHNAME13)
+};
+
+// dump all nls info for all our supported locales!
+HRESULT
+DumpNlsInfo(LCID lcid)
+{
+ BSTR bstr;
+ LCTYPE lctype;
+ int iLctype, size, fetched;
+ BSTR bstrDecimal = NULL;
+ BSTR bstrThousand = NULL;
+
+
+ DbPrintf("LCID = %ld\n", lcid);
+
+ for(iLctype = 0; iLctype < DIM(rglctype); ++iLctype){
+ DbPrintf(HC_MPW ? "%s = " : "%Fs = ",
+ (char FAR*)rglctype[iLctype].szLctype);
+
+ lctype = rglctype[iLctype].lctype;
+
+ size = GetLocaleInfoA(lcid, lctype, NULL, 0);
+ if(size == 0)
+ return RESULT(E_FAIL);
+
+#ifndef SysAllocStringByteLen
+#define SysAllocStringByteLen SysAllocStringLen
+#endif
+ bstr = SysAllocStringByteLen(NULL, size);
+ if(bstr == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ fetched = GetLocaleInfoA(lcid, lctype, (char FAR *)bstr, size);
+
+ DbPrintf(HC_MPW ? "\"%s\"\n" : "\"%Fs\"\n", (char FAR *)bstr);
+
+ switch (lctype) {
+ // save these for later checking
+ case LOCALE_SDECIMAL:
+ bstrDecimal = bstr;
+ break;
+ case LOCALE_STHOUSAND:
+ bstrThousand = bstr;
+ break;
+ default:
+ SysFreeString(bstr);
+ }
+
+ if(fetched != size)
+ return RESULT(E_FAIL);
+ }
+#if defined(WIN32)
+ if (!wcscmp(bstrDecimal, bstrThousand))
+#else //WIN32
+ if (!lstrcmp(bstrDecimal, bstrThousand))
+#endif //WIN32
+ {
+ DbPrintf("ERROR: decimal and thousands separators are the same for lcid = 0x%lx\n", lcid);
+ }
+ SysFreeString(bstrDecimal);
+ SysFreeString(bstrThousand);
+
+ DbPrintf("\n");
+
+ return NOERROR;
+}
+
+HRESULT
+NlsCurrentLCID(LCID ignore)
+{
+ UNUSED(ignore);
+
+ return DumpNlsInfo(GetSystemDefaultLCID());
+}
+
+// regression test for raid!oleprog#28 (sublanguages dont work)
+//
+HRESULT
+NlsAPIRaid28(LCID ignore)
+{
+ int size;
+ LCID lcid;
+
+ UNUSED(ignore);
+
+#if !defined(WIN32) // UNDONE: TEMPORARY
+ lcid = MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_NEUTRAL));
+ size = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE, NULL, 0);
+ if(size <= 0)
+ return RESULT(E_FAIL);
+
+ lcid = MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS));
+ size = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE, NULL, 0);
+ if(size <= 0)
+ return RESULT(E_FAIL);
+#endif //!WIN32
+
+ return NOERROR;
+}
+
+// regression test for raid!oleprog#418
+//
+// problem: LCMapStringA is returning 0 (error) for some characters
+// in some locales.
+//
+HRESULT
+NlsAPIRaid418(LCID ignore)
+{
+ int res;
+ char rgchIn[2], rgchOut[32];
+
+ rgchIn[0] = (BYTE)0x8C;
+
+ res = LCMapStringA(
+ 0x0407,
+ LCMAP_SORTKEY|NORM_IGNORECASE|NORM_IGNORENONSPACE,
+ rgchIn, 1, rgchOut, 32);
+
+ if(res == 0)
+ return RESULT(E_FAIL);
+ return NOERROR;
+}
+
+HRESULT
+OB4589(LCID ignore)
+{
+ int cmp;
+ char rgch1[2], rgch2[2];
+
+ UNUSED(ignore);
+
+ rgch1[0] = 'a';
+ rgch2[0] = 'A';
+ cmp = CompareStringA(0x0409, NORM_IGNORENONSPACE, rgch1, 1, rgch2, 1);
+ DbPrintf(
+ "CompareStringA(0409, NORM_IGNORENONSPACE, 'a', 'A') = %d\n", cmp);
+
+ rgch1[0] = 'a';
+ rgch2[0] = 'C';
+ cmp = CompareStringA(0x0409, NORM_IGNORENONSPACE, rgch1, 1, rgch2, 1);
+ DbPrintf(
+ "CompareStringA(0409, NORM_IGNORENONSPACE, 'a', 'C') = %d\n", cmp);
+
+ return NOERROR;
+}
+
diff --git a/private/oleauto/tests/disptest/csarray.cpp b/private/oleauto/tests/disptest/csarray.cpp
new file mode 100644
index 000000000..7dd783aa7
--- /dev/null
+++ b/private/oleauto/tests/disptest/csarray.cpp
@@ -0,0 +1,371 @@
+/***
+*csarray.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CSafeArraySuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+HRESULT SafeArrayRedimTest(VARTYPE vt, SAFEARRAY FAR* psa);
+HRESULT SafeArrayOleprog181();
+HRESULT SafeArrayOleprog302();
+
+
+static SARRAYDESC rgsarraydesc[] =
+{
+
+ {1, {{1,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{2,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{4,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{8,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{16,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{32,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{64,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{128,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{256,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{512,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{1024,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{2048,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{4096,0}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{5,100}, {0,0}, {0,0}, {0,0}, {0,0}}}
+ , {1, {{5,-100}, {0,0}, {0,0}, {0,0}, {0,0}}}
+
+ , {2, {{1,0}, {1,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{2,0}, {1,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{4,0}, {1,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{8,0}, {1,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{16,0}, {16,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{32,0}, {32,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{64,0}, {64,0}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{5,100}, {5,100}, {0,0}, {0,0}, {0,0}}}
+ , {2, {{5,-100}, {5,-100}, {0,0}, {0,0}, {0,0}}}
+
+ , {3, {{1,0}, {1,0}, {1,0}, {0,0}, {0,0}}}
+ , {3, {{2,0}, {2,0}, {2,0}, {0,0}, {0,0}}}
+ , {3, {{4,0}, {4,0}, {4,0}, {0,0}, {0,0}}}
+ , {3, {{8,0}, {8,0}, {8,0}, {0,0}, {0,0}}}
+ , {3, {{16,0}, {16,0}, {16,0}, {0,0}, {0,0}}}
+ , {3, {{5,100}, {5,100}, {5,100}, {0,0}, {0,0}}}
+ , {3, {{5,-100}, {5,-100}, {5,-100}, {0,0}, {0,0}}}
+
+ , {4, {{1,0}, {1,0}, {1,0}, {1,0}, {0,0}}}
+ , {4, {{2,0}, {2,0}, {2,0}, {2,0}, {0,0}}}
+ , {4, {{4,0}, {4,0}, {4,0}, {4,0}, {0,0}}}
+ , {4, {{8,0}, {8,0}, {8,0}, {8,0}, {0,0}}}
+ , {4, {{5,100}, {5,100}, {5,100}, {5,100}, {0,0}}}
+ , {4, {{5,-100}, {5,-100}, {5,-100}, {5,-100}, {0,0}}}
+};
+
+static OLECHAR FAR* rgszSArrayDesc[] =
+{
+ OLESTR("(1)"),
+ OLESTR("(2)"),
+ OLESTR("(4)"),
+ OLESTR("(8)"),
+ OLESTR("(16)"),
+ OLESTR("(32)"),
+ OLESTR("(64)"),
+ OLESTR("(128)"),
+ OLESTR("(256)"),
+ OLESTR("(512)"),
+ OLESTR("(1024)"),
+ OLESTR("(2048)"),
+ OLESTR("(4096)"),
+ OLESTR("(100 To 105)"),
+ OLESTR("(-100 To -95)"),
+
+ OLESTR("(1, 1)"),
+ OLESTR("(2, 2)"),
+ OLESTR("(4, 4)"),
+ OLESTR("(8, 8)"),
+ OLESTR("(16, 16)"),
+ OLESTR("(32, 32)"),
+ OLESTR("(64, 64)"),
+ OLESTR("(100 To 105, 100 To 105)"),
+ OLESTR("(-100 To -95, -100 To -95)"),
+
+ OLESTR("(1, 1, 1)"),
+ OLESTR("(2, 2, 2)"),
+ OLESTR("(4, 4, 4)"),
+ OLESTR("(8, 8, 8)"),
+ OLESTR("(16, 16, 16)"),
+ OLESTR("(100 To 105, 100 To 105, 100 To 105)"),
+ OLESTR("(-100 To -95, -100 To -95, -100 To -95)"),
+
+ OLESTR("(1, 1, 1, 1)"),
+ OLESTR("(2, 2, 2, 2)"),
+ OLESTR("(4, 4, 4, 4)"),
+ OLESTR("(8, 8, 8, 8)"),
+
+ OLESTR("(100 To 105, 100 To 105, 100 To 105, 100 To 105)"),
+ OLESTR("(-100 To -95, -100 To -95, -100 To -95, -100 To -95)")
+};
+
+static VARTYPE rgvtArrayTypes[] =
+{
+ VT_I2
+#if VBA2
+ , VT_UI1
+#endif //VBA2
+ , VT_I4
+ , VT_R4
+ , VT_R8
+ , VT_CY
+ , VT_DATE
+ , VT_BSTR
+ , VT_ERROR
+ , VT_BOOL
+ , VT_VARIANT
+ , VT_UNKNOWN
+ , VT_DISPATCH
+};
+
+
+
+struct TEST {
+ HRESULT (*pfnTest)();
+ OLECHAR FAR* szName;
+};
+
+static TEST rgtest[] =
+{
+ { SafeArrayOleprog181, OLESTR("raid:oleprog#181")}
+ , { SafeArrayOleprog302, OLESTR("raid!oleprog#302")}
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CSafeArraySuite)
+
+SUITE_IUNKNOWN_IMPL(CSafeArraySuite)
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+CSafeArraySuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("SafeArray API"), pbstr);
+}
+
+STDMETHODIMP
+CSafeArraySuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("saryapi.log"), pbstr);
+}
+
+STDMETHODIMP
+CSafeArraySuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgvtArrayTypes) * DIM(rgsarraydesc) + DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CSafeArraySuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ TCHAR buf[128];
+ int iVt, iDesc;
+
+ if(iTest >= (DIM(rgvtArrayTypes) * DIM(rgsarraydesc) + DIM(rgtest)))
+ return RESULT(E_INVALIDARG); // out-of-bounds really
+
+ if(iTest < (DIM(rgvtArrayTypes) * DIM(rgsarraydesc))) {
+ iVt = iTest / DIM(rgsarraydesc);
+ iDesc = iTest % DIM(rgsarraydesc);
+
+ ASSERT(iVt < DIM(rgvtArrayTypes));
+ ASSERT(iDesc < DIM(rgsarraydesc));
+ ASSERT(iDesc < DIM(rgszSArrayDesc));
+
+#if HC_MPW
+ sprintf(buf, "Dim <Array> %s As %s",
+#else
+ SPRINTF(buf, TSTR("Dim <Array> %Fs As %Fs"),
+#endif
+ rgszSArrayDesc[iDesc],
+ DbSzOfVt(rgvtArrayTypes[iVt]));
+
+ *pbstr = SysAllocString(WIDESTRING(buf));
+ return NOERROR;
+ }
+
+ iTest -= (DIM(rgvtArrayTypes) * DIM(rgsarraydesc));
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+/***
+*HRESULT CSafeArraySuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single SafeArray test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CSafeArraySuite::DoTest(unsigned int iTest)
+{
+ VARTYPE vt;
+ int iVt, iDesc;
+ SAFEARRAY FAR* psa;
+ SARRAYDESC FAR* psadesc;
+ HRESULT hresult, hresultTmp;
+
+
+ if(iTest >= (DIM(rgvtArrayTypes) * DIM(rgsarraydesc) + DIM(rgtest)))
+ return RESULT(E_INVALIDARG); // out-of-bounds really
+
+ if(iTest >= (DIM(rgvtArrayTypes) * DIM(rgsarraydesc))) {
+ iTest -= (DIM(rgvtArrayTypes) * DIM(rgsarraydesc));
+ return rgtest[iTest].pfnTest();
+
+ } else {
+ iVt = iTest / DIM(rgsarraydesc);
+ iDesc = iTest % DIM(rgsarraydesc);
+
+ ASSERT(iVt < DIM(rgvtArrayTypes));
+ ASSERT(iDesc < DIM(rgsarraydesc));
+
+ vt = rgvtArrayTypes[iVt];
+ psadesc = &rgsarraydesc[iDesc];
+
+ IfFailGo(SafeArrayCreateIdentity(vt, psadesc, &psa), LError0);
+
+ DbPrSafeArray(psa, vt);
+
+ IfFailGo(SafeArrayValidateIdentity(vt, psa, 0L), LError1);
+
+ IfFailGo(SafeArrayRedimTest(vt, psa), LError1);
+ hresult = NOERROR;
+ }
+
+LError1:;
+ hresultTmp = SafeArrayDestroy(psa);
+ ASSERT(hresultTmp == NOERROR);
+
+LError0:;
+ return hresult;
+}
+
+HRESULT
+SafeArrayRedimTest(VARTYPE vt, SAFEARRAY FAR* psa)
+{
+ unsigned long cElements;
+ HRESULT hresult;
+ SAFEARRAYBOUND sabound;
+
+ sabound = psa->rgsabound[0];
+
+ cElements = sabound.cElements;
+
+ sabound.cElements = cElements*2;
+ if((hresult = SafeArrayRedim(psa, &sabound)) != NOERROR){
+ if(GetScode(hresult) != E_OUTOFMEMORY)
+ return hresult;
+ // try once more with a smaller increase
+ sabound.cElements = cElements + 5;
+ IfFailRet(SafeArrayRedim(psa, &sabound));
+ }
+
+ DbPrSafeArray(psa, vt);
+
+ if(cElements == 1)
+ return NOERROR;
+
+ sabound.cElements = cElements/2;
+ IfFailRet(SafeArrayRedim(psa, &sabound));
+ DbPrSafeArray(psa, vt);
+
+ return NOERROR;
+}
+
+// regression test for oleprog#181: infinite loop in SafeArrayCopy
+// if the array is a simple type (ie, not unknown/dispatch/bstr/variant).
+
+HRESULT
+SafeArrayOleprog181()
+{
+ SARRAYDESC sadesc;
+ HRESULT hresult, hresultTmp;
+ SAFEARRAY FAR* psaSrc, FAR* psaDst;
+
+ sadesc.cDims = 2;
+ sadesc.rgsabound[0].lLbound = 0;
+ sadesc.rgsabound[0].cElements = 4;
+ sadesc.rgsabound[1].lLbound = 0;
+ sadesc.rgsabound[1].cElements = 4;
+
+
+ IfFailGo(SafeArrayCreateIdentity(VT_I2, &sadesc, &psaSrc), LError0);
+
+ DbPrSafeArray(psaSrc, VT_I2);
+
+ IfFailGo(SafeArrayCopy(psaSrc, &psaDst), LError1);
+
+ DbPrSafeArray(psaDst, VT_I2);
+
+ hresult = NOERROR;
+
+ hresultTmp = SafeArrayDestroy(psaDst);
+ ASSERT(hresultTmp == NOERROR);
+
+LError1:
+ hresultTmp = SafeArrayDestroy(psaSrc);
+ ASSERT(hresultTmp == NOERROR);
+
+LError0:
+ return hresult;
+}
+
+
+// regression test for oleprog#302: Creating a multi-dim SafeArray with a
+// dimension element of zero should return a psa of NULL
+//
+
+HRESULT
+SafeArrayOleprog302()
+{
+ SAFEARRAYBOUND rgsabound[4];
+ SAFEARRAY FAR* psa;
+ int cDims;
+
+ cDims = 4;
+ rgsabound[0].lLbound = 0;
+ rgsabound[0].cElements = 10;
+ rgsabound[1].lLbound = 0;
+ rgsabound[1].cElements = 10;
+ rgsabound[2].lLbound = 0;
+ rgsabound[2].cElements = 0;
+ rgsabound[3].lLbound = 0;
+ rgsabound[3].cElements = 10;
+
+ psa = SafeArrayCreate(VT_I2, cDims, rgsabound);
+
+ if (psa == NULL)
+ return NOERROR;
+
+ SafeArrayDestroy(psa);
+ return RESULT(E_FAIL);
+}
+
+
diff --git a/private/oleauto/tests/disptest/ctime.cpp b/private/oleauto/tests/disptest/ctime.cpp
new file mode 100644
index 000000000..fd8303d41
--- /dev/null
+++ b/private/oleauto/tests/disptest/ctime.cpp
@@ -0,0 +1,266 @@
+/***
+*ctime.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CTimeSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+
+void DbPrDosDateTime(unsigned short, unsigned short);
+
+struct TEST {
+ HRESULT (*pfnTest)(void);
+ OLECHAR FAR* szName;
+};
+
+HRESULT DosToVariant(void);
+HRESULT VariantToDos(void);
+
+static TEST rgtest[] = {
+ { DosToVariant, OLESTR("DosDateTimeToVariantTime") },
+ { VariantToDos, OLESTR("VariantTimeToDosDateTime") }
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CTimeSuite)
+
+SUITE_IUNKNOWN_IMPL(CTimeSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+CTimeSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Time API"), pbstr);
+}
+
+STDMETHODIMP
+CTimeSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("timeapi.log"), pbstr);
+}
+
+STDMETHODIMP
+CTimeSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CTimeSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+/***
+*HRESULT CTimeSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CTimeSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CTimeSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest();
+}
+
+#define DOSDATE(MONTH, DAY, YEAR)\
+ ((((YEAR)-1980) << 9) + ((MONTH) << 5) + (DAY))
+
+#define DOSTIME(HOUR, MIN, SEC)\
+ (((HOUR) << 11) + ((MIN) << 5) + ((SEC) / 2))
+
+HRESULT
+DosToVariant()
+{
+ int i;
+ VARIANT var;
+ unsigned short wDosDate, wDosTime;
+static struct {
+ unsigned short wDosDate;
+ unsigned short wDosTime;
+} rgdostime[] = {
+ { DOSDATE(1, 1, 1980), DOSTIME(0, 0, 0) }
+ , { DOSDATE(1, 1, 1990), DOSTIME(0, 0, 0) }
+ , { DOSDATE(1, 1, 2000), DOSTIME(0, 0, 0) }
+ , { DOSDATE(1, 1, 2099), DOSTIME(0, 0, 0) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 0, 0) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 1, 0) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 1, 1) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 1, 2) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 1, 3) }
+ , { DOSDATE(1, 1, 1980), DOSTIME(1, 1, 4) }
+ , { DOSDATE(5, 8, 1983), DOSTIME(12, 22, 4) }
+ , { DOSDATE(10, 23, 2000), DOSTIME(1, 1, 9) }
+ , { DOSDATE(10, 23, 2015), DOSTIME(1, 1, 22) }
+ , { DOSDATE(11, 30, 2099), DOSTIME(23, 59, 59) }
+};
+
+ for(i = 0; i < DIM(rgdostime); ++i){
+ wDosDate = rgdostime[i].wDosDate;
+ wDosTime = rgdostime[i].wDosTime;
+
+ DbPrDosDateTime(wDosDate, wDosTime);
+ DbPrintf(" = ");
+
+ V_VT(&var) = VT_DATE;
+ V_DATE(&var) = 0.0;
+ if(DosDateTimeToVariantTime(wDosDate, wDosTime, &V_DATE(&var)) == 0){
+ DbPrintf("False\n");
+ }else{
+ DbPrintf("vartime(%#g) = ", V_DATE(&var));
+ if(VariantChangeType(&var, &var, 0, VT_BSTR) != NOERROR)
+ return RESULT(E_FAIL);
+#if HC_MPW
+ DbPrintf("%s\n", V_BSTR(&var));
+#else
+ DbPrintf("%Fs\n", STRING(V_BSTR(&var)));
+#endif
+ }
+ if(VariantClear(&var) != NOERROR)
+ return RESULT(E_FAIL);
+ }
+
+ return NOERROR;
+}
+
+HRESULT
+VariantToDos()
+{
+ int i;
+ VARIANT var;
+ unsigned short wDosDate;
+ unsigned short wDosTime;
+
+static OLECHAR FAR* rgszTime[] = {
+ OLESTR("1/1/1980")
+ , OLESTR("1/1/1990")
+ , OLESTR("1/1/2000")
+ , OLESTR("1/1/2099")
+ , OLESTR("1/1/1980 1:0:0")
+ , OLESTR("1/1/1980 1:1:0")
+ , OLESTR("1/1/1980 1:1:1")
+ , OLESTR("1/1/1980 1:1:2")
+ , OLESTR("1/1/1980 1:1:3")
+ , OLESTR("1/1/1980 1:1:4")
+ , OLESTR("5/8/1983 12:22:4")
+ , OLESTR("10/10/2000 1:1:18")
+ , OLESTR("11/30/2099 23:59:59")
+};
+
+ VariantInit(&var);
+ for(i = 0; i < DIM(rgszTime); ++i){
+#if HC_MPW
+ DbPrintf("\'%s' = ", rgszTime[i]);
+#else
+ DbPrintf("\'%Fs' = ", STRING(rgszTime[i]));
+#endif
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(rgszTime[i]);
+ if(VariantChangeType(&var, &var, 0, VT_DATE) != NOERROR)
+ return RESULT(E_FAIL);
+ DbPrintf("vartime(%#g) = ", V_DATE(&var));
+ if(VariantTimeToDosDateTime(V_DATE(&var), &wDosDate, &wDosTime) == 0){
+ DbPrintf("False\n");
+ }else{
+ DbPrDosDateTime(wDosDate, wDosTime);
+ DbPrintf("\n");
+ }
+ if(VariantClear(&var) != NOERROR)
+ return RESULT(E_FAIL);
+ }
+
+ return NOERROR;
+}
+
+unsigned short
+YearOfDosDate(unsigned short wDosDate)
+{
+ return ((wDosDate >> 9) & 0x007f);
+}
+
+unsigned short
+MonthOfDosDate(unsigned short wDosDate)
+{
+ return ((wDosDate >> 5) & 0x000f);
+}
+
+unsigned short
+DayOfDosDate(unsigned short wDosDate)
+{
+ return ((wDosDate) & 0x001f);
+}
+
+void
+DbPrDosDate(unsigned short wDosDate)
+{
+ DbPrintf("%d-%d-%d",
+ MonthOfDosDate(wDosDate),
+ DayOfDosDate(wDosDate),
+ YearOfDosDate(wDosDate));
+}
+
+unsigned short
+HourOfDosTime(unsigned short wDosTime)
+{
+ return ((wDosTime >> 11) & 0x001f);
+}
+
+unsigned short
+MinOfDosTime(unsigned short wDosTime)
+{
+ return ((wDosTime >> 5) & 0x003f);
+}
+
+unsigned short
+SecOfDosTime(unsigned short wDosTime)
+{
+ return ((wDosTime) & 0x001f);
+}
+
+void
+DbPrDosTime(unsigned short wDosTime)
+{
+ DbPrintf("%d:%d:%d",
+ HourOfDosTime(wDosTime),
+ MinOfDosTime(wDosTime),
+ SecOfDosTime(wDosTime));
+}
+
+void
+DbPrDosDateTime(unsigned short wDosDate, unsigned short wDosTime)
+{
+ DbPrDosDate(wDosDate);
+ DbPrintf(" ");
+ DbPrDosTime(wDosTime);
+}
+
diff --git a/private/oleauto/tests/disptest/cvariant.cpp b/private/oleauto/tests/disptest/cvariant.cpp
new file mode 100644
index 000000000..3b62c9d4c
--- /dev/null
+++ b/private/oleauto/tests/disptest/cvariant.cpp
@@ -0,0 +1,1617 @@
+/***
+*cvariant.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CVariantSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+
+#include <float.h> /* for DBL_MAX */
+
+#include "tstsuite.h"
+#include "cunk.h"
+#include "cdisp.h"
+
+ASSERTDATA
+
+#ifdef _MAC
+# define CY_(HI,LO) {HI,LO}
+#else
+# define CY_(HI,LO) {LO,HI}
+#endif
+
+
+// return on an hresult that is not success, and *not* one of the
+// errors we are expecting/allowing.
+//
+#define IFFAILRET(X) \
+ { HRESULT hresultTmp = (X); \
+ if(HRESULT_FAILED(hresultTmp)){ \
+ SCODE sc = GetScode(hresultTmp); \
+ if (sc != E_NOTIMPL \
+ && sc != DISP_E_OVERFLOW \
+ && sc != E_NOINTERFACE \
+ && sc != DISP_E_TYPEMISMATCH) \
+ return hresultTmp; \
+ } \
+ }
+
+
+long rgEmptyVal[] = {0};
+
+long rgNullVal[] = {0};
+
+#if VBA2
+unsigned char rgUI1Val[] = {0, 1, 128, 255};
+#endif //VBA2
+
+short rgI2Val[] = {0, 1, -1, 42};
+
+long rgI4Val[] = {0, 1, -1, 42000};
+
+float rgR4Val[] = {(float)0.0, (float)42.42, (float)107.66, (float)-2147483648.0};
+
+double rgR8Val[] = {0.0, 42.42, 107.66};
+
+CY rgCyVal[] = {CY_(0,0), CY_(0,2), CY_(42,43), CY_(107,66), CY_(5000,0)};
+
+DATE rgDateVal[] = {0.0, 42.42, 107.66};
+
+OLECHAR FAR* rgBstrVal[] = {
+ OLESTR("a binary string")
+ , OLESTR("42")
+ , OLESTR("42000")
+ , OLESTR("92233800000")
+ , OLESTR("42.42")
+ , OLESTR("#TRUE#")
+ , OLESTR("#FALSE#")
+ , OLESTR("1/7/66")
+ , OLESTR("1:20 pm")
+};
+
+
+SCODE rgErrorVal[] = {S_OK, DISP_E_TYPEMISMATCH};
+
+VARIANT_BOOL rgBoolVal[] = {0, -1};
+
+struct VARIANT_TEST_INFO{
+ VARTYPE vtFrom;
+ int nValues;
+ void FAR* rgValues;
+};
+
+HRESULT VariantOB1469(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB2078(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB2834(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3028(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3336(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3354(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3603(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3875(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOB3876(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog10(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog11(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog12(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog27(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog50(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog82(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog84(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog94(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog235(VARIANT_TEST_INFO FAR*);
+HRESULT VariantOleprog351(VARIANT_TEST_INFO FAR*);
+HRESULT VariantBug0(VARIANT_TEST_INFO FAR*);
+HRESULT VariantBug1(VARIANT_TEST_INFO FAR*);
+HRESULT OverflowTests(VARIANT_TEST_INFO FAR*);
+HRESULT DefVariantTest(VARIANT_TEST_INFO FAR*);
+
+
+struct TEST {
+ HRESULT (*pfnTest)(VARIANT_TEST_INFO FAR*);
+ OLECHAR FAR* szName;
+ struct VARIANT_TEST_INFO vti;
+};
+
+static TEST rgtest[] =
+{
+ { VariantBug1, OLESTR("bug#1"), {0, 0, NULL}}
+
+ , { VariantOleprog10, OLESTR("raid!oleprog#10"), {0, 0, NULL}}
+ , { VariantOleprog11, OLESTR("raid!oleprog#11"), {0, 0, NULL}}
+ , { VariantOleprog12, OLESTR("raid!oleprog#12"), {0, 0, NULL}}
+ , { VariantOleprog27, OLESTR("raid!oleprog#27"), {0, 0, NULL}}
+ , { VariantOleprog50, OLESTR("raid!oleprog#50"), {0, 0, NULL}}
+ , { VariantOleprog82, OLESTR("raid!oleprog#82"), {0, 0, NULL}}
+ , { VariantOleprog84, OLESTR("raid!oleprog#84"), {0, 0, NULL}}
+ , { VariantOleprog94, OLESTR("raid!oleprog#94"), {0, 0, NULL}}
+ , { VariantOleprog235,OLESTR("raid!oleprog#235"),{0, 0, NULL}}
+ , { VariantOleprog351,OLESTR("raid!oleprog#351"),{0, 0, NULL}}
+
+ , { VariantOB1469, OLESTR("raid!ob#1469"), {0,0,NULL}}
+// , { VariantOB2078, OLESTR("raid!ob#2078"), {0,0,NULL}}
+ , { VariantOB2834, OLESTR("raid!ob#2834"), {0,0,NULL}}
+// , { VariantOB3028 OLESTR("raid!ob#3028"), {0,0,NULL}}
+ , { VariantOB3336, OLESTR("raid!ob#3336"), {0,0,NULL}}
+ , { VariantOB3354, OLESTR("raid!ob#3354"), {0,0,NULL}}
+ , { VariantOB3603, OLESTR("raid!ob#3603"), {0,0,NULL}}
+// , { VariantOB3875, OLESTR("raid!ob#3875"), {0,0,NULL}}
+ , { VariantOB3876, OLESTR("raid!ob#3876"), {0,0,NULL}}
+
+ , { VariantBug0, OLESTR("bug#0"), {0, 0, NULL}}
+
+ , { DefVariantTest, OLESTR("VT_EMPTY To *"),
+ {VT_EMPTY, DIM(rgEmptyVal),rgEmptyVal}}
+
+ , { DefVariantTest, OLESTR("VT_NULL To *"),
+ {VT_NULL, DIM(rgNullVal), rgNullVal}}
+
+#if VBA2
+ , { DefVariantTest, OLESTR("VT_UI1 To *"),
+ {VT_UI1, DIM(rgUI1Val), rgUI1Val}}
+#endif //VBA2
+
+ , { DefVariantTest, OLESTR("VT_I2 To *"),
+ {VT_I2, DIM(rgI2Val), rgI2Val}}
+
+ , { DefVariantTest, OLESTR("VT_I4 To *"),
+ {VT_I4, DIM(rgI4Val), rgI4Val}}
+
+ , { DefVariantTest, OLESTR("VT_R4 To *"),
+ {VT_R4, DIM(rgR4Val), rgR4Val}}
+
+ , { DefVariantTest, OLESTR("VT_R8 To *"),
+ {VT_R8, DIM(rgR8Val), rgR8Val}}
+
+ , { DefVariantTest, OLESTR("VT_CY To *"),
+ {VT_CY, DIM(rgCyVal), rgCyVal}}
+
+ , { DefVariantTest, OLESTR("VT_DATE To *"),
+ {VT_DATE, DIM(rgDateVal), rgDateVal}}
+
+ , { DefVariantTest, OLESTR("VT_BSTR To *"),
+ {VT_BSTR, DIM(rgBstrVal), rgBstrVal}}
+
+ , { DefVariantTest, OLESTR("VT_DISPATCH To *"),
+ {VT_DISPATCH, 1, NULL}}
+
+ , { DefVariantTest, OLESTR("VT_ERROR To *"),
+ {VT_ERROR, DIM(rgErrorVal),rgErrorVal}}
+
+ , { DefVariantTest, OLESTR("VT_BOOL To *"),
+ {VT_BOOL, DIM(rgBoolVal), rgBoolVal}}
+
+ , { DefVariantTest, OLESTR("VT_UNKNOWN To *"),
+ {VT_UNKNOWN, 1, NULL}}
+
+#if VBA2
+ , { DefVariantTest, OLESTR("VT_UI1Ref To *"),
+ {VT_BYREF | VT_UI1, DIM(rgUI1Val), rgUI1Val}}
+#endif //VBA2
+
+ , { DefVariantTest, OLESTR("VT_I2Ref To *"),
+ {VT_BYREF | VT_I2, DIM(rgI2Val), rgI2Val}}
+
+ , { DefVariantTest, OLESTR("VT_I4Ref To *"),
+ {VT_BYREF | VT_I4, DIM(rgI4Val), rgI4Val}}
+
+ , { DefVariantTest, OLESTR("VT_R4Ref To *"),
+ {VT_BYREF | VT_R4, DIM(rgR4Val), rgR4Val}}
+
+ , { DefVariantTest, OLESTR("VT_R8Ref To *"),
+ {VT_BYREF | VT_R8, DIM(rgR8Val), rgR8Val}}
+
+ , { DefVariantTest, OLESTR("VT_CYRef To *"),
+ {VT_BYREF | VT_CY, DIM(rgCyVal), rgCyVal}}
+
+ , { DefVariantTest, OLESTR("VT_DATERef To *"),
+ {VT_BYREF | VT_DATE, DIM(rgDateVal), rgDateVal}}
+
+ , { DefVariantTest, OLESTR("VT_BSTRRef To *"),
+ {VT_BYREF | VT_BSTR, DIM(rgBstrVal), rgBstrVal}}
+
+ , { DefVariantTest, OLESTR("VT_DISPATCHRef To *"),
+ {VT_BYREF | VT_DISPATCH, 1, NULL}}
+
+ , { DefVariantTest, OLESTR("VT_ERRORRef To *"),
+ {VT_BYREF | VT_ERROR, DIM(rgErrorVal), rgErrorVal}}
+
+ , { DefVariantTest, OLESTR("VT_BOOLRef To *"),
+ {VT_BYREF | VT_BOOL, DIM(rgBoolVal), rgBoolVal}}
+
+#if 0 /* REVIEW: need a bit more work for this test */
+ , { DefVariantTest, OLESTR("VT_VARIANTRef To *"),
+ {VT_BYREF | VT_VARIANT, 1, NULL}}
+#endif
+
+ , { DefVariantTest, OLESTR("VT_UNKNOWNRef To *"),
+ {VT_BYREF | VT_UNKNOWN, 1, NULL}}
+};
+
+SUITE_CONSTRUCTION_IMPL(CVariantSuite)
+
+SUITE_IUNKNOWN_IMPL(CVariantSuite)
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+
+/***
+*HRESULT CVariantSuite::GetNameOfSuite(BSTR*)
+*Purpose:
+* Return the name of this test suite.
+*
+*Entry:
+* None
+*
+*Exit:
+* return value = HRESULT
+*
+* *pbstr = BSTR containing the name of the suite
+*
+***********************************************************************/
+STDMETHODIMP
+CVariantSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("Variant API"), pbstr);
+}
+
+STDMETHODIMP
+CVariantSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc(OLESTR("varapi.log"), pbstr);
+}
+
+/***
+*HRESULT CVariantSuite::GetTestCount(unsigned int*)
+*Purpose:
+* Return a count of the number of tests in this suite.
+*
+*Entry:
+* None
+*
+*Exit:
+* return value = HRESULT
+*
+* *pcTests = The count of tests
+*
+***********************************************************************/
+STDMETHODIMP
+CVariantSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+/***
+*HRESULT CVariant::GetNameOfTest(unsigned int, BSTR*)
+*Purpose:
+* Return the name of the test associated with the given test index.
+*
+*Entry:
+* iTest = index of the test whose name is requested
+*
+*Exit:
+* return value = HRESULT
+* S_OK, E_INVALIDARG
+*
+* *pbstr = BSTR containing the name of the test
+*
+***********************************************************************/
+STDMETHODIMP
+CVariantSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return ErrBstrAlloc(rgtest[iTest].szName, pbstr);
+}
+
+/***
+*HRESULT CVariantSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single SafeArray test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CVariantSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG); // out-of-bounds really
+
+ return rgtest[iTest].pfnTest(&rgtest[iTest].vti);
+}
+
+HRESULT
+VariantFromVariantTestInfo(
+ VARIANT_TEST_INFO FAR* pvti,
+ int ix,
+ VARIANTARG FAR* pvarg,
+ VARIANT FAR* pvarRefMem)
+{
+ VARTYPE vt;
+ HRESULT hresult;
+
+ V_VT(pvarg) = vt = pvti->vtFrom;
+
+ switch(vt & ~VT_BYREF){
+ case VT_NULL:
+ case VT_EMPTY:
+ break;
+
+#if VBA2
+ case VT_UI1:
+ V_UI1(pvarg) = ((unsigned char FAR*)pvti->rgValues)[ix];
+ break;
+#endif //VBA2
+
+ case VT_I2:
+ case VT_BOOL:
+ V_I2(pvarg) = ((short FAR*)pvti->rgValues)[ix];
+ break;
+
+ case VT_I4:
+ case VT_ERROR:
+ V_I4(pvarg) = ((long FAR*)pvti->rgValues)[ix];
+ break;
+
+ case VT_R4:
+ V_R4(pvarg) = ((float FAR*)pvti->rgValues)[ix];
+ break;
+
+ case VT_R8:
+ case VT_DATE:
+ V_R8(pvarg) = ((double FAR*)pvti->rgValues)[ix];
+ break;
+
+ case VT_CY:
+ V_CY(pvarg) = ((CY FAR*)pvti->rgValues)[ix];
+ break;
+
+ case VT_BSTR:
+ V_BSTR(pvarg) = SysAllocString(((OLECHAR FAR* FAR*)pvti->rgValues)[ix]);
+ ASSERT(V_BSTR(pvarg) != NULL);
+ break;
+
+ case VT_DISPATCH:
+ hresult = CDisp::Create(&V_DISPATCH(pvarg));
+ ASSERT(hresult == NOERROR);
+ break;
+
+ case VT_UNKNOWN:
+ hresult = CUnk::Create(&V_UNKNOWN(pvarg));
+ ASSERT(hresult == NOERROR);
+ break;
+
+ default:
+ ASSERT(UNREACHED);
+ }
+
+ if(vt & VT_BYREF){
+ MEMCPY(pvarRefMem, pvarg, sizeof(VARIANTARG));
+ V_BYREF(pvarg) = &V_NONE(pvarRefMem);
+ }
+
+ return NOERROR;
+}
+
+HRESULT
+doCoerce(VARIANTARG FAR* pvargFrom, VARTYPE vtTo)
+{
+ VARIANTARG vargTo;
+ HRESULT hresult, hrTmp;
+
+ VariantInit(&vargTo);
+
+ DbPrVarg(pvargFrom);
+ DbPrintf(" to ");
+
+ hresult = VariantChangeType(&vargTo, pvargFrom, 0, vtTo);
+
+ if(!HRESULT_FAILED(hresult)){
+ DbPrVarg(&vargTo);
+ }else{
+ DbPrVt(vtTo);
+#if HC_MPW
+ DbPrintf(" => [%s]", DbSzOfScode(GetScode(hresult)));
+#else
+ DbPrintf(" => [%Fs]", DbSzOfScode(GetScode(hresult)));
+#endif
+ }
+ DbPrintf("\n");
+
+ hrTmp = VariantClear(&vargTo);
+ ASSERT(hrTmp == NOERROR);
+
+ return hresult;
+}
+
+/***
+*HRESULT coerce(VARIANTARG*)
+*Purpose:
+* Attempt to coerce the given VARIANTARG to each of the integral types.
+*
+*Entry:
+* pvargFrom = the VARIANTARG to coerce 'from'
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+HRESULT
+coerce(VARIANTARG FAR* pvargFrom)
+{
+ IFFAILRET(doCoerce(pvargFrom, VT_EMPTY));
+ IFFAILRET(doCoerce(pvargFrom, VT_NULL));
+#if VBA2
+ IFFAILRET(doCoerce(pvargFrom, VT_UI1));
+#endif //VBA2
+ IFFAILRET(doCoerce(pvargFrom, VT_I2));
+ IFFAILRET(doCoerce(pvargFrom, VT_I4));
+ IFFAILRET(doCoerce(pvargFrom, VT_R4));
+ IFFAILRET(doCoerce(pvargFrom, VT_R8));
+ IFFAILRET(doCoerce(pvargFrom, VT_CY));
+ IFFAILRET(doCoerce(pvargFrom, VT_DATE));
+ IFFAILRET(doCoerce(pvargFrom, VT_BSTR));
+ IFFAILRET(doCoerce(pvargFrom, VT_DISPATCH));
+ IFFAILRET(doCoerce(pvargFrom, VT_ERROR));
+ IFFAILRET(doCoerce(pvargFrom, VT_BOOL));
+ IFFAILRET(doCoerce(pvargFrom, VT_UNKNOWN));
+
+ return NOERROR;
+}
+
+HRESULT
+DefVariantTest(VARIANT_TEST_INFO FAR* pvti)
+{
+ int i;
+ VARIANTARG vargFrom;
+ VARIANTARG vargRefMem;
+
+
+ for(i = 0; i < pvti->nValues; ++i){
+ VariantInit(&vargFrom);
+
+ IfFailRet(VariantFromVariantTestInfo(pvti, i, &vargFrom, &vargRefMem));
+
+ IfFailRet(coerce(&vargFrom));
+
+ VariantClearAll(&vargFrom);
+ }
+
+ return NOERROR;
+}
+
+
+#define CYFACTOR 10000
+
+// NOTE: we define our own max/min values here, because these differ
+// slightly than those supplied by limits.h for some compilers we use.
+// specifically: C8 (and predecessors) define min short to be -32767,
+// while we allow it to be one lower, -32768.
+
+#if VBA2
+#define MAX_UI1 0xFF
+#define MIN_UI1 0x00
+#endif //VBA2
+
+#define MAX_I2 0x7FFF
+#define MIN_I2 0x8000
+
+#define MAX_I4 0x7FFFFFFF
+#define MIN_I4 0x80000000
+
+#define MAX_R4 3.402823466e+38
+#define MIN_R4 (-3.402823466e+38)
+
+#if VBA2
+unsigned char g_bMax = MAX_UI1;
+unsigned char g_bMin = MIN_UI1;
+#endif //VBA2
+
+short g_sMax = MAX_I2;
+short g_sMin = MIN_I2;
+
+long g_lMax = MAX_I4;
+long g_lMin = MIN_I4;
+
+CY g_cyMax = CY_(0x7FFFFFFF, 0xFFFFFFFF);
+CY g_cyMin = CY_(0x80000000, 0x00000000);
+
+float g_fltMax = (float) MAX_R4;
+float g_fltMin = (float) MIN_R4;
+
+void KillOpt(){}
+
+void
+IncVar(VARIANT FAR* pvar)
+{
+ unsigned long ul;
+ float fltOrg, fltInc;
+ double dblOrg, dblInc;
+
+#if HC_MPW
+ float FAR* pfltTmp;
+ double FAR* pdblTmp;
+#else
+ volatile float FAR* pfltTmp;
+ volatile double FAR* pdblTmp;
+#endif
+
+ pfltTmp = &V_R4(pvar);
+ pdblTmp = &V_R8(pvar);
+
+ switch(V_VT(pvar)){
+#if VBA2
+ case VT_UI1:
+ ++V_UI1(pvar);
+ break;
+#endif //VBA2
+
+ case VT_I2:
+ ++V_I2(pvar);
+ break;
+
+ case VT_I4:
+ ++V_I4(pvar);
+ break;
+
+ case VT_R4:
+ fltInc = (float)1.0;
+ fltOrg = *pfltTmp;
+ while(1){
+ *pfltTmp = *pfltTmp + fltInc;
+ KillOpt();
+ if(*pfltTmp != fltOrg)
+ break;
+ fltInc *= (float)2.0;
+ }
+ break;
+
+ case VT_R8:
+ dblInc = 1.0;
+ dblOrg = *pdblTmp;
+ while(1){
+ *pdblTmp = *pdblTmp + dblInc;
+ KillOpt();
+ if(*pdblTmp != dblOrg)
+ break;
+ dblInc *= 2.0;
+ }
+ break;
+
+ case VT_CY:
+ ul = V_CY(pvar).Lo;
+ if((V_CY(pvar).Lo += CYFACTOR) <= ul){
+ ++V_CY(pvar).Hi;
+ }
+ break;
+ }
+}
+
+void
+DecVar(VARIANT FAR* pvar)
+{
+ unsigned long ul;
+ float fltInc, fltOrg;
+ double dblInc, dblOrg;
+
+#if HC_MPW
+ float FAR* pfltTmp;
+ double FAR* pdblTmp;
+#else
+ volatile float FAR* pfltTmp;
+ volatile double FAR* pdblTmp;
+#endif
+
+ pfltTmp = &V_R4(pvar);
+ pdblTmp = &V_R8(pvar);
+
+ switch(V_VT(pvar)){
+#if VBA2
+ case VT_UI1:
+ --V_UI1(pvar);
+ break;
+#endif //VBA2
+ case VT_I2:
+ --V_I2(pvar);
+ break;
+
+ case VT_I4:
+ --V_I4(pvar);
+ break;
+
+ case VT_R4:
+ fltOrg = *pfltTmp;
+ fltInc = (float)1.0;
+ while(1){
+ *pfltTmp = *pfltTmp - fltInc;
+ KillOpt();
+ if(*pfltTmp != fltOrg)
+ break;
+ fltInc *= (float)2.0;
+ }
+ break;
+
+ case VT_R8:
+ dblOrg = *pdblTmp;
+ dblInc = 1.0;
+ while(1){
+ *pdblTmp = *pdblTmp - dblInc;
+ KillOpt();
+ if(*pdblTmp != dblOrg)
+ break;
+ dblInc *= 2.0;
+ }
+ break;
+
+ case VT_CY:
+ ul = V_CY(pvar).Lo;
+ if((V_CY(pvar).Lo -= CYFACTOR) >= ul){
+ --V_CY(pvar).Hi;
+ }
+ break;
+ }
+}
+
+HRESULT
+doOverflow(VARTYPE vt, VARIANT varMax, VARIANT varMin)
+{
+ int i;
+ HRESULT hr;
+ VARIANT var;
+ VARTYPE vtFrom;
+
+#define BACKOFF_ITERATIONS 3
+
+ vtFrom = V_VT(&varMax);
+ ASSERT(vtFrom == V_VT(&varMin));
+
+
+ VariantInit(&var);
+ IfFailRet(VariantChangeType(&var, &varMax, 0, vt));
+
+ // back off the max value,
+ for(i = 0; i < BACKOFF_ITERATIONS; ++i)
+ DecVar(&var);
+
+ for(i = 0; i <= BACKOFF_ITERATIONS*3; ++i){
+ hr = doCoerce(&var, vtFrom);
+ if(hr != NOERROR){
+ if(GetScode(hr) == DISP_E_OVERFLOW)
+ goto LDoneWithMax;
+ return hr;
+ }
+ IncVar(&var);
+ }
+ return RESULT(E_FAIL); // failed to detect overflow
+
+LDoneWithMax:;
+
+ VariantInit(&var);
+ IfFailRet(VariantChangeType(&var, &varMin, 0, vt));
+
+ // back off the min value
+ for(i = 0; i < BACKOFF_ITERATIONS; ++i)
+ IncVar(&var);
+
+ for(i = 0; i <= BACKOFF_ITERATIONS*3; ++i){
+ hr = doCoerce(&var, vtFrom);
+ if(hr != NOERROR){
+ if(GetScode(hr) == DISP_E_OVERFLOW)
+ goto LDoneWithMin;
+ return hr;
+ }
+ DecVar(&var);
+ }
+ return RESULT(E_FAIL); // failed to detect overflow
+
+LDoneWithMin:;
+
+ return NOERROR;
+}
+
+/***
+*PRIVATE HRESULT OverflowTests
+*Purpose:
+* Test various coersions to make sure they properly catch overflows.
+*
+* The heirarchy of ranges for each datatype is as follows,
+*
+* ui1 < i2 < i4 < cy < r4 < r8
+*
+* which means that we need to check the following coersions for overflow,
+*
+* i2->ui1
+* i4->ui1, i4->i2
+* cy->ui1, cy->i2, cy->i4
+* r4->ui1, r4->i2, r4->i4, r4->cy
+* r8->ui1, r8->i2, r8->i4, r8->cy, r8->r4
+*
+*Entry:
+* None
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+HRESULT
+OverflowTests(VARIANT_TEST_INFO FAR* dummy)
+{
+#if VBA2
+ VARIANT varUI1Max, varUI1Min;
+#endif //VBA2
+ VARIANT varI2Max, varI2Min;
+ VARIANT varI4Max, varI4Min;
+ VARIANT varCyMax, varCyMin;
+ VARIANT varR4Max, varR4Min;
+
+ UNUSED(dummy);
+
+#if VBA2
+ V_VT(&varUI1Max) = VT_UI1; V_UI1(&varUI1Max) = g_bMax;
+ V_VT(&varUI1Min) = VT_UI1; V_UI1(&varUI1Min) = g_bMin;
+#endif //VBA2
+
+ V_VT(&varI2Max) = VT_I2; V_I2(&varI2Max) = g_sMax;
+ V_VT(&varI2Min) = VT_I2; V_I2(&varI2Min) = g_sMin;
+
+ V_VT(&varI4Max) = VT_I4; V_I4(&varI4Max) = g_lMax;
+ V_VT(&varI4Min) = VT_I4; V_I4(&varI4Min) = g_lMin;
+
+ V_VT(&varCyMax) = VT_CY; V_CY(&varCyMax) = g_cyMax;
+ V_VT(&varCyMin) = VT_CY; V_CY(&varCyMin) = g_cyMin;
+
+ V_VT(&varR4Max) = VT_R4; V_R4(&varR4Max) = g_fltMax;
+ V_VT(&varR4Min) = VT_R4; V_R4(&varR4Min) = g_fltMin;
+
+#if VBA2
+ IfFailRet(doOverflow(VT_I2, varUI1Max, varUI1Min));
+#endif //VBA2
+
+#if VBA2
+ IfFailRet(doOverflow(VT_I4, varUI1Max, varUI1Min));
+#endif //VBA2
+ IfFailRet(doOverflow(VT_I4, varI2Max, varI2Min));
+
+#if VBA2
+ IfFailRet(doOverflow(VT_CY, varUI1Max, varUI1Min));
+#endif //VBA2
+ IfFailRet(doOverflow(VT_CY, varI2Max, varI2Min));
+ IfFailRet(doOverflow(VT_CY, varI4Max, varI4Min));
+
+#if VBA2
+ IfFailRet(doOverflow(VT_R4, varUI1Max, varUI1Min));
+#endif //VBA2
+ IfFailRet(doOverflow(VT_R4, varI2Max, varI2Min));
+ IfFailRet(doOverflow(VT_R4, varI4Max, varI4Min));
+ IfFailRet(doOverflow(VT_R4, varCyMax, varCyMin));
+
+#if VBA2
+ IfFailRet(doOverflow(VT_R8, varUI1Max, varUI1Min));
+#endif //VBA2
+ IfFailRet(doOverflow(VT_R8, varI2Max, varI2Min));
+ IfFailRet(doOverflow(VT_R8, varI4Max, varI4Min));
+ IfFailRet(doOverflow(VT_R8, varCyMax, varCyMin));
+ IfFailRet(doOverflow(VT_R8, varR4Max, varR4Min));
+
+ return NOERROR;
+}
+
+
+//---------------------------------------------------------------------
+// regression tests
+//---------------------------------------------------------------------
+
+
+// regression test for raid:oob#1469
+//
+// problem: Currency literal parsed wrong (BSTR -> CY)
+//
+HRESULT
+VariantOB1469(VARIANT_TEST_INFO FAR* dummy)
+{
+ int i;
+ VARIANT var;
+ HRESULT hresult;
+static OLECHAR FAR* str[] = {
+ OLESTR("92233700000"),
+ OLESTR("92233800000"),
+};
+
+ UNUSED(dummy);
+
+ for(i = 0; i < DIM(str); ++i){
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(str[i]);
+ if(V_BSTR(&var) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+ IfFailGo(VariantChangeType(&var, &var, 0, VT_CY), LError0);
+ VariantClear(&var);
+ }
+
+ return NOERROR;
+
+LError0:;
+ VariantClear(&var);
+
+ return hresult;
+}
+
+
+
+// regression for raid:ob#2078
+//
+// problem: double output off by 1 in last digit
+//
+HRESULT
+VariantOB2078(VARIANT_TEST_INFO FAR* dummy)
+{
+ LCID lcid;
+ HRESULT hresult;
+ BSTR bstr1, bstr2;
+ double r1 = -1.797693134862315E+308,
+ r2 = 1.797693134862315E+308;
+
+ UNUSED(dummy);
+
+ bstr1 = bstr2 = NULL;
+
+ lcid = GetUserDefaultLCID();
+
+ IfFailGo(VarBstrFromR8(r1, lcid, NULL, &bstr1), LError0);
+ IfFailGo(VarBstrFromR8(r2, lcid, NULL, &bstr2), LError0);
+
+ if (STRCMP(STRING(bstr1), TSTR("-1.797693134862312E+308")) != 0){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+
+ if (STRCMP(STRING(bstr2), TSTR("1.797693134862312E+308")) != 0){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+
+ hresult = NOERROR;
+
+LError0:;
+ SysFreeString(bstr1);
+ SysFreeString(bstr2);
+ return hresult;
+}
+
+
+
+// regression for raid:ob#2834
+//
+// problem: not accepting YMD without year (accepted by VB3)
+//
+HRESULT
+VariantOB2834(VARIANT_TEST_INFO FAR* dummy)
+{
+ DATE date;
+ BSTR bstr;
+ HRESULT hresult;
+
+ UNUSED(dummy);
+
+ IfFailRet(VarDateFromStr(OLESTR("8:07 AM"),
+ GetUserDefaultLCID(), 0,
+ &date));
+
+ bstr = NULL;
+
+ hresult = VarBstrFromDate(date, GetUserDefaultLCID(), 0, &bstr);
+
+ SysFreeString(bstr);
+
+ return hresult;
+}
+
+
+// regression for raid:ob#3028
+//
+// problem: Leading 0 is being ignored for the system (&prj) locale
+//
+HRESULT
+VariantOB3028(VARIANT_TEST_INFO FAR* dummy)
+{
+ CY cy;
+ LCID lcid;
+ char szBuff[2];
+ BSTR bstr1, bstr2;
+ HRESULT hresult;
+
+ UNUSED(dummy);
+
+ bstr1 = bstr2 = NULL;
+
+ lcid = GetUserDefaultLCID();
+
+ IfFailGo(VarBstrFromR8(0.739, lcid, NULL, &bstr1), LError0);
+ DbPrintf("VarBstrFromR8(0.739) = \"%Fs\"\n", STRING(bstr1));
+
+ IfFailGo(VarCyFromR8(0.739, &cy), LError0);
+ IfFailGo(VarBstrFromCy(cy, lcid, NULL, &bstr2), LError0);
+ DbPrintf("VarBstrFromCy(0.739) = \"%Fs\"\n", STRING(bstr2));
+
+ GetLocaleInfoA(lcid, LOCALE_ILZERO, szBuff, SIZEOFCH(szBuff));
+ if (szBuff[0] == '0') {
+ if (STRCMP(STRING(bstr1), TSTR(".739")) != 0 ||
+ STRCMP(STRING(bstr2), TSTR(".739")) != 0){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+ } else {
+ if (STRCMP(STRING(bstr1), TSTR("0.739")) != 0 ||
+ STRCMP(STRING(bstr2), TSTR("0.739")) != 0){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+ }
+
+ hresult = NOERROR;
+
+LError0:;
+ SysFreeString(bstr1);
+ SysFreeString(bstr2);
+ return hresult;
+}
+
+
+// regression for raid:ob#3336
+//
+// problem: Conversion routines does not remove thousands separators
+// when coersing from STR to either R8 or CY.
+//
+HRESULT
+VariantOB3336(VARIANT_TEST_INFO FAR* dummy)
+{
+ int i;
+ VARIANT var;
+ HRESULT hresult;
+ static OLECHAR FAR* str[] = {
+ OLESTR("12,456.78"),
+ OLESTR("1,2,3,4,5,6,,789.123"),
+ OLESTR(",1234,5678,9"),
+ OLESTR("123,456,789.124")
+};
+
+ UNUSED(dummy);
+
+ for(i = 0; i < DIM(str); ++i){
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(str[i]);
+ if(V_BSTR(&var) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+ IfFailGo(VariantChangeType(&var, &var, 0, VT_CY), LError0);
+ IfFailGo(VariantChangeType(&var, &var, 0, VT_R8), LError0);
+ VariantClear(&var);
+ }
+
+ return NOERROR;
+
+LError0:;
+ VariantClear(&var);
+
+ return hresult;
+}
+
+// regression for raid:ob#3354
+//
+// problem: Coersion to Date doesn't validate input value.
+//
+HRESULT
+VariantOB3354(VARIANT_TEST_INFO FAR* dummy)
+{
+ DATE date;
+
+ UNUSED(dummy);
+ if (VarDateFromR8(3000, &date) != NOERROR) return RESULT(E_FAIL);
+ if (VarDateFromR8(30000000, &date) == NOERROR) return RESULT(E_FAIL);
+ return NOERROR;
+}
+
+
+// regression for raid:ob#3603
+//
+// problem: VarCyFromStr is hammering the input string (it is removing
+// the negative sign in the following example in place).
+//
+HRESULT
+VariantOB3603(VARIANT_TEST_INFO FAR* dummy)
+{
+ CY cy;
+ TCHAR strIn[32];
+ HRESULT hresult;
+
+ UNUSED(dummy);
+ STRCPY(strIn, TSTR("-1.0000000001"));
+ DbPrintf("strIn = \"%Fs\"\n", (char FAR*) strIn);
+ DbPrintf("strIn = \"%Fs\"\n", (char FAR*) strIn);
+ hresult = VarCyFromStr(WIDESTRING(strIn), 0, 0, &cy);
+ DbPrintf("VarCyFromStr(strIn, 0, 0, &cy) = %Fs\n",
+ DbSzOfScode(GetScode(hresult)));
+ DbPrintf("strIn = \"%Fs\"\n", (char FAR*) strIn);
+ return NOERROR;
+}
+
+
+// regression for raid:ob#3875
+//
+// problem: not accepting YMD without year (accepted by VB3)
+//
+HRESULT
+VariantOB3875(VARIANT_TEST_INFO FAR* dummy)
+{
+ DATE date;
+
+ UNUSED(dummy);
+ IfFailRet(VarDateFromStr(OLESTR("93/4/30"),
+ GetUserDefaultLCID(), 0,
+ &date));
+ IfFailRet(VarDateFromStr(OLESTR("4/30"),
+ GetUserDefaultLCID(), 0,
+ &date));
+ return NOERROR;
+}
+
+
+
+// regression for raid:ob#3876
+//
+// problem: medium month with period (dec.) not recognized in date string
+//
+HRESULT
+VariantOB3876(VARIANT_TEST_INFO FAR* dummy)
+{
+ DATE date;
+
+ UNUSED(dummy);
+ IfFailRet(VarDateFromStr(OLESTR("12 dec 05 1:23 pm"),
+ GetUserDefaultLCID(), 0,
+ &date));
+ IfFailRet(VarDateFromStr(OLESTR("12 dec. 05 1:23 pm"),
+ GetUserDefaultLCID(), 0,
+ &date));
+ return NOERROR;
+}
+
+
+// regression test for raid:oleprog#10
+//
+// problem: overflow not detected on coersion from VT_R8 to VT_R4.
+//
+HRESULT
+VariantOleprog10(VARIANT_TEST_INFO FAR* dummy)
+{
+ SCODE scode;
+ HRESULT hresult;
+ VARIANT varFrom, varTo;
+
+ UNUSED(dummy);
+
+ VariantInit(&varTo);
+
+ V_VT(&varFrom) = VT_R8;
+ V_R8(&varFrom) = DBL_MAX;
+
+ hresult = VariantChangeType(&varTo, &varFrom, 0, VT_R4);
+
+ scode = GetScode(hresult);
+
+ if(scode != DISP_E_OVERFLOW)
+ return RESULT(E_UNEXPECTED);
+
+ return NOERROR;
+}
+
+
+// regression test for raid:oleprog#11
+//
+// problem: failed in place coersion of a variant destroys the
+// contents of the variant.
+//
+HRESULT
+VariantOleprog11(VARIANT_TEST_INFO FAR* dummy)
+{
+ SCODE scode;
+ VARIANT var;
+ HRESULT hresult;
+
+ UNUSED(dummy);
+
+ V_VT(&var) = VT_R8;
+ V_R8(&var) = DBL_MAX;
+ hresult = VariantChangeType(&var, &var, 0, VT_R4);
+ scode = GetScode(hresult);
+
+ // make sure the overflow was caught correctly.
+ if(scode != DISP_E_OVERFLOW)
+ return RESULT(E_UNEXPECTED);
+
+ // if the coersion failed, the contents should not be destroyed
+ //
+ if(V_VT(&var) != VT_R8 || V_R8(&var) != DBL_MAX)
+ return RESULT(E_UNEXPECTED);
+
+ return NOERROR;
+}
+
+
+// regression test for raid:oleprog#12
+//
+// problem: coersion of variants in place do not free strings.
+//
+HRESULT
+VariantOleprog12(VARIANT_TEST_INFO FAR* dummy)
+{
+ int i;
+ VARIANT var;
+ HRESULT hresult;
+
+#if VBA2
+static VARTYPE rgvt[] = {VT_UI1, VT_I2, VT_I4, VT_R4, VT_R8, VT_CY};
+#else //VBA2
+static VARTYPE rgvt[] = {VT_I2, VT_I4, VT_R4, VT_R8, VT_CY};
+#endif //VBA2
+
+
+ UNUSED(dummy);
+
+ for(i = 0; i < DIM(rgvt); ++i){
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(OLESTR("14"));
+ if(V_BSTR(&var) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+ IfFailGo(VariantChangeType(&var, &var, 0, rgvt[i]), LError0);
+ VariantClear(&var);
+ }
+
+ return NOERROR;
+
+LError0:;
+ VariantClear(&var);
+
+ return hresult;
+}
+
+
+// retression test for raid:oleprog#27
+//
+// problem: cant VariantCopyInd on a variant containing a ByRef array.
+//
+HRESULT
+VariantOleprog27(VARIANT_TEST_INFO FAR* dummy)
+{
+ VARIANT var, varTo;
+ SAFEARRAY FAR* psa;
+ SARRAYDESC sadesc;
+ HRESULT hresult, hresultTmp;
+
+ UNUSED(dummy);
+
+ sadesc.cDims = 1;
+ sadesc.rgsabound[0].lLbound = 5;
+ sadesc.rgsabound[0].cElements = 5;
+
+ IfFailRet(SafeArrayCreateIdentity(VT_BSTR, &sadesc, &psa));
+
+ V_VT(&var) = (VT_ARRAY|VT_BYREF|VT_BSTR);
+ V_ARRAYREF(&var) = &psa;
+
+ VariantInit(&varTo);
+ IfFailGo(VariantCopyInd(&varTo, &var), LError0);
+ if(V_VT(&varTo) != (VT_ARRAY|VT_BSTR)
+#if 0
+// add this back in when VariantCompare can handle arrays
+ || !VariantCompare(&varTo, &var)
+#endif
+ ){
+ hresult = RESULT(E_UNEXPECTED);
+ goto LError1;
+ }
+
+ hresultTmp = VariantClear(&varTo);
+ ASSERT(hresultTmp == NOERROR);
+
+ // now try the copy in-place
+ //
+ V_VT(&var) |= VT_BYREF;
+ IfFailGo(VariantCopyInd(&var, &var), LError0);
+ if(V_VT(&var) != (VT_ARRAY|VT_BSTR)){
+ hresult = RESULT(E_UNEXPECTED);
+ goto LError0;
+ }
+
+ hresultTmp = VariantClear(&var);
+ ASSERT(hresultTmp == NOERROR);
+
+ hresultTmp = SafeArrayDestroy(psa);
+ ASSERT(hresultTmp == NOERROR);
+
+ return NOERROR;
+
+LError1:;
+ VariantClear(&varTo);
+
+LError0:;
+ VariantClearAll(&var);
+
+ return hresult;
+}
+
+
+// regression test for raid:oleprog#50
+//
+// problem: in place variant coersion from VT_BYREF fail (all types)
+//
+HRESULT
+VariantOleprog50(VARIANT_TEST_INFO FAR* dummy)
+{
+ short i2;
+ VARIANT var;
+
+ UNUSED(dummy);
+
+ i2 = 42;
+ V_I2REF(&var) = &i2;
+ V_VT(&var) = VT_BYREF | VT_I2;
+ return VariantChangeType(&var, &var, 0, VT_I2);
+}
+
+
+// regression test for raid:oleprog#84
+//
+// problem: need to allow literal copying of ByRef variants.
+//
+HRESULT
+VariantOleprog84(VARIANT_TEST_INFO FAR* dummy)
+{
+ short i2;
+ HRESULT hr, hrTmp;
+ VARIANT varSrc, varDst;
+
+ UNUSED(dummy);
+
+ i2 = 42;
+ V_I2REF(&varSrc) = &i2;
+ V_VT(&varSrc) = VT_BYREF | VT_I2;
+ VariantInit(&varDst);
+ hr = VariantCopy(&varDst, &varSrc);
+ hrTmp = VariantClear(&varDst);
+ ASSERT(hrTmp == NOERROR);
+ hrTmp = VariantClear(&varSrc);
+ ASSERT(hrTmp == NOERROR);
+ return hr;
+}
+
+
+// regression for unraided bug
+//
+// problem: VariantCopy/VariantCopyInd incorrectly report OutOfMemory
+// when copying a VT_BSTR that is NULL.
+//
+HRESULT
+VariantBug0(VARIANT_TEST_INFO FAR* dummy)
+{
+ BSTR bstr;
+ VARIANT varFrom, varTo;
+ HRESULT hresult, hresultTmp;
+
+ UNUSED(dummy);
+
+ V_VT(&varFrom) = VT_BSTR;
+ V_BSTR(&varFrom) = NULL;
+
+ VariantInit(&varTo);
+
+ IfFailRet(VariantCopy(&varTo, &varFrom));
+
+ hresultTmp = VariantClear(&varTo);
+ ASSERT(hresultTmp == NOERROR);
+
+ bstr = NULL;
+ V_VT(&varFrom) = VT_BYREF | VT_BSTR;
+ V_BSTRREF(&varFrom) = &bstr;
+
+ hresult = VariantCopyInd(&varTo, &varFrom);
+
+ hresultTmp = VariantClear(&varTo);
+ ASSERT(hresultTmp == NOERROR);
+
+ return hresult;
+}
+
+
+// regression test for raid:oleprog#82
+//
+// problem: variant copy on a VT_BSTR containing an embedded null
+// looses everything after the embedded null.
+//
+HRESULT
+VariantOleprog82(VARIANT_TEST_INFO FAR* dummy)
+{
+ BSTR bstr;
+ HRESULT hresult;
+ VARIANT varFrom, varTo;
+ static OLECHAR sz_embedded_null[] =
+ OLESTR("where is \0 the rest of my string?");
+
+
+ UNUSED(dummy);
+
+ VariantInit(&varTo);
+ VariantInit(&varFrom);
+
+ bstr = SysAllocStringLen(sz_embedded_null, sizeof(sz_embedded_null));
+
+ V_VT(&varFrom) = VT_BSTR;
+ V_BSTR(&varFrom) = bstr;
+
+ VariantInit(&varTo);
+
+ if((hresult = VariantCopy(&varTo, &varFrom)) != NOERROR)
+ goto LError0;
+
+ if(MEMCMP(V_BSTR(&varTo), sz_embedded_null, sizeof(sz_embedded_null)) != 0){
+ hresult = RESULT(E_UNEXPECTED);
+ goto LError1;
+ }
+
+
+ VariantClear(&varTo);
+ VariantClear(&varFrom);
+
+
+ bstr = SysAllocStringLen(sz_embedded_null, sizeof(sz_embedded_null));
+
+ V_VT(&varFrom) = VT_BYREF | VT_BSTR;
+ V_BSTRREF(&varFrom) = &bstr;
+
+ VariantInit(&varTo);
+
+ if((hresult = VariantCopyInd(&varTo, &varFrom)) != NOERROR)
+ goto LError0;
+
+ if(MEMCMP(V_BSTRREF(&varTo), sz_embedded_null, sizeof(sz_embedded_null)) != 0){
+ hresult = RESULT(E_UNEXPECTED);
+ goto LError1;
+ }
+
+ hresult = NOERROR;
+
+LError1:;
+ VariantClear(&varTo);
+
+LError0:;
+ VariantClearAll(&varFrom);
+
+ return hresult;
+}
+
+
+HRESULT
+VariantOleprog94(VARIANT_TEST_INFO FAR* dummy)
+{
+ BSTR bstr;
+ VARIANT var;
+ HRESULT hresult;
+
+ UNUSED(dummy);
+
+ bstr = SysAllocString(OLESTR("hello world"));
+ V_VT(&var) = VT_BYREF | VT_BSTR;
+ V_BSTRREF(&var) = &bstr;
+
+ hresult = doCoerce(&var, VT_BSTR);
+
+ VariantClearAll(&var);
+
+ return hresult;
+}
+
+
+// regression test for raid!oleprog#235
+//
+// Problem: not correctly handling variants of VT_UNKNOWN or VT_DISPATCH
+// that have a null IDispatch or IUnknown ptr.
+//
+HRESULT
+VariantOleprog235(VARIANT_TEST_INFO FAR* dummy)
+{
+ HRESULT hresult;
+ VARIANT varSrc, varDst;
+
+ UNUSED(dummy);
+
+ V_VT(&varSrc) = VT_UNKNOWN;
+ V_UNKNOWN(&varSrc) = NULL;
+ VariantInit(&varDst);
+ IfFailRet(VariantCopy(&varDst, &varSrc));
+ VariantClear(&varDst);
+
+ V_VT(&varSrc) = VT_DISPATCH;
+ V_DISPATCH(&varSrc) = NULL;
+ VariantInit(&varDst);
+ IfFailRet(VariantCopy(&varDst, &varSrc));
+ VariantClear(&varDst);
+
+ // a null object cannot be converted to any fundamental type -
+ // because there is no way for us to extract its value property
+
+ hresult = VariantChangeType(&varDst, &varSrc, 0, VT_I2);
+ if(hresult == NOERROR || GetScode(hresult) != DISP_E_TYPEMISMATCH)
+ return RESULT(E_FAIL);
+
+ VariantClear(&varDst);
+ VariantClear(&varSrc);
+ return NOERROR;
+}
+
+
+// regression test for raid!oleprog#351
+//
+// Problem: not correctly handling coersion of interface variants types
+// of VT_UNKNOWN, VT_DISPATCH, or VT_DISPATCHW
+//
+
+
+class CBar : public IUnknown {
+public:
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv);
+ STDMETHOD_(unsigned long, AddRef)(void);
+ STDMETHOD_(unsigned long, Release)(void);
+ CBar::CBar(){
+ m_refs = 1;
+ }
+private:
+ unsigned long m_refs;
+};
+STDMETHODIMP
+CBar::QueryInterface(REFIID riid, void FAR* FAR* ppv)
+{
+ if(!IsEqualIID(riid, IID_IUnknown))
+ if(!IsEqualIID(riid, IID_IDispatch))
+ return RESULT(E_NOINTERFACE);
+
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+}
+STDMETHODIMP_(unsigned long)
+CBar::AddRef()
+{
+ return ++m_refs;
+}
+STDMETHODIMP_(unsigned long)
+CBar::Release()
+{
+ if(--m_refs == 0){
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+HRESULT
+VariantOleprog351(VARIANT_TEST_INFO FAR* dummy)
+{
+ HRESULT hresult;
+ VARIANT varSrc, varDst;
+ IUnknown FAR* punk;
+
+ UNUSED(dummy);
+
+ if((punk = (IUnknown FAR*)new FAR CBar()) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ VariantInit(&varSrc);
+ VariantInit(&varDst);
+ V_VT(&varSrc) = VT_UNKNOWN;
+ V_UNKNOWN(&varSrc) = punk;
+
+ // Test Non-Interface Coersion
+ VariantClear(&varDst);
+ hresult = VariantChangeType(&varDst, &varSrc, 0, VT_I2);
+ if(!(hresult == NOERROR || GetScode(hresult) == DISP_E_TYPEMISMATCH))
+ return RESULT(E_FAIL);
+
+ // Test IUnknown Coersion
+ VariantClear(&varDst);
+ hresult = VariantChangeType(&varDst, &varSrc, 0, VT_UNKNOWN);
+ if(!(hresult == NOERROR || GetScode(hresult) == DISP_E_TYPEMISMATCH))
+ return RESULT(E_FAIL);
+
+ // Test IDispatch Coersion
+ VariantClear(&varDst);
+ hresult = VariantChangeType(&varDst, &varSrc, 0, VT_DISPATCH);
+ if(!(hresult == NOERROR || GetScode(hresult) == DISP_E_TYPEMISMATCH))
+ return RESULT(E_FAIL);
+
+ VariantClear(&varDst);
+ VariantClear(&varSrc);
+ return NOERROR;
+}
+
+class CFoo : public IUnknown {
+public:
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv);
+ STDMETHOD_(unsigned long, AddRef)(void);
+ STDMETHOD_(unsigned long, Release)(void);
+ CFoo::CFoo(){
+ m_refs = 0;
+ }
+private:
+ unsigned long m_refs;
+};
+STDMETHODIMP
+CFoo::QueryInterface(REFIID riid, void FAR* FAR* ppv)
+{
+ if(IsEqualIID(riid, IID_IUnknown)){
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ return RESULT(E_NOINTERFACE);
+}
+STDMETHODIMP_(unsigned long)
+CFoo::AddRef()
+{
+ return ++m_refs;
+}
+STDMETHODIMP_(unsigned long)
+CFoo::Release()
+{
+ if(--m_refs == 0){
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+
+HRESULT
+VariantBug1(VARIANT_TEST_INFO FAR* dummy)
+{
+ unsigned long refs;
+ VARIANT varDst, var;
+ HRESULT hresult;
+ IUnknown FAR* punk;
+
+ UNUSED(dummy);
+
+ if((punk = (IUnknown FAR*)new FAR CFoo()) == NULL)
+ return RESULT(E_OUTOFMEMORY);
+ punk->AddRef();
+
+ V_VT(&var) = VT_BYREF | VT_DISPATCH;
+ V_UNKNOWNREF(&var) = &punk;
+ VariantInit(&varDst);
+ hresult = VariantCopyInd(&varDst, &var);
+ ASSERT(hresult == NOERROR);
+ ASSERT(V_VT(&varDst) == VT_DISPATCH);
+ refs = punk->Release();
+ ASSERT(refs == 1);
+ refs = V_DISPATCH(&varDst)->Release();
+ ASSERT(refs == 0);
+
+ return NOERROR;
+}
+
diff --git a/private/oleauto/tests/disptest/cwbstr.cpp b/private/oleauto/tests/disptest/cwbstr.cpp
new file mode 100644
index 000000000..443ff47a3
--- /dev/null
+++ b/private/oleauto/tests/disptest/cwbstr.cpp
@@ -0,0 +1,320 @@
+/***
+*cbstr.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file implements the CBstrSuite test object.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+
+#include <limits.h>
+
+#include "tstsuite.h"
+
+ASSERTDATA
+
+#if OE_WIN32 && 0
+
+struct TEST {
+ HRESULT (*pfnTest)(void);
+ char FAR* szName;
+};
+
+
+HRESULT WBstrOleprog5(void);
+HRESULT WBstrOleprog8(void);
+HRESULT WBstrOleprog65(void);
+HRESULT WBstrOleprog234(void);
+HRESULT WBstrLimits(void);
+HRESULT WBstrConvert(void);
+
+static TEST rgtest[] = {
+ { WBstrOleprog5, "raid!oleprog#5W" }
+ , { WBstrOleprog8, "raid!oleprog#8W" }
+ , { WBstrOleprog65, "raid!oleprog#65W" }
+ , { WBstrOleprog234, "raid!oleprog#234W" }
+ , { WBstrLimits, "WBstr limits" }
+ , { WBstrConvert, "WBstr conversion" }
+};
+
+
+SUITE_CONSTRUCTION_IMPL(CWBstrSuite)
+
+SUITE_IUNKNOWN_IMPL(CWBstrSuite)
+
+
+//---------------------------------------------------------------------
+// ITestSuite Methods
+//---------------------------------------------------------------------
+
+STDMETHODIMP
+CWBstrSuite::GetNameOfSuite(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc("WBSTR API", pbstr);
+}
+
+STDMETHODIMP
+CWBstrSuite::GetNameOfLogfile(BSTR FAR* pbstr)
+{
+ return ErrBstrAlloc("wbstrapi.log", pbstr);
+}
+
+STDMETHODIMP
+CWBstrSuite::GetTestCount(unsigned int FAR* pcTests)
+{
+ *pcTests = DIM(rgtest);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CWBstrSuite::GetNameOfTest(unsigned int iTest, BSTR FAR* pbstr)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ *pbstr = SysAllocString(rgtest[iTest].szName);
+ return NOERROR;
+}
+
+
+/***
+*HRESULT CWBstrSuite::DoTest(unsigned int)
+*Purpose:
+* Execute a single CWBstrSuite test.
+*
+*Entry:
+* iTest = the index of the test to execute
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDMETHODIMP
+CWBstrSuite::DoTest(unsigned int iTest)
+{
+ if(iTest >= DIM(rgtest))
+ return RESULT(E_INVALIDARG);
+
+ return rgtest[iTest].pfnTest();
+}
+
+
+
+//---------------------------------------------------------------------
+// WBSTR Test Suites
+//---------------------------------------------------------------------
+
+
+// regression test for raid!oleprog:5
+//
+HRESULT
+WBstrOleprog5()
+{
+ unsigned int len;
+ WBSTR wbstr;
+static WCHAR a_string[] = L"a string";
+static WCHAR another_string[] = L"another (longer) string";
+
+ wbstr = SysAllocStringW(a_string);
+ if(wbstr == NULL)
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLenW(wbstr);
+ if(len != (unsigned int) lstrlenW(a_string))
+ return RESULT(E_FAIL);
+
+ if(!SysReAllocStringW(&wbstr, another_string))
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLenW(wbstr);
+ if(len != (unsigned int) lstrlenW(another_string))
+ return RESULT(E_FAIL);
+
+ SysFreeStringW(wbstr);
+
+ return NOERROR;
+}
+
+// regression test for raid!oleprog:8
+//
+HRESULT
+WBstrOleprog8()
+{
+ unsigned int len;
+ HRESULT hresult;
+ WBSTR wbstr1, wbstr2;
+#define LARGE_BSTR_SIZE 128600
+
+ if((wbstr1 = SysAllocStringLenW(NULL, LARGE_BSTR_SIZE)) == NULL){
+ hresult = RESULT(E_OUTOFMEMORY);
+ goto LError0;
+ }
+
+ if((wbstr2 = SysAllocStringW(L"hello world")) == NULL){
+ hresult = RESULT(E_OUTOFMEMORY);
+ goto LError1;
+ }
+
+ if((len = SysStringLenW(wbstr1)) != LARGE_BSTR_SIZE){
+ hresult = RESULT(E_FAIL);
+ goto LError2;
+ }
+
+ hresult = NOERROR;
+
+LError2:;
+ SysFreeStringW(wbstr1);
+
+LError1:;
+ SysFreeStringW(wbstr2);
+
+LError0:;
+ return hresult;
+
+#undef LARGE_BSTR_SIZE
+}
+
+// regression test for raid!oleprog:8
+//
+// SysAllocString of a string containing an embedded '\0' stops
+// copying at the '\0';
+//
+HRESULT
+WBstrOleprog65()
+{
+ WBSTR wbstr;
+ HRESULT hresult;
+static WCHAR sz_embedded_null[] = L"a string \0 with an embedded null";
+
+
+ wbstr = SysAllocStringLenW(sz_embedded_null, sizeof(sz_embedded_null));
+
+ hresult = (MEMCMP(wbstr, sz_embedded_null, sizeof(sz_embedded_null)) == 0)
+ ? NOERROR
+ : RESULT(E_UNEXPECTED);
+
+ SysFreeStringW(wbstr);
+
+ return hresult;
+}
+
+// regression test for raid!oleprog:234
+//
+// make sure we are properly handling Reallocing a bstr thats Null.
+//
+HRESULT
+WBstrOleprog234()
+{
+ unsigned int len;
+ WBSTR wbstr;
+static WCHAR szHooHa[] = L"HooHa";
+
+ wbstr = NULL;
+ if(!SysReAllocStringW(&wbstr, szHooHa))
+ return RESULT(E_OUTOFMEMORY);
+
+ len = SysStringLenW(wbstr);
+ if(len != (unsigned int) lstrlenW(szHooHa))
+ return RESULT(E_FAIL);
+
+ SysFreeStringW(wbstr);
+
+ return NOERROR;
+}
+
+HRESULT
+WBstrLimits()
+{
+ unsigned long u;
+ WBSTR wbstr;
+
+static unsigned long s2M = 2097152;
+static unsigned long INCREMENT = 262144;
+
+ DbPrintf("SysAllocStringLen()\n");
+
+ DbPrintf("linear increasing...\n");
+ for(u = 1; u < s2M; u+=INCREMENT){
+ DbPrintf("%lu\n", u);
+ wbstr = SysAllocStringLenW(NULL, (unsigned int)u);
+ Yield();
+ if(wbstr == NULL)
+ break;
+ SysFreeStringW(wbstr);
+ }
+ DbPrintf("max len = %lu\n", u-1);
+
+ DbPrintf("linear decreasing...\n");
+ for(u = s2M; u > 0; u-=INCREMENT){
+ DbPrintf("%lu\n", u);
+ wbstr = SysAllocStringLenW(NULL, (unsigned int)u);
+ Yield();
+ if(wbstr == NULL)
+ break;
+ SysFreeStringW(wbstr);
+ }
+ DbPrintf("max len = %lu\n", u);
+
+ return NOERROR;
+}
+
+
+HRESULT
+WBstrConvert()
+{
+ static char* rgStrVal[] = {
+ "This is line #1"
+ , "This is another line"
+ };
+
+ static WCHAR* rgWStrVal[] ={
+ L"This is line #1"
+ , L"This is another line"
+ };
+ BSTR bstr;
+ WBSTR wbstr;
+ unsigned long len;
+ unsigned int i;
+
+ DbPrintf("SysStringAtoW test\n");
+ for(i = 0; i < DIM(rgStrVal); i++) {
+ bstr = SysAllocString(rgStrVal[i]);
+ wbstr = SysStringAtoW(bstr, CP_ACP);
+ if (wbstr != NULL) {
+ len = SysStringLenW(wbstr);
+ if((len != (unsigned int) lstrlenW(rgWStrVal[i])) ||
+ (lstrcmpW(wbstr, rgWStrVal[i]) != 0))
+ return RESULT(E_FAIL);
+ SysFreeStringW(wbstr);
+ SysFreeString(bstr);
+ }
+ }
+
+ DbPrintf("SysStringWtoA test\n");
+ for(i = 0; i < DIM(rgWStrVal); i++) {
+ wbstr = SysAllocStringW(rgWStrVal[i]);
+ bstr = SysStringWtoA(wbstr, CP_ACP);
+ if (bstr != NULL) {
+ len = SysStringLen(bstr);
+ if((len != (unsigned int) lstrlen(rgStrVal[i])) ||
+ (lstrcmp(bstr, rgStrVal[i]) != 0))
+ return RESULT(E_FAIL);
+ SysFreeString(bstr);
+ SysFreeStringW(wbstr);
+ }
+ }
+
+ return NOERROR;
+}
+
+#endif
diff --git a/private/oleauto/tests/disptest/disptest.cpp b/private/oleauto/tests/disptest/disptest.cpp
new file mode 100644
index 000000000..f8cd8a163
--- /dev/null
+++ b/private/oleauto/tests/disptest/disptest.cpp
@@ -0,0 +1,316 @@
+/***
+*disptest.c - IDispatch test driver.
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This module contains the entry point for the IDispatch test app.
+*
+* iid.cpp - allocation of the ITestSuite IID
+* dtmisc.cpp - misc helpers and utilities
+* cbstr.cpp - CBstrSuite
+* cwbstr.cpp - CWBstrSuite (WIN32 Only)
+* ctime.cpp - CTimeSuite
+* cdatecnv.cpp = CDateCoersionSuite
+* cvariant.cpp - CVariantSuite
+* csarray.cpp - CSafeArraySuite
+* cinvval.cpp - CInvokeByValSuite
+* cinvref.cpp - CInvokeByRefSuite
+* cinvmult.cpp - CInvokeMultipleSuite
+* cinvsary.cpp - CInvokeSafeArraySuite
+* cinvex.cpp - CInvokeExcepinfoSuite
+* ccollect.cpp - CCollectionSuite
+* cearly.cpp - CEarlySuite
+*
+* REVIEW: tests still needed for the following,
+* heterogeneous variant arrays - csarray/cinvsary
+*
+*Revision History:
+*
+* [00] 23-Sep-92 bradlo: Added header.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+STDAPI_(void) PassFail(HRESULT, OLECHAR FAR*, HWND);
+STDAPI DispTestAll(HWND, int, int);
+STDAPI DispTestOne(HWND, int);
+
+BOOL InitApplication(HINSTANCE hinst);
+BOOL InitInstance(HINSTANCE hist, int nCmdShow);
+
+extern "C" BOOL CALLBACK EXPORT
+AboutDlgProc(HWND, unsigned, WORD, LONG);
+
+extern "C" LRESULT CALLBACK EXPORT
+MainWndProc(HWND, UINT, WPARAM, LPARAM);
+
+
+int g_fTrace = FALSE;
+int g_fNamed = FALSE;
+int g_fMultiThread = FALSE;
+int g_fDetectLeaks = FALSE;
+
+HINSTANCE g_hinst; // current instance
+
+HWND g_hwnd = NULL;
+
+TCHAR g_szFrameWinClass[] = TSTR("DispTestWinClass");
+
+#if OE_WIN32
+CRITICAL_SECTION g_csDbPrintf;
+#endif // OE_WIN32
+
+/***
+*int WinMain(HANDLE, HANDLE, LPSTR, int)
+*Purpose:
+* Windows recognizes this function by name as the initial entry
+* point for the program
+*
+*Entry:
+* hinst = instance handle of this instance
+* hinstPrev = instance handle of previous running instance (if any)
+* lpszCmdLine = command line passed to the program
+* nCmdShow = how to show the main window
+*
+*Exit:
+* return value = int, exit status of the program
+*
+***********************************************************************/
+extern "C" int PASCAL
+WinMain(
+ HINSTANCE hinst,
+ HINSTANCE hinstPrev,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ MSG msg;
+
+ if(!hinstPrev)
+ if(!InitApplication(hinst))
+ return FALSE;
+
+#if OE_WIN32
+ if(strstr(lpCmdLine, "-detectleaks"))
+#else
+ if(STRSTR(lpCmdLine, "-detectleaks"))
+#endif
+ g_fDetectLeaks = TRUE;
+
+ if(InitOle() != NOERROR)
+ return FALSE;
+
+ if(!InitInstance(hinst, nCmdShow) || !InitAppData()) {
+ UninitOle();
+ return FALSE;
+ }
+
+#if OE_WIN32
+ InitializeCriticalSection(&g_csDbPrintf);
+#endif // OE_WIN32
+
+#if OE_WIN32
+ if(strstr(lpCmdLine, "-all"))
+#else
+ if(STRSTR(lpCmdLine, "-all"))
+#endif
+ { DispTestAll(g_hwnd, FALSE, FALSE); PostQuitMessage(0); }
+
+ while(GetMessage(&msg, NULL, NULL, NULL)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ ReleaseAppData();
+ UninitOle();
+
+ return msg.wParam; /* Returns the value from PostQuitMessage */
+}
+
+BOOL
+InitApplication(HINSTANCE hinst)
+{
+ WNDCLASS wc;
+
+ wc.style = NULL;
+ wc.lpfnWndProc = MainWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hinst;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = TSTR("DispTestMenu");
+ wc.lpszClassName = g_szFrameWinClass;
+ if(!RegisterClass(&wc))
+ return FALSE;
+
+ return TRUE;
+}
+
+#ifdef WIN32
+#define szAppTitle TSTR("IDispatch Test App (32-bit)")
+#else //WIN32
+#define szAppTitle TSTR("IDispatch Test App")
+#endif //WIN32
+
+BOOL
+InitInstance(HINSTANCE hinst, int nCmdShow)
+{
+ HWND hwnd;
+
+ g_hinst = hinst;
+
+ /* Create a main window for this application instance. */
+
+ hwnd = CreateWindow(
+ g_szFrameWinClass,
+ szAppTitle, // title bar text
+ WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, // window style
+ CW_USEDEFAULT, // horizontal position
+ CW_USEDEFAULT, // vertical position
+ 550, // width position
+ 100, // height position
+ NULL, // no parent
+ NULL, // use the window class menu
+ hinst, // this instance owns this window
+ NULL); // pointer not needed
+
+ if(!hwnd)
+ return FALSE;
+
+#if OE_WIN16
+ // Multithreading is not availible on WIN16.
+ // UNDONE: Grey this for WIN32s.
+ //
+ EnableMenuItem(GetMenu(hwnd), IDM_OPTIONS_MULTITHREAD, MF_DISABLED);
+#endif // OE_WIN16
+
+ ShowWindow(hwnd, nCmdShow);
+ UpdateWindow(hwnd);
+
+ g_hwnd = hwnd;
+ return TRUE;
+}
+
+
+/***
+*BOOL AboutDlgProc(HWND, unsigned, WORD, LONG)
+*Purpose:
+* The "about" dialog box procedure.
+*
+*Entry:
+* hwndDlg = window handle for the dialog box
+* message = the window message
+* wparam = message data
+* lparam = message data
+*
+*Exit:
+* return value = BOOL. TRUE if processed message, FALSE if not
+*
+***********************************************************************/
+extern "C" BOOL CALLBACK EXPORT
+AboutDlgProc(HWND hwndDlg, unsigned message, WORD wparam, LONG lparam)
+{
+ switch(message){
+ case WM_INITDIALOG: /* message: initialize dialog box */
+ return TRUE;
+
+ case WM_COMMAND:
+ if(wparam == IDOK || wparam == IDCANCEL){
+ EndDialog(hwndDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+extern "C" LRESULT CALLBACK EXPORT
+MainWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ BOOL fChk;
+ HMENU hmenu;
+static DLGPROC pfnAboutDlgProc;
+ HRESULT hresult;
+
+ switch(message){
+ case WM_COMMAND:
+ switch(wparam){
+ case IDM_OPTIONS_MULTITHREAD:
+ fChk = g_fMultiThread = (g_fMultiThread) ? FALSE : TRUE;
+ goto LCheckMark;
+
+ case IDM_OPTIONS_TRACE:
+ fChk = g_fTrace = (g_fTrace) ? FALSE : TRUE;
+ goto LCheckMark;
+
+ case IDM_OPTIONS_NAMED:
+ fChk = g_fNamed = (g_fNamed) ? FALSE : TRUE;
+
+LCheckMark:;
+ hmenu = GetMenu(hwnd);
+ CheckMenuItem(hmenu, wparam, fChk ? MF_CHECKED : MF_UNCHECKED);
+ return 0;
+
+ case IDM_ALL:
+ hresult = DispTestAll(hwnd, TRUE, g_fMultiThread);
+
+ // If S_FALSE is returned, we've already displayed an error, so
+ // don't do it again.
+ //
+ if (GetScode(hresult) != S_FALSE) {
+ PassFail(hresult, OLESTR("Test All"), hwnd);
+ }
+
+ return 0;
+
+ case IDM_SUITE_BSTR:
+#if OE_WIN32 && 0
+ case IDM_SUITE_WBSTR:
+#endif
+ case IDM_SUITE_TIME:
+ case IDM_SUITE_DATECNV:
+ case IDM_SUITE_VARIANT:
+ case IDM_SUITE_SAFEARRAY:
+ case IDM_SUITE_NLS:
+ case IDM_SUITE_BIND:
+ case IDM_SUITE_INVOKE_BYVAL:
+ case IDM_SUITE_INVOKE_BYREF:
+ case IDM_SUITE_INVOKE_SAFEARRAY:
+ case IDM_SUITE_INVOKE_EXCEPINFO:
+ case IDM_SUITE_COLLECTION:
+#if VBA2
+ case IDM_SUITE_EARLY:
+#endif
+ DispTestOne(hwnd, wparam);
+ return 0;
+
+ case IDM_HELP_ABOUT:
+ pfnAboutDlgProc =
+ (DLGPROC)MakeProcInstance((DLGPROC)AboutDlgProc, g_hinst);
+ DialogBox(g_hinst, TSTR("AboutBox"), hwnd, pfnAboutDlgProc);
+ FreeProcInstance(pfnAboutDlgProc);
+ return 0;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ return 0;
+
+ case WM_DESTROY: /* message: window being destroyed */
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wparam, lparam);
+}
diff --git a/private/oleauto/tests/disptest/disptest.h b/private/oleauto/tests/disptest/disptest.h
new file mode 100644
index 000000000..6822aa2f5
--- /dev/null
+++ b/private/oleauto/tests/disptest/disptest.h
@@ -0,0 +1,63 @@
+/***
+*disptest.h
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* IDispatch test app definitions.
+*
+*Revision History:
+*
+* [00] 28-Sep-92 bradlo: Added this cool header.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#ifndef _DISPTEST_H_
+#define _DISPTEST_H_
+
+#include "common.h"
+#include "resource.h"
+#include "testhelp.h"
+#include "dispdbug.h"
+
+#ifdef _MAC
+# include <stdio.h>
+typedef FILE* HFILE;
+# define HFILE_ERROR NULL
+#endif
+
+// misc.cpp
+//
+struct APP_DATA {
+ HFILE m_hfLogfile;
+
+ APP_DATA() {
+ m_hfLogfile = HFILE_ERROR;
+ }
+};
+
+#if OE_WIN32
+extern unsigned long g_itlsAppData;
+#else // !OE_WIN32
+extern APP_DATA g_appdata;
+#endif // !OE_WIN32
+
+APP_DATA *Pappdata();
+BOOL InitAppData();
+VOID ReleaseAppData();
+
+STDAPI InitOle(void);
+STDAPI_(void) UninitOle(void);
+
+EXTERN_C void DbPrintf(char FAR*, ...);
+
+void PrintSuiteHeader(TCHAR FAR* szFmt, ...);
+void PrintTestHeader(TCHAR FAR* szFmt, ...);
+void PrintVarg(OLECHAR FAR* sz, VARIANTARG FAR* pvarg);
+void PrintDate(DATE date);
+
+#endif
+
diff --git a/private/oleauto/tests/disptest/guid.c b/private/oleauto/tests/disptest/guid.c
new file mode 100644
index 000000000..3cf489210
--- /dev/null
+++ b/private/oleauto/tests/disptest/guid.c
@@ -0,0 +1,56 @@
+/***
+*guid.c
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file allocates (via Ole macro mania) the ITestSuite IID.
+*
+*Revision History:
+*
+* [00] 31-Oct-92 bradlo: Created.
+*
+*****************************************************************************/
+
+#ifdef _MAC
+# ifdef _MSC_VER
+# include <macos/types.h>
+# include <macos/processe.h>
+# include <macos/appleeve.h>
+# define far
+# define FAR far
+# define near
+# define NEAR near
+# define PASCAL pascal
+# define cdecl _cdecl
+# define CDECL cdecl
+#ifndef _PPCMAC
+# define pascal _pascal
+#endif
+# else
+# include <Types.h>
+# include <Processes.h>
+# include <AppleEvents.h>
+# endif
+#else
+# include <windows.h>
+#endif
+
+#ifndef WIN32
+#include <compobj.h>
+#endif //!WIN32
+
+// this redefines the DEFINE_GUID() macro to do allocation.
+//
+#include <initguid.h>
+
+#ifndef INITGUID
+# define INITGUID
+#endif
+
+// due to the previous header, including this causes our DEFINE_GUID defs
+// in the following header(s) to actually allocate data.
+//
+#include "clsid.h"
+
diff --git a/private/oleauto/tests/disptest/macmain.cpp b/private/oleauto/tests/disptest/macmain.cpp
new file mode 100644
index 000000000..9ee2a2f40
--- /dev/null
+++ b/private/oleauto/tests/disptest/macmain.cpp
@@ -0,0 +1,1447 @@
+/***
+*mcdsptst.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* UNDONE
+*
+*
+*Revision History:
+*
+* [00] 28-Apr-93 bradlo: Created from TESample.c.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "disptest.h"
+#include "macmain.h"
+#include "resource.h"
+
+#if HC_MSC && !defined(_PPCMAC)
+#include <swap.h>
+#endif
+
+ASSERTDATA
+
+STDAPI
+DispTestOne(void*, int);
+
+typedef struct {
+ WindowRecord docWindow;
+ TEHandle docTE;
+ ControlHandle docVScroll;
+ ControlHandle docHScroll;
+#if 0
+// ProcPtr docClik;
+#endif
+} Doc;
+
+
+SysEnvRec g_sysenv;
+Boolean g_fInitOle = false;
+Boolean g_fInBackground = false;
+Boolean g_fLibrariesLoaded = false;
+
+short g_cNumDocs = 0;
+
+
+
+/* Define HIWRD and LOWRD macros for efficiency. */
+#define HIWRD(aLong) (((aLong) >> 16) & 0xFFFF)
+#define LOWRD(aLong) ((aLong) & 0xFFFF)
+
+/* Define TOPLEFT and BOTRIGHT macros for convenience. Notice the implicit
+ dependency on the ordering of fields within a Rect */
+#define TOPLEFT(aRect) (*(Point*)&(aRect).top)
+#define BOTRIGHT(aRect) (*(Point*)&(aRect).bottom)
+
+
+void
+Exit()
+{
+ if(g_fInitOle)
+ UninitOle();
+#ifndef _PPCMAC
+ if(g_fLibrariesLoaded)
+#endif
+#if 0
+ CleanupLibraryManager();
+#else
+#ifndef _PPCMAC
+ UninitOleManager(); // clean up applet
+#endif
+#endif
+ ExitToShell();
+}
+
+/* display fatal error alert, and exit */
+void
+Fatal(char *msg)
+{
+static const unsigned char pnil[2] = {0,0};
+ unsigned char buf[128];
+
+ SetCursor(&qd.arrow);
+
+ buf[0] = (unsigned char)strlen(msg);
+ memcpy(&buf[1], msg, buf[0]+1);
+
+ ParamText(buf, pnil, pnil, pnil);
+ Alert(rUserAlert, nil);
+ Exit();
+}
+
+extern "C" int
+main()
+{
+
+
+
+ Init();
+ long l = OleBuildVersion();
+ DbPrintf("OleBuildVersion = %d.%d\n", (int)HIWRD(l), (int)LOWRD(l));
+
+#ifdef _DEBUG
+ FnAssertOn(false); // TEMPORARY: to get around IMessageFilter assertions
+#endif
+ EventLoop();
+ return 0;
+}
+
+/* Get events forever, and handle them by calling DoEvent.
+ Also call AdjustCursor each time through the loop. */
+void
+EventLoop()
+{
+ Point mouse;
+ Boolean gotEvent;
+ EventRecord event;
+ RgnHandle cursorRgn;
+
+ cursorRgn = NewRgn(); /* we'll pass WNE an empty region the 1st time thru */
+ do{
+ GetGlobalMouse(&mouse);
+ AdjustCursor(mouse, cursorRgn);
+ gotEvent = WaitNextEvent(everyEvent, &event, GetSleep(), cursorRgn);
+ if(gotEvent){
+ /* make sure we have the right cursor before handling the event */
+ AdjustCursor(event.where, cursorRgn);
+ DoEvent(&event);
+ }else{
+ DoIdle(); /* perform idle tasks when it's not our event */
+ }
+
+ }while(true);
+}
+
+
+/* Do the right thing for an event. Determine what kind of event it is,
+ and call the appropriate routines. */
+void
+DoEvent(EventRecord *pevent)
+{
+ char key;
+ short part;
+ WindowPtr window;
+
+ switch(pevent->what){
+ case nullEvent:
+ // we idle for null/mouse moved events ands for events which
+ // aren't ours (see EventLoop)
+ DoIdle();
+ break;
+
+ case mouseDown:
+ part = FindWindow(pevent->where, &window);
+ switch(part){
+ case inMenuBar: /* process a mouse menu command (if any) */
+ AdjustMenus(); /* bring 'em up-to-date */
+ DoMenuCommand(MenuSelect(pevent->where));
+ break;
+
+ case inSysWindow: /* let the system handle the mouseDown */
+ SystemClick(pevent, window);
+ break;
+
+ case inContent:
+ if(window != FrontWindow()){
+ SelectWindow(window);
+ }else{
+ DoContentClick(window, pevent);
+ }
+ break;
+
+ case inDrag: /* pass screenBits.bounds to get all gDevices */
+ DragWindow(window, pevent->where, &qd.screenBits.bounds);
+ break;
+
+ case inGoAway:
+ if(TrackGoAway(window, pevent->where))
+ DoCloseWindow(window); /* we don't care if the user cancelled */
+ break;
+
+ case inGrow:
+ DoGrowWindow(window, pevent);
+ break;
+
+ case inZoomIn:
+ case inZoomOut:
+ if(TrackBox(window, pevent->where, part))
+ DoZoomWindow(window, part);
+ break;
+ }
+ break;
+
+ case keyDown:
+ case autoKey: /* check for menukey equivalents */
+ key = (char)(pevent->message & charCodeMask);
+ if(pevent->modifiers & cmdKey){/* Command key down */
+ if(pevent->what == keyDown){
+ AdjustMenus(); /* enable/disable/check menu items properly */
+ DoMenuCommand(MenuKey(key));
+ }
+ }else{
+ DoKeyDown(pevent);
+ }
+ break;
+
+ case activateEvt:
+ DoActivate(
+ (WindowPtr)pevent->message,
+ (Boolean)((pevent->modifiers & activeFlag) != 0));
+ break;
+
+ case updateEvt:
+ DoUpdate((WindowPtr)pevent->message);
+ break;
+
+ case kOSEvent:
+ switch((pevent->message >> 24) & 0x0FF){ /* high byte of message */
+ case kMouseMovedMessage:
+ DoIdle(); /* mouse-moved is also an idle event */
+ break;
+
+ case kSuspendResumeMessage:
+ /* suspend/resume is also an activate/deactivate */
+ g_fInBackground = (pevent->message & kResumeMask) == 0;
+ DoActivate(FrontWindow(), (Boolean)!g_fInBackground);
+ break;
+ }
+ break;
+
+ case kHighLevelEvent:
+ AEProcessAppleEvent(pevent);
+ break;
+ }
+}
+
+/* Change the cursor's shape, depending on its position. This also
+ calculates the region where the current cursor resides (for
+ WaitNextEvent). When the mouse moves outside of this region,
+ an event is generated. If there is more to the event than just
+ the mouse moved, we get called before the event is processed to
+ make sure the cursor is the right one. In any (ahem) event, this
+ is called again before we fall back into WNE. */
+void
+AdjustCursor(Point mouse, RgnHandle region)
+{
+ Rect iBeamRect;
+ WindowPtr window;
+ RgnHandle arrowRgn;
+ RgnHandle iBeamRgn;
+
+ /* we only adjust the cursor when we are in front */
+ window = FrontWindow();
+
+ if((!g_fInBackground) && (!IsDAWindow(window))){
+ /* calculate regions for different cursor shapes */
+ arrowRgn = NewRgn();
+ iBeamRgn = NewRgn();
+
+ /* start arrowRgn wide open */
+ SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
+
+ /* calculate iBeamRgn */
+ if(IsAppWindow(window)){
+ iBeamRect = (*((Doc*)window)->docTE)->viewRect;
+ SetPort(window); /* make a global version of the viewRect */
+ LocalToGlobal(&TOPLEFT(iBeamRect));
+ LocalToGlobal(&BOTRIGHT(iBeamRect));
+ RectRgn(iBeamRgn, &iBeamRect);
+ /* we temporarily change the port's origin to "globalfy" the visRgn */
+ SetOrigin(
+ (short)-window->portBits.bounds.left,
+ (short)-window->portBits.bounds.top);
+ SectRgn(iBeamRgn, window->visRgn, iBeamRgn);
+ SetOrigin((short)0, (short)0);
+ }
+
+ /* subtract other regions from arrowRgn */
+ DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
+
+ /* change the cursor and the region parameter */
+ if(PtInRgn(mouse, iBeamRgn)){
+ SetCursor(*GetCursor(iBeamCursor));
+ CopyRgn(iBeamRgn, region);
+ }else{
+ SetCursor(&qd.arrow);
+ CopyRgn(arrowRgn, region);
+ }
+ DisposeRgn(arrowRgn);
+ DisposeRgn(iBeamRgn);
+ }
+}
+
+/* Get the global coordinates of the mouse. When you call OSEventAvail
+ it will return either a pending event or a null event. In either case,
+ the where field of the event record will contain the current position
+ of the mouse in global coordinates and the modifiers field will reflect
+ the current state of the modifiers. Another way to get the global
+ coordinates is to call GetMouse and LocalToGlobal, but that requires
+ being sure that thePort is set to a valid port. */
+void
+GetGlobalMouse(Point *mouse)
+{
+ EventRecord event;
+
+ /* we aren't interested in any events */
+ OSEventAvail(kNoEvents, &event);
+
+ /* just the mouse position */
+ *mouse = event.where;
+}
+
+/* Called when a mouseDown occurs in the grow box of an active window.
+ In order to eliminate any 'flicker', we want to invalidate only what
+ is necessary. Since ResizeWindow invalidates the whole portRect, we
+ save the old TE viewRect, intersect it with the new TE viewRect, and
+ remove the result from the update region. However, we must make sure
+ that any old update region that might have been around gets put back. */
+void
+DoGrowWindow(WindowPtr window, EventRecord *event)
+{
+ Rect tempRect;
+ long growResult;
+ Doc* doc;
+ RgnHandle tempRgn;
+
+ tempRect = qd.screenBits.bounds; /* set up limiting values */
+ tempRect.left = kMinDocDim;
+ tempRect.top = kMinDocDim;
+ growResult = GrowWindow(window, event->where, &tempRect);
+
+ /* see if it really changed size */
+ if(growResult != 0){
+ doc = (Doc*)window;
+ /* save old text box */
+ tempRect = (*doc->docTE)->viewRect;
+ tempRgn = NewRgn();
+ /* get localized update region */
+ GetLocalUpdateRgn(window, tempRgn);
+ SizeWindow(window, (short)LOWRD(growResult), (short)HIWRD(growResult), (Boolean)true);
+ ResizeWindow(window);
+
+ /* calculate & validate the region that hasn't changed so
+ it won't get redrawn */
+ SectRect(&tempRect, &(*doc->docTE)->viewRect, &tempRect);
+ ValidRect(&tempRect); /* take it out of update */
+ InvalRgn(tempRgn); /* put back any prior update */
+ DisposeRgn(tempRgn);
+ }
+}
+
+/* Called when a mouseClick occurs in the zoom box of an active window.
+ Everything has to get re-drawn here, so we don't mind that
+ ResizeWindow invalidates the whole portRect. */
+void DoZoomWindow(WindowPtr window, short part)
+{
+ EraseRect(&window->portRect);
+ ZoomWindow(window, part, (Boolean)(window == FrontWindow()));
+ ResizeWindow(window);
+}
+
+/* Called when the window has been resized to fix up the controls and
+ content. */
+void ResizeWindow(WindowPtr window)
+{
+ AdjustScrollbars(window, true);
+ AdjustTE(window);
+ InvalRect(&window->portRect);
+}
+
+/* Returns the update region in local coordinates */
+void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn)
+{
+ /* save old update region */
+ CopyRgn(((WindowPeek) window)->updateRgn, localRgn);
+
+ OffsetRgn(
+ localRgn,
+ window->portBits.bounds.left,
+ window->portBits.bounds.top);
+}
+
+void
+DoUpdate(WindowPtr window)
+{
+ if(IsAppWindow(window)){
+ /* this sets up the visRgn */
+ BeginUpdate(window);
+ /* draw if updating needs to be done */
+ if(!EmptyRgn(window->visRgn))
+ DrawWindow(window);
+ EndUpdate(window);
+ }
+}
+
+/* This is called when a window is activated or deactivated.
+ It calls TextEdit to deal with the selection. */
+void
+DoActivate(WindowPtr window, Boolean becomingActive)
+{
+ Rect growRect;
+ Doc* doc;
+ RgnHandle tempRgn, clipRgn;
+
+ if(IsAppWindow(window)){
+ doc = (Doc*)window;
+ if(becomingActive){
+ /* since we don't want TEActivate to draw a selection in an
+ area where we're going to erase and redraw, we'll clip
+ out the update region before calling it. */
+ tempRgn = NewRgn();
+ clipRgn = NewRgn();
+ /* get localized update region */
+ GetLocalUpdateRgn(window, tempRgn);
+ GetClip(clipRgn);
+ /* subtract updateRgn from clipRgn */
+ DiffRgn(clipRgn, tempRgn, tempRgn);
+ SetClip(tempRgn);
+ TEActivate(doc->docTE);
+ /* restore the full-blown clipRgn */
+ SetClip(clipRgn);
+ DisposeRgn(tempRgn);
+ DisposeRgn(clipRgn);
+
+ /* the controls must be redrawn on activation: */
+ (*doc->docVScroll)->contrlVis = kControlVisible;
+ (*doc->docHScroll)->contrlVis = kControlVisible;
+ InvalRect(&(*doc->docVScroll)->contrlRect);
+ InvalRect(&(*doc->docHScroll)->contrlRect);
+ /* the growbox needs to be redrawn on activation: */
+ growRect = window->portRect;
+ /* adjust for the scrollbars */
+ growRect.top = growRect.bottom - kScrollbarAdjust;
+ growRect.left = growRect.right - kScrollbarAdjust;
+ InvalRect(&growRect);
+ }else{
+ TEDeactivate(doc->docTE);
+ /* the controls must be hidden on deactivation: */
+ HideControl(doc->docVScroll);
+ HideControl(doc->docHScroll);
+ /* the growbox should be changed immediately on deactivation: */
+ DrawGrowIcon(window);
+ }
+ }
+}
+
+/* This is called when a mouseDown occurs in the content of a window. */
+void
+DoContentClick(WindowPtr window, EventRecord *event)
+{
+ Rect teRect;
+ Point mouse;
+ Doc* doc;
+ short part, value;
+ Boolean shiftDown;
+ ControlHandle control;
+
+ if(IsAppWindow(window)){
+ SetPort(window);
+ mouse = event->where; /* get the click position */
+ GlobalToLocal(&mouse);
+ doc = (Doc*)window;
+ /* see if we are in the viewRect. if so, we won't check the controls */
+ GetTERect(window, &teRect);
+ if(PtInRect(mouse, &teRect)){
+ /* see if we need to extend the selection - extend if Shift is down */
+ shiftDown = (event->modifiers & shiftKey) != 0;
+ TEClick(mouse, shiftDown, doc->docTE);
+#if 0
+ PascalClikLoop();
+#endif
+ }else{
+ part = FindControl(mouse, window, &control);
+ switch(part){
+ case 0: /* do nothing for viewRect case */
+ break;
+ case inThumb:
+ value = GetCtlValue(control);
+ part = TrackControl(control, mouse, nil);
+ if(part != 0){
+ value -= GetCtlValue(control);
+ /* value now has CHANGE in value; if value changed, scroll */
+ if(value != 0){
+ if(control == doc->docVScroll){
+ TEScroll(
+ (short)0,
+ (short)(value * (*doc->docTE)->lineHeight),
+ doc->docTE);
+ }else{
+ TEScroll((short)value, (short)0, doc->docTE);
+ }
+ }
+ }
+ break;
+
+ default: /* they clicked in an arrow, so track & scroll */
+ if(control == doc->docVScroll)
+#ifdef _PPCMAC
+ value = TrackControl(control, mouse, (ControlActionUPP)VActionProc);
+ else
+ value = TrackControl(control, mouse, (ControlActionUPP)HActionProc);
+#else
+ value = TrackControl(control, mouse, (ProcPtr)VActionProc);
+ else
+ value = TrackControl(control, mouse, (ProcPtr)HActionProc);
+ break;
+#endif
+ }
+ }
+ }
+}
+
+/* This is called for any keyDown or autoKey events, except when the
+ Command key is held down. It looks at the frontmost window to decide what
+ to do with the key typed. */
+void
+DoKeyDown(EventRecord *event)
+{
+ char key;
+ TEHandle te;
+ WindowPtr window;
+
+ window = FrontWindow();
+ if(IsAppWindow(window)){
+ te = ((Doc*) window)->docTE;
+ key = (char)(event->message & charCodeMask);
+ /* we have a char. for our window; see if we are still below TextEditÕs
+ limit for the number of characters (but deletes are always rad) */
+ if(key == kDelChar
+ || (*te)->teLength - ((*te)->selEnd - (*te)->selStart)+1 < kMaxTELength)
+ {
+ TEKey(key, te);
+ AdjustScrollbars(window, false);
+ AdjustTE(window);
+ }
+ }
+}
+
+/* Common algorithm for pinning the value of a control. It returns
+ the actual amount the value of the control changed. Note the
+ pinning is done for the sake of returning the amount the control
+ value changed. */
+void
+CommonAction(ControlHandle control, short *amount)
+{
+ short value, max;
+
+ value = GetCtlValue(control); /* get current value */
+ max = GetCtlMax(control); /* and maximum value */
+ *amount = value - *amount;
+ if(*amount < 0)
+ *amount = 0;
+ else if(*amount > max)
+ *amount = max;
+ SetCtlValue(control, *amount);
+ *amount = value - *amount; /* calculate the real change */
+}
+
+/* Determines how much to change the value of the vertical scrollbar
+ by and how much to scroll the TE record. */
+extern "C"
+PASCAL_(void)
+VActionProc(ControlHandle control, short part)
+{
+ TEPtr te;
+ short amount;
+ WindowPtr window;
+
+ if(part != 0){ /* if it was actually in the control */
+ window = (*control)->contrlOwner;
+ te = *((Doc*) window)->docTE;
+ switch(part){
+ case inUpButton:
+ case inDownButton: /* one line */
+ amount = 1;
+ break;
+ case inPageUp: /* one page */
+ case inPageDown:
+ amount = (te->viewRect.bottom - te->viewRect.top) / te->lineHeight;
+ break;
+ }
+ if((part == inDownButton) || (part == inPageDown))
+ amount = -amount; /* reverse direction for a downer */
+ CommonAction(control, &amount);
+ if(amount != 0){
+ TEScroll((short)0,
+ (short)(amount * te->lineHeight),
+ ((Doc*)window)->docTE);
+ }
+ }
+}
+
+/* Determines how much to change the value of the horizontal scrollbar
+ by and how much to scroll the TE record. */
+extern "C"
+PASCAL_(void)
+HActionProc(ControlHandle control, short part)
+{
+ TEPtr te;
+ short amount;
+ WindowPtr window;
+
+ if(part != 0){
+ window = (*control)->contrlOwner;
+ te = *((Doc*) window)->docTE;
+ switch(part){
+ case inUpButton:
+ case inDownButton: /* a few pixels */
+ amount = kButtonScroll;
+ break;
+ case inPageUp: /* a page */
+ case inPageDown:
+ amount = te->viewRect.right - te->viewRect.left;
+ break;
+ }
+ if((part == inDownButton) || (part == inPageDown))
+ amount = -amount; /* reverse direction */
+ CommonAction(control, &amount);
+ if(amount != 0)
+ TEScroll(amount, 0, ((Doc*) window)->docTE);
+ }
+}
+
+/* This is called whenever we get a null event et al. It takes care
+ of necessary periodic actions. For this program, it calls TEIdle. */
+void
+DoIdle()
+{
+ WindowPtr window;
+
+ window = FrontWindow();
+ if(IsAppWindow(window))
+ TEIdle(((Doc*)window)->docTE);
+}
+
+/* Draw the contents of an application window. */
+void DrawWindow(WindowPtr window)
+{
+ SetPort(window);
+ EraseRect(&window->portRect);
+ DrawControls(window);
+ DrawGrowIcon(window);
+ TEUpdate(&window->portRect, ((Doc*)window)->docTE);
+}
+
+/* Enable and disable menus based on the current state. */
+
+void DoEnableItem(MenuHandle hmenu, short sItem) {
+ EnableItem(hmenu, sItem);
+}
+
+void DoDisableItem(MenuHandle hmenu, short sItem) {
+ DisableItem(hmenu, sItem);
+}
+
+/* Enable and disable menus based on the current state. */
+void
+AdjustMenus()
+{
+ long offset;
+ TEHandle hte;
+ MenuHandle menu;
+ WindowPtr window;
+ Boolean undo;
+ Boolean paste;
+ Boolean cutCopyClear;
+ void (*pfnEnable)(MenuHandle, short);
+
+#if 0
+
+ File
+ New
+ Close
+
+ Edit
+ Undo
+ Cut
+ Copy
+ Clear
+ Paste
+#endif
+
+ window = FrontWindow();
+
+ menu = GetMHandle(mFile);
+
+ pfnEnable = ((g_cNumDocs < kMaxOpenDocs) ? DoEnableItem : DoDisableItem);
+ pfnEnable(menu, iNew);
+
+ pfnEnable = ((window != nil) ? DoEnableItem : DoDisableItem);
+ pfnEnable(menu, iClose);
+
+ menu = GetMHandle(mEdit);
+ undo = false;
+ paste = false;
+ cutCopyClear = false;
+
+ if(IsDAWindow(window)){
+ undo = true; /* all editing is enabled for DA windows */
+ cutCopyClear = true;
+ paste = true;
+ }else if(IsAppWindow(window)){
+ hte = ((Doc*) window)->docTE;
+ if((*hte)->selStart < (*hte)->selEnd){
+ /* Cut, Copy, and Clear is enabled for app. windows with selections */
+ cutCopyClear = true;
+ }
+ if(GetScrap(nil, 'TEXT', &offset) > 0){
+ /* if there's any text in the clipboard, paste is enabled */
+ paste = true;
+ }
+ }
+
+ pfnEnable = (undo) ? DoEnableItem : DoDisableItem;
+ pfnEnable(menu, iUndo);
+
+ pfnEnable = (cutCopyClear) ? DoEnableItem : DoDisableItem;
+ pfnEnable(menu, iCut);
+ pfnEnable(menu, iCopy);
+ pfnEnable(menu, iClear);
+
+ pfnEnable = (paste) ? DoEnableItem : DoDisableItem;
+ pfnEnable(menu, iPaste);
+}
+
+
+/* This is called when an item is chosen from the menu bar (after calling
+ MenuSelect or MenuKey). It does the right thing for each command. */
+void
+DoMenuCommand(long menuResult)
+{
+ TEHandle te;
+ Str255 daName;
+ OSErr saveErr;
+ Handle aHandle;
+ WindowPtr window;
+ long oldSize, newSize, total, contig;
+ short menuID, menuItem, itemHit, daRefNum;
+static int rgIDMOfItem[] = {
+ -1 // <placeholder>
+ , IDM_SUITE_BSTR // iBstrAPI
+ , IDM_SUITE_TIME // iTimeAPI
+ , IDM_SUITE_DATECNV // iDateCnv
+ , IDM_SUITE_VARIANT // iVariantAPI
+ , IDM_SUITE_SAFEARRAY // iSafeArrayAPI
+ , IDM_SUITE_NLS // iNlsAPI
+ , IDM_SUITE_BIND // iBinding
+ , IDM_SUITE_INVOKE_BYVAL // iInvokeByVal
+ , IDM_SUITE_INVOKE_BYREF // iInvokeByRef
+ , IDM_SUITE_INVOKE_SAFEARRAY // iInvokeArray
+ , IDM_SUITE_INVOKE_EXCEPINFO // iInvokeExinfo
+ , IDM_SUITE_COLLECTION // iCollections
+};
+
+ window = FrontWindow();
+
+ menuID = (short)HIWRD(menuResult);
+ menuItem = (short)LOWRD(menuResult);
+
+ /* get menu item number and menu number */
+ switch(menuID){
+ case mApple:
+ switch(menuItem){
+ case iAbout: /* bring up alert for About */
+ itemHit = Alert(rAboutAlert, nil);
+ break;
+ default: /* all non-About items in this menu are DAs et al */
+ /* type Str255 is an array in MPW 3 */
+ GetMenuItemText(GetMHandle(mApple), menuItem, daName);
+ daRefNum = OpenDeskAcc(daName);
+ break;
+ }
+ break;
+
+ case mFile:
+ switch(menuItem){
+ case iNew:
+ DoNew();
+ break;
+ case iClose:
+ DoCloseWindow(FrontWindow()); /* ignore the result */
+ break;
+ case iQuit:
+ Terminate();
+ break;
+ }
+ break;
+
+ case mEdit: /* call SystemEdit for DA editing & MultiFinder */
+ if(!SystemEdit((short)(menuItem-1))){
+ te = ((Doc*)FrontWindow())->docTE;
+ switch(menuItem){
+ case iCut:
+ if(ZeroScrap() == noErr){
+ PurgeSpace(&total, &contig);
+ if((*te)->selEnd - (*te)->selStart + kTESlop > contig){
+ AlertUser(eNoSpaceCut);
+ }else{
+ TECut(te);
+ if(TEToScrap() != noErr){
+ AlertUser(eNoCut);
+ ZeroScrap();
+ }
+ }
+ }
+ break;
+
+ case iCopy:
+ if(ZeroScrap() == noErr){
+ TECopy(te); /* after copying, export the TE scrap */
+ if(TEToScrap() != noErr){
+ AlertUser(eNoCopy);
+ ZeroScrap();
+ }
+ }
+ break;
+
+ case iPaste: /* import the TE scrap before pasting */
+ if(TEFromScrap() == noErr){
+ if(TEGetScrapLen() + ((*te)->teLength -
+ ((*te)->selEnd - (*te)->selStart)) > kMaxTELength){
+ AlertUser(eExceedPaste);
+ }else{
+ aHandle = (Handle)TEGetText(te);
+ oldSize = GetHandleSize(aHandle);
+ newSize = oldSize + TEGetScrapLen() + kTESlop;
+ SetHandleSize(aHandle, newSize);
+ saveErr = MemError();
+ SetHandleSize(aHandle, oldSize);
+ if(saveErr != noErr)
+ AlertUser(eNoSpacePaste);
+ else
+ TEPaste(te);
+ }
+ }else{
+ AlertUser(eNoPaste);
+ }
+ break;
+
+ case iClear:
+ TEDelete(te);
+ break;
+ }
+ AdjustScrollbars(window, false);
+ AdjustTE(window);
+ }
+ break;
+
+ case mSuite:
+ switch(menuItem){
+ case iBstrAPI:
+ case iTimeAPI:
+ case iDateCnv:
+ case iVariantAPI:
+ case iSafeArrayAPI:
+ case iNlsAPI:
+ case iBinding:
+ case iInvokeByVal:
+ case iInvokeByRef:
+ case iInvokeArray:
+ case iInvokeExinfo:
+ case iCollections:
+ DispTestOne(NULL, rgIDMOfItem[menuItem]);
+ break;
+ }
+ break;
+
+ case mOptions:
+ switch(menuItem){
+ case iClearAll:
+ te = ((Doc*)FrontWindow())->docTE;
+ TESetSelect(0, 32767, te);
+ TEDelete(te);
+ break;
+ case iDebugger:
+ Debugger();
+ break;
+ }
+ break;
+ }
+ HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
+}
+
+/* Create a new document and window. */
+void
+DoNew()
+{
+ Ptr storage;
+ Boolean good;
+ Doc* doc;
+ WindowPtr window;
+ Rect destRect, viewRect;
+
+ storage = NewPtr(sizeof(Doc));
+ if(storage != nil){
+ window = GetNewWindow(rDocWindow, storage, (WindowPtr) -1);
+ if(window != nil){
+ /* this will be decremented when we call DoCloseWindow */
+ good = false;
+ g_cNumDocs += 1;
+ SetPort(window);
+
+ short font;
+ GetFNum((const unsigned char*)"\006Monaco", &font);
+ TextFont(font);
+ TextSize(9);
+
+ doc = (Doc*)window;
+ GetTERect(window, &viewRect);
+ destRect = viewRect;
+ destRect.right = destRect.left + kMaxDocWidth;
+ doc->docTE = TENew(&destRect, &viewRect);
+
+ /* if TENew succeeded, we have a good document */
+ good = doc->docTE != nil;
+ if(good){
+ AdjustViewRect(doc->docTE);
+ TEAutoView(true, doc->docTE);
+ }
+
+ if(good){
+ doc->docVScroll = GetNewControl(rVScroll, window);
+ good = (doc->docVScroll != nil);
+ }
+
+ if(good){
+ doc->docHScroll = GetNewControl(rHScroll, window);
+ good = (doc->docHScroll != nil);
+ }
+
+ if(good){ /* good? adjust & draw the controls, draw the window */
+ /* false to AdjustScrollValues means musn't redraw;
+ technically, of course, the window is hidden so
+ it wouldn't matter whether we called ShowControl
+ or not. */
+ AdjustScrollValues(window, false);
+ ShowWindow(window);
+ }else{
+ /* otherwise regret we ever created it... */
+ DoCloseWindow(window);
+ AlertUser(eNoWindow);
+ }
+ }else{
+ /* get rid of the storage if it is never used */
+ DisposPtr(storage);
+ }
+ }
+}
+
+
+/* Close a window. This handles desk accessory and application windows. */
+/* 1.01 - At this point, if there was a document associated with a
+ window, you could do any document saving processing if it is 'dirty'.
+ DoCloseWindow would return true if the window actually closed, i.e.,
+ the user didn't cancel from a save dialog. This result is handy when
+ the user quits an application, but then cancels the save of a document
+ associated with a window. */
+Boolean
+DoCloseWindow(WindowPtr window)
+{
+ TEHandle te;
+
+ if(IsDAWindow(window)){
+ CloseDeskAcc(((WindowPeek) window)->windowKind);
+ }else if(IsAppWindow(window)){
+ te = ((Doc*)window)->docTE;
+ if(te != nil){
+ /* dispose the TEHandle if we got far enough to make one */
+ TEDispose(te);
+ }
+ CloseWindow(window);
+ DisposPtr((Ptr)window);
+ g_cNumDocs -= 1;
+ }
+ return true;
+}
+
+/* Clean up the application and exit. We close all of the windows
+ so that they can update their documents, if any. */
+void
+Terminate()
+{
+ Boolean closed;
+ WindowPtr aWindow;
+
+ closed = true;
+ do{
+ aWindow = FrontWindow(); /* get the current front window */
+ if(aWindow != nil)
+ closed = DoCloseWindow(aWindow); /* close this window */
+ } while (closed && (aWindow != nil));
+
+ if(closed)
+ Exit(); /* exit if no cancellation */
+}
+
+/* Return a rectangle that is inset from the portRect by the
+ size of the scrollbars and a little extra margin. */
+void
+GetTERect(WindowPtr window, Rect *teRect)
+{
+ *teRect = window->portRect;
+ InsetRect(teRect, kTextMargin, kTextMargin);/* adjust for margin */
+ teRect->bottom = teRect->bottom - 15; /* and for the scrollbars */
+ teRect->right = teRect->right - 15;
+}
+
+/* Update the TERec's view rect so that it is the greatest multiple
+ of the lineHeight that still fits in the old viewRect. */
+void
+AdjustViewRect(TEHandle docTE)
+{
+ TEPtr te;
+
+ te = *docTE;
+ te->viewRect.bottom = (((te->viewRect.bottom - te->viewRect.top) / te->lineHeight) * te->lineHeight) + te->viewRect.top;
+}
+
+/* Scroll the TERec around to match up to the potentially updated
+ scrollbar values. This is really useful when the window has been
+ resized such that the scrollbars became inactive but the TERec
+ was already scrolled. */
+void
+AdjustTE(WindowPtr window)
+{
+ TEPtr te;
+
+ te = *((Doc*)window)->docTE;
+
+ TEScroll(
+ (short)((te->viewRect.left - te->destRect.left) -
+ GetCtlValue(((Doc*)window)->docHScroll)),
+ (short)((te->viewRect.top - te->destRect.top) -
+ (GetCtlValue(((Doc*)window)->docVScroll) * te->lineHeight)),
+ ((Doc*)window)->docTE);
+}
+
+
+/* Calculate the new control maximum value and current value, whether
+ it is the horizontal or vertical scrollbar. The vertical max is
+ calculated by comparing the number of lines to the vertical size
+ of the viewRect. The horizontal max is calculated by comparing the
+ maximum document width to the width of the viewRect. The current
+ values are set by comparing the offset between the view and
+ destination rects. If necessary and we canRedraw, have the control
+ be re-drawn by calling ShowControl. */
+void
+AdjustHV(
+ Boolean isVert,
+ ControlHandle control,
+ TEHandle docTE,
+ Boolean canRedraw)
+{
+ TEPtr te;
+ short value, lines, max, oldValue, oldMax;
+
+ oldValue = GetCtlValue(control);
+ oldMax = GetCtlMax(control);
+ te = *docTE; /* point to TERec for convenience */
+
+ if(isVert){
+ lines = te->nLines;
+ /* since nLines isn't right if the last character is a return,
+ check for that case */
+ if(*(*te->hText + te->teLength - 1) == kCrChar)
+ lines += 1;
+ max = lines - ((te->viewRect.bottom - te->viewRect.top) / te->lineHeight);
+ }else{
+ max = kMaxDocWidth - (te->viewRect.right - te->viewRect.left);
+ }
+
+ if ( max < 0 ) max = 0;
+ SetCtlMax(control, max);
+
+ /* Must deref. after SetCtlMax since, technically, it could
+ draw and therefore move memory. This is why we don't just
+ do it once at the beginning. */
+ te = *docTE;
+ if(isVert)
+ value = (te->viewRect.top - te->destRect.top) / te->lineHeight;
+ else
+ value = te->viewRect.left - te->destRect.left;
+
+ if(value < 0)
+ value = 0;
+ else if(value > max)
+ value = max;
+
+ SetCtlValue(control, value);
+ /* now redraw the control if it needs to be and can be */
+ if(canRedraw || (max != oldMax) || (value != oldValue))
+ ShowControl(control);
+}
+
+/* Simply call the common adjust routine for the vertical and
+ horizontal scrollbars. */
+void
+AdjustScrollValues(WindowPtr window, Boolean canRedraw)
+{
+ Doc* doc;
+
+ doc = (Doc*)window;
+ AdjustHV(true, doc->docVScroll, doc->docTE, canRedraw);
+ AdjustHV(false, doc->docHScroll, doc->docTE, canRedraw);
+}
+
+/* Re-calculate the position and size of the viewRect and the
+ scrollbars. kScrollTweek compensates for off-by-one requirements
+ of the scrollbars to have borders coincide with the growbox. */
+void
+AdjustScrollSizes(WindowPtr window)
+{
+ Rect teRect;
+ Doc* doc;
+
+ doc = (Doc*) window;
+ GetTERect(window, &teRect); /* start with TERect */
+ (*doc->docTE)->viewRect = teRect;
+ AdjustViewRect(doc->docTE); /* snap to nearest line */
+
+ MoveControl(
+ doc->docVScroll,
+ (short)(window->portRect.right - kScrollbarAdjust),
+ (short)-1);
+ SizeControl(
+ doc->docVScroll,
+ (short)kScrollbarWidth,
+ (short)((window->portRect.bottom - window->portRect.top) -
+ (kScrollbarAdjust - kScrollTweek)));
+
+ MoveControl(
+ doc->docHScroll,
+ (short)-1,
+ (short)(window->portRect.bottom - kScrollbarAdjust));
+ SizeControl(
+ doc->docHScroll,
+ (short)((window->portRect.right - window->portRect.left) -
+ (kScrollbarAdjust - kScrollTweek)),
+ (short)kScrollbarWidth);
+}
+
+/* Turn off the controls by jamming a zero into their contrlVis
+ fields (HideControl erases them and we don't want that). If the
+ controls are to be resized as well, call the procedure to do that,
+ then call the procedure to adjust the maximum and current values.
+ Finally re-enable the controls by jamming a $FF in their contrlVis
+ fields. */
+void
+AdjustScrollbars(WindowPtr window, Boolean needsResize)
+{
+ Doc* doc;
+
+ doc = (Doc*)window;
+
+ /* First, turn visibility of scrollbars off so we won't get
+ unwanted redrawing */
+ (*doc->docVScroll)->contrlVis = kControlInvisible; /* turn them off */
+ (*doc->docHScroll)->contrlVis = kControlInvisible;
+ if(needsResize) /* move & size as needed */
+ AdjustScrollSizes(window);
+
+ /* fool with max and current value */
+ AdjustScrollValues(window, needsResize);
+
+ /* Now, restore visibility in case we never had to ShowControl
+ during adjustment */
+ (*doc->docVScroll)->contrlVis = kControlVisible; /* turn them on */
+ (*doc->docHScroll)->contrlVis = kControlVisible;
+}
+
+#if 0
+/* Gets called from our assembly language routine, AsmClikLoop,
+ which is in turn called by the TEClick toolbox routine. Saves
+ the windows clip region, sets it to the portRect, adjusts the
+ scrollbar values to match the TE scroll amount, then restores
+ the clip region. */
+PASCAL_(Boolean)
+PascalClikLoop()
+{
+ WindowPtr window;
+ RgnHandle region;
+
+ window = FrontWindow();
+
+ region = NewRgn();
+ GetClip(region); /* save clip */
+ ClipRect(&window->portRect);
+ AdjustScrollValues(window, true); /* pass true for canRedraw */
+ SetClip(region); /* restore clip */
+ DisposeRgn(region);
+
+ return true;
+}
+#endif
+
+Boolean
+IsAppWindow(WindowPtr window)
+{
+ return (window == nil)
+ ? false : (((WindowPeek)window)->windowKind == userKind);
+}
+
+/* Check to see if a window belongs to a desk accessory. */
+Boolean IsDAWindow(WindowPtr window)
+{
+ /* DA windows have negative windowKinds */
+ return (window == nil)
+ ? false : (((WindowPeek)window)->windowKind < 0);
+}
+
+void
+AlertUser(short error)
+{
+ short itemHit;
+ Str255 message, tmp;
+
+ SetCursor(&qd.arrow);
+ GetIndString(message, kErrStrings, error);
+ tmp[0] = '\0';
+ ParamText(message, tmp, tmp, tmp);
+ itemHit = Alert(rUserAlert, nil);
+}
+
+PASCAL_(OSErr)
+RemoteLowLevelEvt(
+ AppleEvent theAppEvt,
+ AppleEvent reply,
+ long HandlerRefCon)
+{
+ long cb;
+ OSErr err;
+ DescType descType;
+ EventRecord event;
+
+ UNUSED(reply);
+ UNUSED(HandlerRefCon);
+
+ err = AEGetKeyPtr(
+ &theAppEvt,
+ keyDirectObject,
+ typeWildCard,
+ &descType,
+ (Ptr)&event,
+ sizeof(event),
+ &cb);
+
+ if(err != noErr){
+ ASSERT(0);
+ return err;
+ }
+
+ DoEvent(&event);
+
+ return noErr;
+}
+
+void
+InitAE()
+{
+ OSErr err;
+
+ err = AEInstallEventHandler(
+ 'OLE2', 'EVNT', (EventHandlerProcPtr)RemoteLowLevelEvt, 0, false);
+ ASSERT(err == noErr);
+}
+
+
+void
+Init()
+{
+ short count;
+ Handle menuBar;
+ long total, contig;
+ EventRecord event;
+
+ g_fInBackground = false;
+
+#if 0
+ MoreMasters();
+#endif
+ MaxApplZone();
+
+ InitGraf((Ptr)&qd.thePort);
+ InitFonts();
+ InitWindows();
+ InitMenus();
+ TEInit();
+ InitDialogs(nil);
+ InitCursor();
+ FlushEvents(everyEvent, 0);
+ InitCursor();
+
+ // REVIEW: move this above load of Ole?
+ SysEnvirons(kSysEnvironsVersion, &g_sysenv);
+ if (g_sysenv.machineType < 0
+ || g_sysenv.systemVersion < 0x0600
+ || g_sysenv.hasColorQD == false
+ || TrapExists(_WaitNextEvent) == false)
+ {
+ Fatal("System is too whimpy");
+ }
+
+ /* get MultiFinder started */
+ for(count = 1; count <= 3; count++)
+ EventAvail(everyEvent, &event);
+
+ /* make sure we have enough memory to run */
+ if((long)GetApplLimit() - (long)ApplicZone() < kMinHeap)
+ Fatal("Not enough memory to run");
+ PurgeSpace(&total, &contig);
+ if(total < kMinSpace)
+ Fatal("Not enough memory after purge");
+
+ menuBar = GetNewMBar(rMenuBar); /* read menus into menu bar */
+ if(menuBar == nil)
+ Fatal("Unable to load menu bar");
+ SetMenuBar(menuBar);
+ DisposHandle(menuBar);
+ AddResMenu(GetMHandle(mApple), 'DRVR'); /* add DA names to Apple menu */
+ DrawMenuBar();
+
+ DoNew();
+
+#ifdef _MSC_VER
+ DbPrintf("Wings Build\n");
+#else
+ DbPrintf("MPW Build\n");
+#endif
+
+ DbPrintf("InitLibraryManager\n");
+#ifndef _PPCMAC
+ if (InitOleManager(0) != NOERROR)
+ Fatal("Unable to initialize Library Manager");
+ g_fLibrariesLoaded = true;
+#endif
+
+ DbPrintf("Initializing Ole\n");
+ if(InitOle() != NOERROR)
+ Fatal("Failed to initialize Ole");
+ g_fInitOle = true;
+
+ InitAE();
+}
+
+/* Calculate a sleep value for WaitNextEvent. This takes into
+ account the things that DoIdle does with idle time. */
+unsigned long
+GetSleep()
+{
+ long sleep;
+ TEHandle te;
+ WindowPtr window;
+
+ sleep = MAXLONG; /* default value for sleep */
+ if(!g_fInBackground){
+ window = FrontWindow(); /* and the front window is ours... */
+ if(IsAppWindow(window)){
+ /* and the selection is an insertion point... */
+ te = ((Doc*)window)->docTE;
+ if((*te)->selStart == (*te)->selEnd){
+ /* blink time for the insertion point */
+ sleep = GetCaretTime();
+ }
+ }
+ }
+ return sleep;
+}
+
+/* Check the bits of a trap number to determine its type. If bit 11
+ is set, its a Toolbox trap, otherwise its an OS trap. */
+TrapType
+GetTrapType(short theTrap)
+{
+ return ((theTrap & 0x0800) == 0) ? OSTrap : ToolTrap;
+}
+
+/* Find the size of the Toolbox trap table. This can be either 0x0200
+ or 0x0400 bytes, depending on which Macintosh we are running on. We
+ determine the size by taking advantage of an anomaly of the smaller
+ trap table: any entries that fall beyond the end of the table are
+ mirrored back down into the lower part. For example, on a large table,
+ trap numbers A86E and AA6E correspond to different routines. However,
+ on a small table, they correspond to the same routine. By checking
+ the address of these routines, we can determine the size of the
+ table. */
+short
+NumToolboxTraps()
+{
+ return
+ (NGetTrapAddress((short)0xA86E, ToolTrap) ==
+ NGetTrapAddress((short)0xAA6E, ToolTrap)) ? 0x0200 : 0x0400;
+}
+
+/* Check to see if a given trap is implemented */
+Boolean
+TrapExists(short theTrap)
+{
+ TrapType theTrapType;
+
+ theTrapType = GetTrapType(theTrap);
+ if((theTrapType == ToolTrap)
+ && ((theTrap & 0x07FF) >= NumToolboxTraps()))
+ return false;
+ return (NGetTrapAddress((short)_Unimplemented, ToolTrap) !=
+ NGetTrapAddress(theTrap, theTrapType));
+}
+
+
+STDAPI_(void)
+OutputDebugString(const char *sz)
+{
+ long len;
+ TEHandle hTE;
+ WindowPtr window;
+
+ len = strlen(sz);
+
+ window = FrontWindow();
+ if(window == nil)
+ return;
+
+ hTE = ((Doc*)window)->docTE;
+ if(hTE == nil || *hTE == nil)
+ return;
+
+ // if this insertion will cause us to overflow the TextEdit
+ // buffer, then delete enough from the beginning of the buffer
+ // to make room
+
+ if(((long)(*hTE)->teLength + len) > 30000){
+ TESetSelect(0, 15000, hTE);
+ TEDelete(hTE);
+ TESetSelect(30000, 30000, hTE);
+ }
+
+ TEInsert(sz, len, hTE);
+ TESelView(hTE);
+}
+
diff --git a/private/oleauto/tests/disptest/macmain.h b/private/oleauto/tests/disptest/macmain.h
new file mode 100644
index 000000000..fc36822bc
--- /dev/null
+++ b/private/oleauto/tests/disptest/macmain.h
@@ -0,0 +1,191 @@
+
+#ifndef rez // {
+void AlertUser(short error );
+void EventLoop(void );
+void DoEvent( EventRecord *event );
+void AdjustCursor(Point mouse, RgnHandle region );
+void GetGlobalMouse(Point *mouse );
+void DoGrowWindow(WindowPtr window, EventRecord *event );
+void DoZoomWindow(WindowPtr window, short part );
+void ResizeWindow(WindowPtr window );
+void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn );
+void DoUpdate(WindowPtr window );
+void DoDeactivate(WindowPtr window );
+void DoActivate(WindowPtr window, Boolean becomingActive);
+void DoContentClick(WindowPtr window, EventRecord *event );
+void DoKeyDown(EventRecord *event );
+void CommonAction(ControlHandle control, short *amount);
+extern "C" PASCAL_(void) VActionProc(ControlHandle control, short part);
+extern "C" PASCAL_(void) HActionProc(ControlHandle control, short part);
+void DoIdle(void );
+void DrawWindow(WindowPtr window );
+void AdjustMenus(void );
+void DoMenuCommand(long menuResult );
+void DoNew(void );
+void Terminate(void );
+void Init(void );
+void BigBadError(short error );
+void GetTERect(WindowPtr window, Rect *teRect );
+void AdjustViewRect(TEHandle docTE );
+void AdjustTE(WindowPtr window );
+void AdjustHV(Boolean isVert, ControlHandle control, TEHandle docTE, Boolean canRedraw );
+void AdjustScrollValues(WindowPtr window, Boolean canRedraw );
+void AdjustScrollSizes(WindowPtr window );
+void AdjustScrollbars(WindowPtr window, Boolean needsResize );
+unsigned long GetSleep(void );
+Boolean DoCloseWindow(WindowPtr window );
+Boolean IsAppWindow(WindowPtr window );
+Boolean IsDAWindow(WindowPtr window );
+Boolean TrapExists(short tNumber);
+PASCAL_(Boolean) PascalClikLoop();
+#endif // }
+
+
+#define kPrefSize 3500
+#define kMinSize 2100
+
+/* The following constants are used to identify menus and their items.
+ The menu IDs have an "m" prefix and the item numbers within each menu
+ have an "i" prefix. */
+#define mApple 128 /* Apple menu */
+#define iAbout 1
+
+#define mFile 129 /* File menu */
+#define iNew 1
+#define iClose 4
+#define iQuit 12
+
+#define mEdit 130 /* Edit menu */
+#define iUndo 1
+#define iCut 3
+#define iCopy 4
+#define iPaste 5
+#define iClear 6
+
+#define mSuite 131
+#define iBstrAPI 1
+#define iTimeAPI 2
+#define iDateCnv 3
+#define iVariantAPI 4
+#define iSafeArrayAPI 5
+#define iNlsAPI 6
+#define iBinding 7
+#define iInvokeByVal 8
+#define iInvokeByRef 9
+#define iInvokeArray 10
+#define iInvokeExinfo 11
+#define iCollections 12
+
+#define mOptions 132
+#define iClearAll 1
+#define iDebugger 2
+
+#define kDITop 0x0050
+#define kDILeft 0x0070
+
+/* kTextMargin is the number of pixels we leave blank at the edge
+ of the window. */
+#define kTextMargin 2
+
+/* kMaxOpenDocs is used to determine whether a new document can be
+ opened or created. We keep track of the number of open documents, and
+ disable the menu items that create a new document when the maximum is
+ reached. If the number of documents falls below the maximum, the items
+ are enabled again. */
+#define kMaxOpenDocs 1
+
+/* kMaxDocWidth is an arbitrary number used to specify the width of the
+ TERec's destination rectangle so that word wrap and horizontal scrolling
+ can be demonstrated. */
+#define kMaxDocWidth 576
+
+/* kMinDocDim is used to limit the minimum dimension of a window when
+ GrowWindow is called. */
+#define kMinDocDim 64
+
+/* kControlInvisible is used to 'turn off' controls (i.e., cause the
+ control not to be redrawn as a result of some Control Manager call
+ such as SetCtlValue) by being put into the contrlVis field of the
+ record. kControlVisible is used the same way to 'turn on' the control. */
+#define kControlInvisible 0
+#define kControlVisible 0xFF
+
+/* kScrollbarAdjust and kScrollbarWidth are used in calculating
+ values for control positioning and sizing. */
+#define kScrollbarWidth 16
+#define kScrollbarAdjust (kScrollbarWidth - 1)
+
+/* kScrollTweek compensates for off-by-one requirements of the
+ scrollbars to have borders coincide with the growbox. */
+#define kScrollTweek 2
+
+/* kCrChar is used to match with a carriage return when calculating
+ the number of lines in the TextEdit record. kDelChar is used to
+ check for delete in keyDowns. */
+#define kCrChar 13
+#define kDelChar 8
+
+/* kButtonScroll is how many pixels to scroll horizontally when the
+ button part of the horizontal scrollbar is pressed. */
+#define kButtonScroll 4
+
+/* kMaxTELength is an arbitrary number used to limit the length of text
+ in the TERec so that various errors won't occur from too many characters
+ in the text. */
+#define kMaxTELength 32000
+
+/* kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
+ SysEnvRec we understand. */
+#define kSysEnvironsVersion 1
+
+/* kOSEvent is the event number of the suspend/resume and mouse-moved
+ events sent by MultiFinder. Once we determine that an event is an
+ OSEvent, we look at the high byte of the message sent to determine
+ which kind it is. To differentiate suspend and resume events we check
+ the resumeMask bit. */
+#define kOSEvent app4Evt /* event used by MultiFinder */
+
+/* high byte of suspend/resume event message */
+#define kSuspendResumeMessage 1
+
+/* bit of message field for resume vs. suspend */
+#define kResumeMask 1
+
+/* high byte of mouse-moved event message */
+#define kMouseMovedMessage 0xFA
+
+#define kNoEvents 0 /* no events mask */
+
+
+#define kMinHeap (29 * 1024)
+
+#define kMinSpace (20 * 1024)
+
+/* kExtremeNeg and kExtremePos are used to set up wide open rectangles
+ and regions. */
+#define kExtremeNeg -32768
+#define kExtremePos (32767 - 1) /* required to address an old region bug */
+
+/* kTESlop provides some extra security when pre-flighting edit commands. */
+#define kTESlop 1024
+
+/* The following are indicies into STR# resources. */
+#define eWrongMachine 1
+#define eSmallSize 2
+#define eNoMemory 3
+#define eNoSpaceCut 4
+#define eNoCut 5
+#define eNoCopy 6
+#define eExceedPaste 7
+#define eNoSpacePaste 8
+#define eNoWindow 9
+#define eExceedChar 10
+#define eNoPaste 11
+
+#define rMenuBar 128 /* application's menu bar */
+#define rAboutAlert 128 /* about alert */
+#define rUserAlert 129 /* user error alert */
+#define rDocWindow 128 /* application's window */
+#define rVScroll 128 /* vertical scrollbar control */
+#define rHScroll 129 /* horizontal scrollbar control */
+#define kErrStrings 128 /* error string list */
diff --git a/private/oleauto/tests/disptest/makefile b/private/oleauto/tests/disptest/makefile
new file mode 100644
index 000000000..e9e562dfc
--- /dev/null
+++ b/private/oleauto/tests/disptest/makefile
@@ -0,0 +1,552 @@
+##############################################################################
+#
+# (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved
+#
+# File:
+#
+# makefile - makefile for cdisptst.exe
+#
+# Purpose:
+#
+# Builds the OLE Automation test apps, cdisptst.exe.
+#
+#
+# Usage:
+#
+# NMAKE ; build with defaults
+# or: NMAKE option ; build with the given option(s)
+# or: NMAKE clean ; erase all compiled files
+#
+# option: dev = [win16 | win32 | mac] ; dev=win16 is the default
+#
+#
+# Notes:
+#
+# This makefile assumes that the PATH, INCLUDE and LIB environment
+# variables are setup properly.
+#
+#
+# Revision History:
+#
+# [00] 21-Sep-92 bradlo: Created
+# [00] 1-Mar-93 tometeng: Update for Win32 build
+#
+##############################################################################
+
+
+##########################################################################
+#
+# Default Settings
+#
+
+!if !defined(OLEPROG)
+!error OLEPROG environment variable not set
+!endif
+
+TESTS = $(OLEPROG)\TESTS
+!INCLUDE $(OLEPROG)\TESTS\OLEPROG.MAK
+
+APPS = cdisptst
+
+
+##########################################################################
+#
+# Common Directories
+#
+
+SRCDIR = $(TESTS)\DISPTEST
+COMDIR = $(TESTS)\COMMON
+
+
+##########################################################################
+#
+# Local WIN16 Settings
+#
+!if "$(TARG)" == "WIN16"
+
+OBJDIR = $(SRCDIR)\win16
+
+!if [if not exist $(OBJDIR)\*.* mkdir $(OBJDIR)] != 0
+!endif
+
+GOAL = $(OBJDIR)\$(APPS).exe
+
+LCFLAGS = -Fo$(OBJDIR)\ -Fd$(OBJDIR)\cdsptst.pdb -AM -GA -GEs -I$(COMDIR)
+
+INCPATHS = $(INCPATHS);$(OLEPROG)\TESTS\COMMON
+
+CLIBS = \
+ $(OLEPROG)\tools\win16\hdos\c800\lib\libw.lib \
+ $(OLEPROG)\tools\win16\hdos\c800\lib\mlibcew.lib \
+ $(OLEPROG)\tools\win16\hdos\c800\lib\shell.lib
+
+OLELIBS = \
+ $(OLEPROG)\ole\win16\lib\ole2.lib \
+ $(OLEPROG)\ole\win16\lib\compobj.lib \
+ $(OLEPROG)\dwin16\ole2disp.lib \
+ $(OLEPROG)\dwin16\ole2nls.lib
+
+OBJS = $(OBJDIR)\assert.obj \
+ $(OBJDIR)\dispdbug.obj \
+ $(OBJDIR)\dballoc.obj \
+# $(OBJDIR)\dispbind.obj \
+ $(OBJDIR)\cunk.obj \
+ $(OBJDIR)\cdisp.obj \
+ $(OBJDIR)\testhelp.obj \
+ $(OBJDIR)\util.obj \
+ $(OBJDIR)\suite.obj \
+ $(OBJDIR)\disptest.obj \
+ $(OBJDIR)\disphelp.obj \
+ $(OBJDIR)\crempoly.obj \
+ $(OBJDIR)\cbstr.obj \
+ $(OBJDIR)\cdatecnv.obj \
+ $(OBJDIR)\ctime.obj \
+ $(OBJDIR)\cnls.obj \
+ $(OBJDIR)\cvariant.obj \
+ $(OBJDIR)\cbind.obj \
+ $(OBJDIR)\cinvsary.obj \
+ $(OBJDIR)\cinvval.obj \
+ $(OBJDIR)\cinvref.obj \
+ $(OBJDIR)\cinvex.obj \
+ $(OBJDIR)\csarray.obj \
+ $(OBJDIR)\ccollect.obj \
+ $(OBJDIR)\cearly.obj \
+ $(OBJDIR)\misc.obj \
+ $(OBJDIR)\guid.obj
+
+$(OBJDIR)\$(APPS).exe : \
+ $(OBJS) \
+ $(CLIBS) \
+ $(OLELIBS) \
+ $(OBJDIR)\$(APPS).res
+ $(LD) $(LFLAGS) $(LNOI) @<<$(OBJDIR)\cdisptst.lnk
+$(OBJS: = +^
+)
+$@,
+$(OBJDIR)\$(APPS).map,
+$(CLIBS) +
+$(OLELIBS),
+$(SRCDIR)\$(APPS).def
+<<KEEP
+ rc -k -t $(OBJDIR)\$(APPS).res $@
+
+$(OBJDIR)\$(APPS).res : \
+ $(SRCDIR)\resource.h \
+ $(COMDIR)\assert.dlg \
+ $(SRCDIR)\$(APPS).rc
+ rc $(RCFLAGS) -r -fo$@ $(SRCDIR)\$(APPS).rc
+
+!endif
+
+
+##########################################################################
+#
+# WIN32 Settings
+#
+!if "$(TARG)" == "WIN32"
+
+OBJDIR = $(SRCDIR)\win32
+
+!if [if not exist $(OBJDIR)\*.* mkdir $(OBJDIR)] != 0
+!endif
+
+GOAL = $(OBJDIR)\$(APPS).exe
+
+LCFLAGS = -Fo$(OBJDIR)\ -I$(COMDIR)
+
+INCPATHS = $(INCPATHS);$(OLEPROG)\TESTS\COMMON
+
+LIBS = \
+ libcmt.lib \
+ kernel32.lib \
+ user32.lib \
+ gdi32.lib \
+ ole32.lib \
+ $(OLEPROG)\dwin32\oleaut32.lib \
+ uuid.lib
+
+
+OBJS = $(OBJDIR)\assert.obj \
+ $(OBJDIR)\dispdbug.obj \
+ $(OBJDIR)\dballoc.obj \
+ $(OBJDIR)\nlshelp.obj \
+# $(OBJDIR)\dispbind.obj \
+ $(OBJDIR)\cunk.obj \
+ $(OBJDIR)\cdisp.obj \
+ $(OBJDIR)\testhelp.obj \
+ $(OBJDIR)\util.obj \
+ $(OBJDIR)\suite.obj \
+ $(OBJDIR)\disptest.obj \
+ $(OBJDIR)\disphelp.obj \
+ $(OBJDIR)\crempoly.obj \
+ $(OBJDIR)\cbstr.obj \
+ $(OBJDIR)\cdatecnv.obj \
+ $(OBJDIR)\ctime.obj \
+ $(OBJDIR)\cvariant.obj \
+ $(OBJDIR)\cbind.obj \
+ $(OBJDIR)\cinvsary.obj \
+ $(OBJDIR)\cinvval.obj \
+ $(OBJDIR)\cinvref.obj \
+ $(OBJDIR)\cinvex.obj \
+ $(OBJDIR)\csarray.obj \
+ $(OBJDIR)\ccollect.obj \
+ $(OBJDIR)\cearly.obj \
+ $(OBJDIR)\misc.obj \
+ $(OBJDIR)\cnls.obj \
+ $(OBJDIR)\guid.obj
+
+$(OBJDIR)\$(APPS).exe : \
+ $(OBJS) \
+ $(SRCDIR)\$(APPS).def \
+ $(OBJDIR)\$(APPS).res
+ cvtres -$(CPU) $(OBJDIR)\$(APPS).res -o $(OBJDIR)\$(APPS).rs
+ $(LD) @<<
+ -entry:WinMainCRTStartup
+ -out:$@
+ -map:$*.map
+ -nodefaultlib
+ $(LFLAGS)
+ $(OBJS)
+ $(OBJDIR)\$(APPS).rs
+ $(LIBS)
+<<
+
+$(OBJDIR)\$(APPS).res : $(SRCDIR)\$(APPS).rc $(SRCDIR)\resource.h
+ rc $(RCFLAGS) -r -fo$@ $(SRCDIR)\$(APPS).rc
+
+!endif
+
+
+##########################################################################
+#
+# MAC Settings
+#
+!if "$(TARG)" == "MAC"
+
+OASRC = $(DISPDIR)\mac
+
+!if "$(TARGCPU)"=="PPC"
+OBJDIR = $(SRCDIR)\macppc
+!else
+OBJDIR = $(SRCDIR)\mac
+!endif
+
+!if [if not exist $(OBJDIR)\*.* mkdir $(OBJDIR)] != 0
+!endif
+
+MACLIBDIR = $(VBATOOLS)\win32\$(COMPILER)\LIB
+
+!if "$(TARGCPU)"=="PPC"
+LCFLAGS = -Fd$(OBJDIR)\cdisptst.pdb -Fo$(OBJDIR)\ -D _SLM
+!else
+LCFLAGS = -AL -Gt1 -Fd$(OBJDIR)\cdisptst.pdb -Fo$(OBJDIR)\ -D _SLM
+!endif
+
+
+INCPATHS = $(INCPATHS);$(OLEPROG)\TESTS\COMMON;$(VBATOOLS)\win32\$(COMPILER)\INC\MRC
+
+LIBS = \
+ $(MACLIBDIR)\interfac.lib \
+!if "$(TARGCPU)"=="PPC"
+ ole2auto.lib \
+ ole2.lib \
+ $(MACLIBDIR)\mprof.lib \
+ $(MACLIBDIR)\libc.lib
+!else
+ $(MACLIBDIR)\wlm.lib \
+!if ("$(SWAP)" == "1")
+ $(MACLIBDIR)\llibcs.lib \
+ $(MACLIBDIR)\lsanes.lib \
+ $(MACLIBDIR)\swap.lib
+!else
+ $(MACLIBDIR)\llibc.lib \
+ $(MACLIBDIR)\lsane.lib
+!endif
+
+OLEOBJS = \
+!if ("$(SWAP)" == "1")
+ $(OLEDIR)\olelds.obj $(OLEDIR)\oalds.obj
+!else
+ $(OLEDIR)\olendf.obj $(OLEDIR)\oandf.obj
+!endif
+
+!endif # TARGCPU=PPC
+
+
+
+STATIC_OBJS = \
+ $(OBJDIR)\assert.obj \
+ $(OBJDIR)\dispdbug.obj \
+ $(OBJDIR)\macmain.obj \
+ $(OBJDIR)\suite.obj \
+ $(OBJDIR)\dballoc.obj \
+ $(OBJDIR)\cunk.obj \
+ $(OBJDIR)\cdisp.obj \
+ $(OBJDIR)\testhelp.obj \
+ $(OBJDIR)\util.obj \
+ $(OBJDIR)\cbstr.obj \
+ $(OBJDIR)\cdatecnv.obj \
+ $(OBJDIR)\ctime.obj \
+ $(OBJDIR)\cnls.obj \
+ $(OBJDIR)\cvariant.obj \
+ $(OBJDIR)\csarray.obj \
+ $(OBJDIR)\misc.obj \
+ $(OBJDIR)\guid.obj \
+ $(OBJDIR)\oleguids.obj
+
+DLL_OBJS = \
+ $(OBJDIR)\disphelp.obj \
+ $(OBJDIR)\crempoly.obj \
+ $(OBJDIR)\cbind.obj \
+ $(OBJDIR)\cinvsary.obj \
+ $(OBJDIR)\cinvval.obj \
+ $(OBJDIR)\ccollect.obj \
+ $(OBJDIR)\cinvref.obj \
+ $(OBJDIR)\cinvex.obj
+
+OBJS = \
+ $(STATIC_OBJS) \
+ $(DLL_OBJS)
+
+
+$(OBJDIR)\$(APPS).exe : \
+ $(OBJS) \
+ $(OLEOBJS) \
+ $(OBJDIR)\$(APPS).x
+ $(LD) @<<
+ $(OBJS)
+ $(OLEOBJS)
+ $(LIBS)
+!if "$(TARGCPU)"=="PPC"
+ -machine:mppc
+!else
+ -machine:m68k
+!endif
+ -entry:mainCRTStartup
+ -debug:full
+ -debugtype:cv
+ -nopack
+ -nodefaultlib
+ -out:$@
+ -map:$*.map
+<<KEEP
+ cvpack $(OBJDIR)\$(APPS).exe
+
+
+$(OBJDIR)\$(APPS).x : $(SRCDIR)\$(APPS).r
+!if "$(TARGCPU)" == "PPC"
+ mrc -s$(VBATOOLS)\win32\ppc\lib -D_PPCMAC -o $(OBJDIR)\$(APPS).x $(SRCDIR)\$(APPS).r
+!else
+ mrc -D_MAC -o $(OBJDIR)\$(APPS).x $(SRCDIR)\$(APPS).r
+!endif
+
+!if "$(TARGCPU)" == "PPC"
+GOAL = $(OBJDIR)\$(APPS).pef
+
+$(OBJDIR)\$(APPS) : $(OBJDIR)\$(APPS).exe $(OBJDIR)\$(APPS).x
+ copy $(OBJDIR)\$(APPS).x $(OBJDIR)\$(APPS)
+ makepef $(OBJDIR)\$(APPS).exe $(OBJDIR)\$(APPS).pef
+
+!else
+
+GOAL = $(OBJDIR)\$(APPS)
+
+$(OBJDIR)\$(APPS) : $(OBJDIR)\$(APPS).exe $(OBJDIR)\$(APPS).x
+ copy $(OBJDIR)\$(APPS).x $(OBJDIR)\$(APPS)
+ mrc -e $(OBJDIR)\$(APPS).exe -a -o $(OBJDIR)\$(APPS)
+
+!endif
+
+$(OBJDIR)\oleguids.obj : $(SRCDIR)\oleguids.c $(SRCDIR)\oleguids.h
+ $(CC) -c $(SRCDIR)\oleguids.c
+
+$(OBJDIR)\macmain.obj : $(SRCDIR)\macmain.h $(SRCDIR)\macmain.cpp
+ $(CCPP) -c $(SRCDIR)\macmain.cpp
+
+!endif
+
+
+##########################################################################
+#
+# Default Goal
+#
+
+all : setflags $(GOAL)
+
+setflags :
+ set CL=$(CFLAGS) $(LCFLAGS)
+ set LIB=$(LIBPATHS)
+ set PATH=$(BINPATHS)
+ set INCLUDE=$(INCPATHS)
+
+
+##########################################################################
+#
+# Clean (erase) generated files
+#
+clean :
+ -erase $(OBJDIR)\*.obj
+ -erase $(OBJDIR)\*.lib
+ -erase $(OBJDIR)\*.dll
+ -erase $(OBJDIR)\*.exe
+ -erase $(OBJDIR)\*.map
+ -erase $(OBJDIR)\*.res
+ -erase $(OBJDIR)\*.rs
+ -erase $(OBJDIR)\*.lnk
+ -erase $(OBJDIR)\*.rpp
+ -erase $(OBJDIR)\*.x
+
+
+##########################################################################
+#
+# Dependencies
+#
+
+$(OBJDIR)\disptest.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\resource.h \
+ $(SRCDIR)\disptest.cpp
+ $(CCPP) -c $(SRCDIR)\disptest.cpp
+
+$(OBJDIR)\suite.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\resource.h \
+ $(SRCDIR)\suite.cpp
+ $(CCPP) -c $(SRCDIR)\suite.cpp
+
+$(OBJDIR)\misc.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\misc.cpp
+ $(CCPP) -c $(SRCDIR)\misc.cpp
+
+$(OBJDIR)\guid.obj : \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\clsid.h \
+ $(SRCDIR)\guid.c
+ $(CCPP) -c $(SRCDIR)\guid.c
+
+$(OBJDIR)\cbstr.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cbstr.cpp
+ $(CCPP) -c $(SRCDIR)\cbstr.cpp
+
+$(OBJDIR)\cwbstr.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cwbstr.cpp
+ $(CCPP) -c $(SRCDIR)\cwbstr.cpp
+
+$(OBJDIR)\cdatecnv.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cdatecnv.cpp
+ $(CCPP) -c $(SRCDIR)\cdatecnv.cpp
+
+$(OBJDIR)\ctime.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\ctime.cpp
+ $(CCPP) -c $(SRCDIR)\ctime.cpp
+
+$(OBJDIR)\cnls.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cnls.cpp
+ $(CCPP) -c $(SRCDIR)\cnls.cpp
+
+$(OBJDIR)\cbind.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cbind.cpp
+ $(CCPP) -c $(SRCDIR)\cbind.cpp
+
+$(OBJDIR)\cvariant.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cvariant.cpp
+ $(CCPP) -c $(SRCDIR)\cvariant.cpp
+
+$(OBJDIR)\csarray.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\csarray.cpp
+ $(CCPP) -c $(SRCDIR)\csarray.cpp
+
+$(OBJDIR)\cinvval.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cinvval.cpp
+ $(CCPP) -c $(SRCDIR)\cinvval.cpp
+
+$(OBJDIR)\cinvref.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cinvref.cpp
+ $(CCPP) -c $(SRCDIR)\cinvref.cpp
+
+$(OBJDIR)\cinvsary.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cinvsary.cpp
+ $(CCPP) -c $(SRCDIR)\cinvsary.cpp
+
+$(OBJDIR)\cinvex.obj : \
+ $(SRCDIR)\disptest.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cinvex.cpp
+ $(CCPP) -c $(SRCDIR)\cinvex.cpp
+
+$(OBJDIR)\ccollect.obj : \
+ $(SRCDIR)\disptest.h \
+ $(COMDIR)\crempoly.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\ccollect.cpp
+ $(CCPP) -c $(SRCDIR)\ccollect.cpp
+
+$(OBJDIR)\cearly.obj : \
+ $(SRCDIR)\disptest.h \
+ $(COMDIR)\dualtst.h \
+ $(SRCDIR)\tstsuite.h \
+ $(SRCDIR)\cearly.cpp
+ $(CCPP) -c $(SRCDIR)\cearly.cpp
+
+$(OBJDIR)\cunk.obj : $(COMDIR)\cunk.h $(COMDIR)\cunk.cpp
+ $(CCPP) -c $(COMDIR)\cunk.cpp
+
+$(OBJDIR)\cdisp.obj : $(COMDIR)\cdisp.h $(COMDIR)\cdisp.cpp
+ $(CCPP) -c $(COMDIR)\cdisp.cpp
+
+$(OBJDIR)\testhelp.obj : $(COMDIR)\testhelp.h $(COMDIR)\testhelp.cpp
+ $(CCPP) -c $(COMDIR)\testhelp.cpp
+
+$(OBJDIR)\util.obj : $(COMDIR)\common.h $(COMDIR)\util.cpp
+ $(CCPP) -c $(COMDIR)\util.cpp
+
+$(OBJDIR)\crempoly.obj : $(COMDIR)\crempoly.h $(COMDIR)\crempoly.cpp
+ $(CCPP) -c $(COMDIR)\crempoly.cpp
+
+$(OBJDIR)\disphelp.obj : $(COMDIR)\disphelp.h $(COMDIR)\disphelp.cpp
+ $(CCPP) -c $(COMDIR)\disphelp.cpp
+
+#$(OBJDIR)\dispbind.obj : $(COMDIR)\dispbind.cpp
+# $(CCPP) -c $(COMDIR)\dispbind.cpp
+
+$(OBJDIR)\assert.obj : \
+ $(COMDIR)\assrtdlg.h \
+ $(COMDIR)\assert.cpp
+ $(CCPP) -c $(COMDIR)\assert.cpp
+
+$(OBJDIR)\nlshelp.obj : \
+ $(COMDIR)\common.h \
+ $(COMDIR)\nlshelp.cpp
+ $(CCPP) -c $(COMDIR)\nlshelp.cpp
+
+$(OBJDIR)\dispdbug.obj : \
+ $(COMDIR)\common.h \
+ $(COMDIR)\dispdbug.h \
+ $(COMDIR)\dispdbug.cpp
+ $(CCPP) -c $(COMDIR)\dispdbug.cpp
+
+$(OBJDIR)\dballoc.obj : $(COMDIR)\dballoc.h $(COMDIR)\dballoc.cpp
+ $(CCPP) -c $(COMDIR)\dballoc.cpp
diff --git a/private/oleauto/tests/disptest/makefile.mpw b/private/oleauto/tests/disptest/makefile.mpw
new file mode 100644
index 000000000..ab3fb0a6e
--- /dev/null
+++ b/private/oleauto/tests/disptest/makefile.mpw
@@ -0,0 +1,181 @@
+#***
+#makefile.mpw
+#
+# Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+#
+#Purpose:
+# Makefile for the Ole Automation Test App (Client), cdisptst
+#
+#
+#Implementation Notes:
+#
+#****************************************************************************/
+
+OleRoot = HD:Ole2:
+
+OleIncDir= {OleRoot}MPW:Interfaces:CIncludes:
+OleLibDir= {OleRoot}MPW:Libraries:CLibraries:
+
+Common = hd:ole2auto:tests:common:
+ObjDir = hd:ole2auto:build:cdisptst:d:
+BinDir = hd:ole2auto:bin:
+
+defs = -d _MAC -d _DEBUG
+incs = -i {CIncludes} -i {OleIncDir} -i {Common}
+
+cflags = -mf -w3 -z6 -model far -sym full -mbg full {defs} {incs}
+cppflags = -mf -w3 -z6 -model far -sym full -mbg full {defs} {incs}
+
+pch = -load {ObjDir}disptest.h.dump
+
+AppleLibObjs = \
+ "{Libraries}"Runtime.o \
+ "{Libraries}"Interface.o \
+ "{CLibraries}"CPluslib.o \
+ "{CLibraries}"Math.o \
+ "{CLibraries}"CSANELib.o \
+ "{CLibraries}"StdCLib.o
+
+OleLibs = \
+ {OleLibDir}LibraryManager.o \
+ {OleLibDir}CompObjLib.cl.o \
+ {OleLibDir}DefLib.cl.o \
+ {OleLibDir}ole2nlsLib.cl.o \
+ {OleLibDir}ole2dispLib.cl.o
+
+pchObjs = \
+ {ObjDir}disptest.h.o
+
+commonObjs = \
+ {ObjDir}assert.cpp.o \
+ {ObjDir}cdisp.cpp.o \
+ {ObjDir}crempoly.cpp.o \
+ {ObjDir}cunk.cpp.o \
+ {ObjDir}dballoc.cpp.o \
+ {ObjDir}dispdbug.cpp.o \
+ {ObjDir}disphelp.cpp.o \
+ {ObjDir}testhelp.cpp.o \
+ {ObjDir}util.cpp.o
+
+Objs = \
+ {pchObjs} \
+ {commonObjs} \
+ {ObjDir}guid.c.o \
+ {ObjDir}oleguids.c.o \
+ {ObjDir}cbind.cpp.o \
+ {ObjDir}cbstr.cpp.o \
+ {ObjDir}ccollect.cpp.o \
+ {ObjDir}cdatecnv.cpp.o \
+ {ObjDir}cinvsary.cpp.o \
+ {ObjDir}cinvval.cpp.o \
+ {ObjDir}cinvref.cpp.o \
+ {ObjDir}cinvex.cpp.o \
+ {ObjDir}cnls.cpp.o \
+ {ObjDir}csarray.cpp.o \
+ {ObjDir}ctime.cpp.o \
+ {ObjDir}cvariant.cpp.o \
+ {ObjDir}macmain.cpp.o \
+ {ObjDir}misc.cpp.o \
+ {ObjDir}suite.cpp.o
+
+
+all ^ {ObjDir}cdisptst
+
+
+{ObjDir}cdisptst ^^ {Objs} {ObjDir}AppleLib.o {OleLibs} cdisptst.r resource.h
+ Link -model far -d -o {targ} -sym full {Objs} {ObjDir}AppleLib.o {OleLibs}
+ SetFile {targ} -t APPL -c 'CDSP' -a B
+ Rez -d _MAC -rd -append -o {targ} cdisptst.r
+ Duplicate -y {targ} {BinDir}
+ Duplicate -y {targ}.SYM {BinDir}
+
+{ObjDir}AppleLib.o ^ {AppleLibObjs}
+ Lib -o {ObjDir}AppleLib.o {AppleLibObjs}
+
+
+## precompiled header
+
+{ObjDir}disptest.h.o ^ disptest.h
+ cplus disptest.h -o {targ} {cppflags} -dumpc {ObjDir}disptest.h.dump
+
+
+{ObjDir}guid.c.o ^ guid.c
+ cplus guid.c -o {targ} {cppflags}
+
+{ObjDir}oleguids.c.o ^ oleguids.c oleguids.h
+ cplus oleguids.c -o {targ} {cppflags}
+
+
+{ObjDir}assert.cpp.o ^ {Common}assert.cpp
+ cplus {Common}assert.cpp -o {targ} {cppflags}
+
+{ObjDir}crempoly.cpp.o ^ {Common}crempoly.cpp disptest.h
+ cplus {Common}crempoly.cpp -o {targ} {cppflags}
+
+{ObjDir}cunk.cpp.o ^ {Common}cunk.cpp {Common}cunk.h
+ cplus {Common}cunk.cpp -o {targ} {cppflags}
+
+{ObjDir}cdisp.cpp.o ^ {Common}cdisp.cpp {Common}cdisp.h
+ cplus {Common}cdisp.cpp -o {targ} {cppflags}
+
+{ObjDir}dballoc.cpp.o ^ {Common}dballoc.cpp {Common}dballoc.h
+ cplus {Common}dballoc.cpp -o {targ} {cppflags}
+
+{ObjDir}dispdbug.cpp.o ^ {Common}dispdbug.cpp disptest.h
+ cplus {Common}dispdbug.cpp -o {targ} {cppflags}
+
+{ObjDir}disphelp.cpp.o ^ {Common}disphelp.cpp disptest.h
+ cplus {Common}disphelp.cpp -o {targ} {cppflags}
+
+{ObjDir}testhelp.cpp.o ^ {Common}testhelp.cpp disptest.h
+ cplus {Common}testhelp.cpp -o {targ} {cppflags}
+
+{ObjDir}util.cpp.o ^ {Common}util.cpp disptest.h
+ cplus {Common}util.cpp -o {targ} {cppflags}
+
+
+{ObjDir}cbind.cpp.o ^ cbind.cpp disptest.h
+ cplus cbind.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cbstr.cpp.o ^ cbstr.cpp disptest.h
+ cplus cbstr.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}ccollect.cpp.o ^ ccollect.cpp disptest.h
+ cplus ccollect.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cdatecnv.cpp.o ^ cdatecnv.cpp disptest.h
+ cplus cdatecnv.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cinvsary.cpp.o ^ cinvsary.cpp disptest.h
+ cplus cinvsary.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cinvval.cpp.o ^ cinvval.cpp disptest.h
+ cplus cinvval.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cinvref.cpp.o ^ cinvref.cpp disptest.h
+ cplus cinvref.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cinvex.cpp.o ^ cinvex.cpp disptest.h
+ cplus cinvex.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cnls.cpp.o ^ cnls.cpp disptest.h
+ cplus cnls.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}csarray.cpp.o ^ csarray.cpp disptest.h
+ cplus csarray.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}ctime.cpp.o ^ ctime.cpp disptest.h
+ cplus ctime.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}cvariant.cpp.o ^ cvariant.cpp disptest.h
+ cplus cvariant.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}macmain.cpp.o ^ macmain.cpp disptest.h
+ cplus macmain.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}misc.cpp.o ^ misc.cpp disptest.h
+ cplus misc.cpp -o {targ} {pch} {cppflags}
+
+{ObjDir}suite.cpp.o ^ suite.cpp disptest.h
+ cplus suite.cpp -o {targ} {pch} {cppflags}
+
diff --git a/private/oleauto/tests/disptest/misc.cpp b/private/oleauto/tests/disptest/misc.cpp
new file mode 100644
index 000000000..d5773d13a
--- /dev/null
+++ b/private/oleauto/tests/disptest/misc.cpp
@@ -0,0 +1,271 @@
+/***
+*misc.cpp
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* Misc DispTest helpers and initialization functions.
+*
+*Revision History:
+*
+* [00] 02-Oct-92 bradlo: Created
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "disptest.h"
+#include "dballoc.h"
+
+ASSERTDATA
+
+extern int g_fDetectLeaks;
+
+#if OE_WIN32
+extern CRITICAL_SECTION g_csDbPrintf;
+#endif // OE_WIN32
+
+int g_fLog = TRUE;
+
+OLECHAR FAR* g_szCPoly = OLESTR("spoly.cpoly");
+OLECHAR FAR* g_szCSArray = OLESTR("sdisptst.csarray");
+OLECHAR FAR* g_szCDispTst = OLESTR("sdisptst.cdisptst");
+OLECHAR FAR* g_szCExcepinfo = OLESTR("sdisptst.cexcepinfo");
+OLECHAR FAR* g_szCWExcepinfo = OLESTR("sdisptst.cwexcepinfo");
+
+#if OE_WIN32
+unsigned long g_itlsAppData = ~(ULONG)0;
+#else // !OE_WIN32
+APP_DATA g_appdata;
+#endif // !OE_WIN32
+
+APP_DATA *Pappdata()
+{
+#if OE_WIN32
+ return (APP_DATA *)TlsGetValue(g_itlsAppData);
+#else // !OE_WIN32
+ return &g_appdata;
+#endif // !OE_WIN32
+}
+
+
+BOOL InitAppData()
+{
+#if OE_WIN32
+ APP_DATA *pappdata;
+
+ if (g_itlsAppData == ~(ULONG)0) {
+ if ((g_itlsAppData = TlsAlloc()) == ~(ULONG)0) {
+ return FALSE;
+ }
+ }
+
+ ASSERT(TlsGetValue(g_itlsAppData) == NULL);
+
+ pappdata = new APP_DATA;
+
+ if (pappdata == NULL) {
+ return FALSE;
+ }
+
+ TlsSetValue(g_itlsAppData, (LPVOID)pappdata);
+#endif // OE_WIN32
+
+ return TRUE;
+}
+
+VOID ReleaseAppData()
+{
+#if OE_WIN32
+ ASSERT(g_itlsAppData != ~(ULONG)0);
+
+ delete Pappdata();
+ TlsSetValue(g_itlsAppData, NULL);
+#endif // OE_WIN32
+}
+
+STDAPI
+InitOle()
+{
+ HRESULT hresult;
+ IMalloc FAR* pmalloc;
+
+ pmalloc = NULL;
+
+#if OE_MAC
+
+#if 0
+ OSErr oserr = LoadAllLibraries();
+ if(oserr != noErr){
+ hresult = ResultFromScode(E_FAIL);
+ goto LError0;
+ }
+#endif
+
+#else
+
+#if !OE_WIN32 // latest OLE complains about our allocs not being
+ // properly aligned (it wants 8-byte alignment even
+ // on x86). New OLE debug allocator is pretty good
+ // now, so we'll just use theirs.
+ unsigned long options = DBALLOC_NONE;
+
+ if(g_fDetectLeaks)
+ options |= DBALLOC_DETECTLEAKS;
+
+ IfFailGo(CreateDbAlloc(options, NULL, &pmalloc), LError0);
+#endif //!OE_WIN32
+
+#endif
+
+ hresult = OleInitialize(pmalloc);
+
+#if !OE_WIN32
+LError0:;
+#endif // !OE_WIN32
+
+ if(pmalloc != NULL)
+ pmalloc->Release();
+
+ return hresult;
+}
+
+STDAPI_(void)
+UninitOle()
+{
+ OleUninitialize();
+}
+
+void
+PrintSuiteHeader(TCHAR FAR* szFmt, ...)
+{
+ int i, len;
+ va_list args;
+ TCHAR rgch[256];
+
+ va_start(args, szFmt);
+#if OE_MAC
+ vsprintf(rgch, szFmt, args);
+#else
+ wvsprintf(rgch, szFmt, args);
+#endif
+
+ DbPrintf("\n\nSuite : ");
+ DbPrintf((char FAR*)rgch);
+ DbPrintf("\n");
+ len = STRLEN(rgch) + 8;
+ for(i = 0; i < len+8; ++i)
+ rgch[i] = TSTR('-');
+ rgch[i] = TSTR('\n');
+ rgch[i+1] = TSTR('\0');
+ DbPrintf((char FAR*) rgch);
+}
+
+void
+PrintTestHeader(TCHAR FAR* szFmt, ...)
+{
+ va_list args;
+ TCHAR rgch[256];
+
+ va_start(args, szFmt);
+#if OE_MAC
+ vsprintf(rgch, szFmt, args);
+#else
+ wvsprintf(rgch, szFmt, args);
+#endif
+ DbPrintf("Test : ");
+ DbPrintf((char FAR*)rgch);
+ DbPrintf("\n");
+}
+
+
+#if OE_MAC
+STDAPI_(void) OutputDebugString(const OLECHAR*);
+#endif
+
+
+extern "C" void
+DbPrintf(char FAR* szFmt, ...)
+{
+ int len;
+ va_list args;
+ char *pn, FAR* pf;
+ static char rgchFmtBuf[512];
+ static char rgchOutputBuf[1024];
+
+#if OE_WIN32
+ EnterCriticalSection(&g_csDbPrintf);
+#endif // OE_WIN32
+
+#if HC_MPW
+
+ // translate all instances of %Fs to %s
+
+ for(pf=szFmt, pn=rgchFmtBuf; *pf != '\0';){
+
+ if(pf[0] == '%' && pf[1] == 'F' && pf[2] == 's'){
+ pn[0] = '%';
+ pn[1] = 's';
+ pf += 3;
+ pn += 2;
+ }else{
+ *pn++ = *pf++;
+ }
+
+ }
+ *pn = '\0';
+
+ pn = rgchFmtBuf;
+
+#else
+
+# if OE_WIN16
+
+ // copy the 'far' format string to a near buffer so we can use
+ // the medium model vsprintf, which only supports near data pointers.
+
+ pn = rgchFmtBuf, pf=szFmt;
+ while(*pf != '\0')
+ *pn++ = *pf++;
+ *pn = '\0';
+
+ pn = rgchFmtBuf;
+
+# else
+
+ pn = szFmt;
+
+# endif
+
+#endif
+
+ va_start(args, szFmt);
+ vsprintf(rgchOutputBuf, pn, args);
+
+ len = strlen(rgchOutputBuf);
+ ASSERT(len < DIM(rgchOutputBuf));
+#if OE_WIN32
+ OutputDebugStringA(rgchOutputBuf);
+#else
+ OutputDebugString(rgchOutputBuf);
+#endif
+ if(Pappdata()->m_hfLogfile != HFILE_ERROR){
+#if OE_MAC
+ fprintf(Pappdata()->m_hfLogfile, rgchOutputBuf);
+#else
+ _lwrite(Pappdata()->m_hfLogfile, rgchOutputBuf, len);
+#endif
+ }
+
+#if OE_WIN32
+ LeaveCriticalSection(&g_csDbPrintf);
+#endif // OE_WIN32
+
+}
+
diff --git a/private/oleauto/tests/disptest/oleguids.c b/private/oleauto/tests/disptest/oleguids.c
new file mode 100644
index 000000000..360169b83
--- /dev/null
+++ b/private/oleauto/tests/disptest/oleguids.c
@@ -0,0 +1,51 @@
+/***
+*oleguids.c
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file allocates (via Ole macro mania) the Ole GUIDS that are
+* referenced by the OLEDISP dll.
+*
+*Revision History:
+*
+* [00] 21-Jan-93 bradlo: Created.
+*
+*****************************************************************************/
+
+#ifdef _MAC
+# ifdef _MSC_VER
+# include <macos/types.h>
+# include <macos/processe.h>
+# include <macos/appleeve.h>
+# define far
+# define FAR far
+# define near
+# define NEAR near
+# define pascal _pascal
+# define PASCAL pascal
+# define cdecl _cdecl
+# define CDECL cdecl
+# else
+# include <Types.h>
+# include <Processes.h>
+# include <AppleEvents.h>
+# endif
+#endif
+#include <compobj.h>
+
+// this redefines the Ole DEFINE_GUID() macro to do allocation.
+//
+#include <initguid.h>
+
+#ifndef INITGUID
+# define INITGUID
+#endif
+
+// due to the previous header, including this causes our DEFINE_GUID
+// definitions in the following headers to actually allocate data.
+
+// instantiate the ole2 guids that we use
+#include "oleguids.h"
+
diff --git a/private/oleauto/tests/disptest/oleguids.h b/private/oleauto/tests/disptest/oleguids.h
new file mode 100644
index 000000000..446f7631b
--- /dev/null
+++ b/private/oleauto/tests/disptest/oleguids.h
@@ -0,0 +1,37 @@
+/***
+*oleguids.h
+*
+* Copyright (C) 1993, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This file is a subset of the Ole2 guid header: coguid.h.
+*
+* This file is used to instantiate the data for the Ole2 IIDs that
+* are used in OLEDISP.DLL, rather than linking with the Ole2 implib,
+* which causes us to pull in way more IID and CLSID definitions than
+* we want.
+*
+* NOTE: the GUIDs below must be *exactly* the same as those assigned
+* by the Ole group - If the Ole group ever changes their numbers, we
+* must change accordingly.
+*
+*Revision History:
+*
+* [00] 03-Jun-93 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
+
+#ifdef _MAC
+DEFINE_OLEGUID(IID_IDispatch, 0x00020400L, 0, 0);
+DEFINE_OLEGUID(IID_IEnumVARIANT,0x00020404L, 0, 0);
+#endif
+
diff --git a/private/oleauto/tests/disptest/pch.cpp b/private/oleauto/tests/disptest/pch.cpp
new file mode 100644
index 000000000..9a23250d4
--- /dev/null
+++ b/private/oleauto/tests/disptest/pch.cpp
@@ -0,0 +1,5 @@
+// this file is used to construct the precompiled header
+
+#include "disptest.h"
+#include "tstsuite.h"
+
diff --git a/private/oleauto/tests/disptest/resource.h b/private/oleauto/tests/disptest/resource.h
new file mode 100644
index 000000000..c3a0102a6
--- /dev/null
+++ b/private/oleauto/tests/disptest/resource.h
@@ -0,0 +1,41 @@
+#ifdef _MAC
+# define MBARID_CDISPTST 128
+# define MENUID_APPLE 128
+# define ICONID_CDISPTST 228
+#endif
+
+#define IDM_ALL 200
+
+#define IDM_SUITE 300
+#define IDM_SUITE_BSTR 301
+#define IDM_SUITE_TIME 302
+#define IDM_SUITE_DATECNV 303
+#define IDM_SUITE_VARIANT 304
+#define IDM_SUITE_SAFEARRAY 305
+#define IDM_SUITE_NLS 306
+#define IDM_SUITE_BIND 307
+#define IDM_SUITE_INVOKE_BYVAL 308
+#define IDM_SUITE_INVOKE_BYREF 309
+#define IDM_SUITE_INVOKE_MULTIPLE 310
+#define IDM_SUITE_INVOKE_SAFEARRAY 311
+#define IDM_SUITE_INVOKE_EXCEPINFO 312
+#define IDM_SUITE_COLLECTION 313
+#define IDM_SUITE_EARLY 314
+
+#define IDM_OPTIONS 400
+#define IDM_OPTIONS_TRACE 401
+#define IDM_OPTIONS_NAMED 402
+#define IDM_OPTIONS_MULTITHREAD 403
+
+#define IDM_HELP 500
+#define IDM_HELP_ABOUT 501
+
+
+#define IDD_SUITE_NAME 600
+#define IDD_SUITE_TESTNAME 601
+#define IDD_SUITE_PERCENT 603
+#define IDD_SUITE_GUAGE 604
+
+#ifdef WIN32
+#define IDM_SUITE_WBSTR 314
+#endif
diff --git a/private/oleauto/tests/disptest/src2mac.mak b/private/oleauto/tests/disptest/src2mac.mak
new file mode 100644
index 000000000..7100cf7b1
--- /dev/null
+++ b/private/oleauto/tests/disptest/src2mac.mak
@@ -0,0 +1,228 @@
+#***
+#src2mac.mak
+#
+# Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+# Information Contained Herein Is Proprietary and Confidential.
+#
+#Purpose:
+# UNDONE
+#
+#
+#Revision History:
+#
+# [00] 15-Jun-93 bradlo: Created.
+#
+#Implementation Notes:
+#
+#****************************************************************************/
+
+.SUFFIXES: .c .cpp .h
+
+all: setflags files
+
+# source directories
+#
+SRCCOMN = $(OLEPROG)\TESTS\COMMON
+SRCCDSP = $(OLEPROG)\TESTS\DISPTEST
+
+# destination directories
+#
+MACCOMN = :hd:ole2auto:tests:common:
+MACCDSP = :hd:ole2auto:tests:disptest:
+
+# timestamp directories
+#
+TMPCOMN = $(TMP)\common
+TMPCDSP = $(TMP)\disptest
+
+CP2MAC=ec copy -l -t TEXT -c "MPS "
+
+setflags:
+ set path=%tools%\hnt\wings\bin;%oleprog%\bin
+ if not exist %TMP%\common mkdir %TMP%\common
+ if not exist %TMP%\disptest mkdir %TMP%\disptest
+
+
+files : common cdisptst
+
+common : \
+ $(TMPCOMN)\assrtdlg.h \
+ $(TMPCOMN)\cdisp.h \
+ $(TMPCOMN)\common.h \
+ $(TMPCOMN)\crempoly.h \
+ $(TMPCOMN)\cunk.h \
+ $(TMPCOMN)\dballoc.h \
+ $(TMPCOMN)\dispdbug.h \
+ $(TMPCOMN)\disphelp.h \
+ $(TMPCOMN)\testhelp.h \
+ $(TMPCOMN)\assert.cpp \
+ $(TMPCOMN)\cdisp.cpp \
+ $(TMPCOMN)\crempoly.cpp \
+ $(TMPCOMN)\cunk.cpp \
+ $(TMPCOMN)\dispdbug.cpp \
+ $(TMPCOMN)\dballoc.cpp \
+ $(TMPCOMN)\disphelp.cpp \
+ $(TMPCOMN)\testhelp.cpp \
+ $(TMPCOMN)\util.cpp
+
+cdisptst : \
+ $(TMPCDSP)\clsid.h \
+ $(TMPCDSP)\disptest.h \
+ $(TMPCDSP)\macmain.h \
+ $(TMPCDSP)\oleguids.h \
+ $(TMPCDSP)\resource.h \
+ $(TMPCDSP)\tstsuite.h \
+ $(TMPCDSP)\guid.c \
+ $(TMPCDSP)\oleguids.c \
+ $(TMPCDSP)\cbind.cpp \
+ $(TMPCDSP)\cbstr.cpp \
+ $(TMPCDSP)\ccollect.cpp \
+ $(TMPCDSP)\cdatecnv.cpp \
+ $(TMPCDSP)\cinvsary.cpp \
+ $(TMPCDSP)\cinvval.cpp \
+ $(TMPCDSP)\cinvref.cpp \
+ $(TMPCDSP)\cinvex.cpp \
+ $(TMPCDSP)\cnls.cpp \
+ $(TMPCDSP)\csarray.cpp \
+ $(TMPCDSP)\ctime.cpp \
+ $(TMPCDSP)\cvariant.cpp \
+ $(TMPCDSP)\macmain.cpp \
+ $(TMPCDSP)\misc.cpp \
+ $(TMPCDSP)\suite.cpp \
+ $(TMPCDSP)\cdisptst.r \
+ $(TMPCDSP)\makefile.tmp
+
+
+#---------------------------------------------------------------------
+# default rules
+#---------------------------------------------------------------------
+
+##### tests\common
+
+{$(SRCCOMN)}.h{$(TMPCOMN)}.h:
+ $(CP2MAC) $< $(MACCOMN)$(@F)
+ echo $(@F) > $@
+
+{$(SRCCOMN)}.c{$(TMPCOMN)}.c:
+ $(CP2MAC) $< $(MACCOMN)$(@F)
+ echo $(@F) > $@
+
+{$(SRCCOMN)}.cpp{$(TMPCOMN)}.cpp:
+ $(CP2MAC) $< $(MACCOMN)$(@F)
+ echo $(@F) > $@
+
+
+##### tests\disptest
+
+{$(SRCCDSP)}.h{$(TMPCDSP)}.h:
+ $(CP2MAC) $< $(MACCDSP)$(@F)
+ echo $(@F) > $@
+
+{$(SRCCDSP)}.c{$(TMPCDSP)}.c:
+ $(CP2MAC) $< $(MACCDSP)$(@F)
+ echo $(@F) > $@
+
+{$(SRCCDSP)}.cpp{$(TMPCDSP)}.cpp:
+ $(CP2MAC) $< $(MACCDSP)$(@F)
+ echo $(@F) > $@
+
+
+#---------------------------------------------------------------------
+# common test sources
+#---------------------------------------------------------------------
+
+$(TMPCOMN)\assrtdlg.h : $(SRCCOMN)\assrtdlg.h
+
+$(TMPCOMN)\cdisp.h : $(SRCCOMN)\cdisp.h
+
+$(TMPCOMN)\common.h : $(SRCCOMN)\common.h
+
+$(TMPCOMN)\crempoly.h : $(SRCCOMN)\crempoly.h
+
+$(TMPCOMN)\cunk.h : $(SRCCOMN)\cunk.h
+
+$(TMPCOMN)\dballoc.h : $(SRCCOMN)\dballoc.h
+
+$(TMPCOMN)\dispdbug.h : $(SRCCOMN)\dispdbug.h
+
+$(TMPCOMN)\disphelp.h : $(SRCCOMN)\disphelp.h
+
+$(TMPCOMN)\testhelp.h : $(SRCCOMN)\testhelp.h
+
+$(TMPCOMN)\assert.cpp : $(SRCCOMN)\assert.cpp
+
+$(TMPCOMN)\cdisp.cpp : $(SRCCOMN)\cdisp.cpp
+
+$(TMPCOMN)\crempoly.cpp : $(SRCCOMN)\crempoly.cpp
+
+$(TMPCOMN)\cunk.cpp : $(SRCCOMN)\cunk.cpp
+
+$(TMPCOMN)\dispdbug.cpp : $(SRCCOMN)\dispdbug.cpp
+
+$(TMPCOMN)\dballoc.cpp : $(SRCCOMN)\dballoc.cpp
+
+$(TMPCOMN)\disphelp.cpp : $(SRCCOMN)\disphelp.cpp
+
+$(TMPCOMN)\testhelp.cpp : $(SRCCOMN)\testhelp.cpp
+
+$(TMPCOMN)\util.cpp : $(SRCCOMN)\util.cpp
+
+
+#---------------------------------------------------------------------
+# cdisptst sources
+#---------------------------------------------------------------------
+
+$(TMPCDSP)\clsid.h : $(SRCCDSP)\clsid.h
+
+$(TMPCDSP)\disptest.h : $(SRCCDSP)\disptest.h
+
+$(TMPCDSP)\macmain.h : $(SRCCDSP)\macmain.h
+
+$(TMPCDSP)\oleguids.h : $(SRCCDSP)\oleguids.h
+
+$(TMPCDSP)\resource.h : $(SRCCDSP)\resource.h
+
+$(TMPCDSP)\tstsuite.h : $(SRCCDSP)\tstsuite.h
+
+$(TMPCDSP)\guid.c : $(SRCCDSP)\guid.c
+
+$(TMPCDSP)\oleguids.c : $(SRCCDSP)\oleguids.c
+
+$(TMPCDSP)\cbind.cpp : $(SRCCDSP)\cbind.cpp
+
+$(TMPCDSP)\cbstr.cpp : $(SRCCDSP)\cbstr.cpp
+
+$(TMPCDSP)\ccollect.cpp : $(SRCCDSP)\ccollect.cpp
+
+$(TMPCDSP)\cdatecnv.cpp : $(SRCCDSP)\cdatecnv.cpp
+
+$(TMPCDSP)\cinvsary.cpp : $(SRCCDSP)\cinvsary.cpp
+
+$(TMPCDSP)\cinvval.cpp : $(SRCCDSP)\cinvval.cpp
+
+$(TMPCDSP)\cinvref.cpp : $(SRCCDSP)\cinvref.cpp
+
+$(TMPCDSP)\cinvex.cpp : $(SRCCDSP)\cinvex.cpp
+
+$(TMPCDSP)\cnls.cpp : $(SRCCDSP)\cnls.cpp
+
+$(TMPCDSP)\csarray.cpp : $(SRCCDSP)\csarray.cpp
+
+$(TMPCDSP)\ctime.cpp : $(SRCCDSP)\ctime.cpp
+
+$(TMPCDSP)\cvariant.cpp : $(SRCCDSP)\cvariant.cpp
+
+$(TMPCDSP)\macmain.cpp : $(SRCCDSP)\macmain.cpp
+
+$(TMPCDSP)\misc.cpp : $(SRCCDSP)\misc.cpp
+
+$(TMPCDSP)\suite.cpp : $(SRCCDSP)\suite.cpp
+
+$(TMPCDSP)\cdisptst.r : $(SRCCDSP)\cdisptst.r
+ $(CP2MAC) $(SRCCDSP)\cdisptst.r $(MACCDSP)$(@F)
+ echo $(@F) > $@
+
+$(TMPCDSP)\makefile.tmp : $(SRCCDSP)\makefile.mpw
+ mungemak $(SRCCDSP)\makefile.mpw > $(TMPCDSP)\makefile.tmp
+ $(CP2MAC) $(TMPCDSP)\makefile.tmp $(MACCDSP)makefile
+
diff --git a/private/oleauto/tests/disptest/suite.cpp b/private/oleauto/tests/disptest/suite.cpp
new file mode 100644
index 000000000..d38eaedbb
--- /dev/null
+++ b/private/oleauto/tests/disptest/suite.cpp
@@ -0,0 +1,590 @@
+/***
+*suite.cpp
+*
+* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* This module contains the test suite drivers.
+*
+*Revision History:
+*
+* [00] 29-Apr-93 bradlo: Added header.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+
+#include "disptest.h"
+#include "tstsuite.h"
+
+ASSERTDATA
+
+
+#if OE_MAC
+typedef void* HWND;
+#endif
+
+#if !OE_MAC
+extern HINSTANCE g_hinst;
+#endif
+
+struct TEST_INFO {
+ HRESULT hresult;
+ HWND hwnd;
+ BSTR bstr;
+
+ ITestSuite FAR * ptst;
+
+ TEST_INFO () {
+ hresult = NOERROR;
+ hwnd = NULL;
+ bstr = NULL;
+ ptst = NULL;
+ }
+};
+
+extern int g_fLog;
+
+STDAPI_(void)
+PassFail(HRESULT hresult, OLECHAR FAR* szCaption, HWND hwnd)
+{
+ SCODE sc;
+ TCHAR buf[80];
+
+ sc = GetScode(hresult);
+ // E_ABORT indicates the test was aborted by the user, so we do nothing.
+ if(sc == E_ABORT)
+ return;
+ SPRINTF(buf,
+ HC_MPW ? TSTR("%s : %s") : TSTR("%Fs : %Fs"),
+ (TCHAR FAR*)(FAILED(sc) ? TSTR("FAIL") : TSTR("PASS")),
+ DbSzOfScode(sc));
+
+ DbPrintf(
+ HC_MPW ? "DT : %s ==> %s\n" : "DT : %Fs ==> %Fs\n",
+ szCaption == NULL ? "" : (char FAR*) STRING(szCaption), (char FAR*)buf);
+
+#if OE_MAC
+ UNUSED(hwnd);
+#else
+ MessageBox(hwnd, buf, STRING(szCaption), MB_OK);
+#endif
+}
+
+#if !OE_MAC /* { */
+
+int g_nPercent = 0;
+BOOL g_fCancel = FALSE;
+
+void PASCAL
+PaintTheGuage(HWND hwndDlg)
+{
+ RECT rc;
+ HDC hdc;
+ int width;
+ HBRUSH hbrush;
+ HWND hwndGuage;
+
+ hwndGuage = GetDlgItem(hwndDlg, IDD_SUITE_GUAGE);
+
+ hdc = GetDC(hwndGuage);
+
+ GetClientRect(hwndGuage, &rc);
+
+ // draw the border
+ //
+ hbrush = CreateSolidBrush(RGB(255, 255, 255));
+ hbrush = (HBRUSH)SelectObject(hdc, hbrush);
+ Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
+ DeleteObject(SelectObject(hdc, hbrush));
+
+ // leave room for the border
+ //
+ rc.left++, rc.top++, rc.right--, rc.bottom--;
+
+ // compute the ammount of the guage rect to fill
+ //
+ width = ((rc.right - rc.left) * g_nPercent) / 100;
+ rc.right = rc.left + width;
+
+ // fill the guage
+ //
+ hbrush = CreateSolidBrush(RGB(0, 0, 255)); // Blue brush
+ FillRect(hdc, &rc, hbrush);
+ DeleteObject(hbrush);
+
+ ReleaseDC(hwndGuage, hdc);
+}
+
+
+extern "C" BOOL CALLBACK EXPORT
+SuiteDlgProc(HWND hwndDlg, unsigned message, WORD wparam, LONG lparam)
+{
+ switch(message){
+ case WM_INITDIALOG:
+ return TRUE;
+
+ case WM_COMMAND:
+ if(wparam == IDCANCEL){
+ g_fCancel = TRUE;
+ return TRUE;
+ }
+ break;
+
+ case WM_PAINT:
+ PaintTheGuage(hwndDlg);
+ break;
+ }
+
+ return FALSE;
+}
+
+
+void PASCAL
+ProgressYield(HWND hwnd)
+{
+ MSG msg;
+
+ // empty the message loop...
+ while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
+ if(!hwnd || !IsDialogMessage(hwnd, &msg)){
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+#endif /* } */
+
+
+// Open a logfile for the given suite, in the directory that the
+// test app lives.
+//
+
+#if defined(WIN32)
+ #define GETMODULEFILENAME GetModuleFileNameA
+#else
+ #define GETMODULEFILENAME GetModuleFileName
+#endif
+
+HFILE
+OpenLogFile(ITestSuite FAR* ptst)
+{
+ BSTR bstr;
+ HFILE hfile;
+ char szModuleName[512], FAR* p, FAR* q;
+ char buf[256];
+
+ bstr = NULL;
+ hfile = HFILE_ERROR;
+
+#if OE_WIN
+ int cb;
+ if((cb = GETMODULEFILENAME(g_hinst, szModuleName,sizeof(szModuleName)))==0)
+ goto LError0; /* couldn't get the module name */
+#endif
+
+ // get the logfile name for this suite
+ if(ptst->GetNameOfLogfile(&bstr) != NOERROR)
+ goto LError0;
+
+#if OE_WIN
+ // backup to the first path separator (ie, backup over the .exe name)
+ for(p = &szModuleName[cb]; p > szModuleName; --p){
+ if(*p == '\\'){
+ ++p;
+ break;
+ }
+ }
+#else
+ p = szModuleName;
+#endif
+
+ // tack the logfile name onto the end of the path
+#if OE_WIN32
+ for(q = ConvertStrWtoA(bstr, buf); *q != '\0';)
+#else
+ for(q = bstr; *q != '\0';)
+#endif
+ *p++ = *q++;
+ *p = '\0';
+
+#if OE_WIN
+ OFSTRUCT of;
+ hfile = OpenFile(szModuleName, &of, OF_CREATE);
+#else
+ hfile = fopen(szModuleName, "w");
+#endif
+
+LError0:;
+ SysFreeString(bstr);
+
+ return hfile;
+}
+
+/***
+*HRESULT DispTestDoSuite(ITestSuite*, HWND)
+*Purpose:
+* Execute all tests in the given suite.
+*
+*Entry:
+* ptst = the ITestSuite* to execute tests from
+* hwnd = HWND of the parent window
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+HRESULT
+DispTestDoSuite(ITestSuite FAR* ptst, HWND hwnd)
+{
+ BSTR bstr;
+ HRESULT hresult;
+ unsigned int i, cTests;
+
+#if !OE_MAC
+ TCHAR buf[32];
+ HWND hwndSuiteDlg;
+
+#if OE_WIN16
+static DLGPROC pfnSuiteDlgProc;
+#endif // OE_WIN16
+#endif
+
+#if OE_MAC
+ UNUSED(hwnd);
+#endif
+
+#if !OE_MAC
+ g_fCancel = FALSE;
+#endif
+
+ if(g_fLog){
+ ASSERT(Pappdata()->m_hfLogfile == HFILE_ERROR);
+ if((Pappdata()->m_hfLogfile = OpenLogFile(ptst)) == HFILE_ERROR){
+ hresult = RESULT(E_FAIL);
+ goto LError0;
+ }
+ }
+
+ IfFailGo(ptst->GetNameOfSuite(&bstr), LError0);
+ IfFailGo(ptst->GetTestCount(&cTests), LError0);
+ PrintSuiteHeader(STRING(bstr));
+
+#if OE_WIN
+
+#if OE_WIN16
+ pfnSuiteDlgProc =
+ (DLGPROC)MakeProcInstance((DLGPROC)SuiteDlgProc, g_hinst);
+
+ hwndSuiteDlg = CreateDialog(g_hinst, TSTR("SuiteDlg"), hwnd, pfnSuiteDlgProc);
+
+#else // !OE_WIN16
+ hwndSuiteDlg = CreateDialog(g_hinst, TSTR("SuiteDlg"), hwnd, (DLGPROC)SuiteDlgProc);
+#endif // !OE_WIN16
+
+ SetDlgItemText(hwndSuiteDlg, IDD_SUITE_NAME, STRING(bstr));
+ ShowWindow(hwndSuiteDlg, SW_SHOW);
+#endif
+
+ SysFreeString(bstr);
+
+ for(i = 0; i < cTests; ++i){
+ IfFailGo(ptst->GetNameOfTest(i, &bstr), LError0);
+ PrintTestHeader(STRING(bstr));
+#if OE_WIN
+ SetDlgItemText(hwndSuiteDlg, IDD_SUITE_TESTNAME, STRING(bstr));
+#endif
+ SysFreeString(bstr);
+
+#if OE_WIN
+ g_nPercent = (i*100) / cTests;
+ SPRINTF(buf, TSTR("%d%%"), g_nPercent);
+ SetDlgItemText(hwndSuiteDlg, IDD_SUITE_PERCENT, buf);
+ PaintTheGuage(hwndSuiteDlg);
+#endif
+
+ // ** Execute the Test **
+ //
+ IfFailGo(ptst->DoTest(i), LError0);
+
+#if OE_WIN
+ ProgressYield(hwndSuiteDlg);
+ if(g_fCancel == TRUE){
+ hresult = RESULT(E_ABORT);
+ goto LError0;
+ }
+#endif
+ }
+
+#if OE_WIN
+ g_nPercent = 100;
+ PaintTheGuage(hwndSuiteDlg);
+#endif
+
+ hresult = NOERROR;
+
+LError0:;
+#if OE_WIN
+ if(hwndSuiteDlg)
+ DestroyWindow(hwndSuiteDlg);
+
+#if OE_WIN16
+ FreeProcInstance(pfnSuiteDlgProc);
+#endif // OE_WIN16
+#endif
+
+ if(Pappdata()->m_hfLogfile != HFILE_ERROR){
+#if OE_MAC
+ fclose(Pappdata()->m_hfLogfile);
+#else
+ _lclose(Pappdata()->m_hfLogfile);
+#endif
+ Pappdata()->m_hfLogfile = HFILE_ERROR;
+ }
+
+ return hresult;
+}
+
+struct {
+ int idm;
+ ITestSuite FAR* (*create)(void);
+} g_rgTestSuite[] = {
+#if OE_MAC
+ { IDM_SUITE_BSTR, CBstrSuite::Create }
+ , { IDM_SUITE_TIME, CTimeSuite::Create }
+ , { IDM_SUITE_DATECNV, CDateCoersionSuite::Create }
+ , { IDM_SUITE_VARIANT, CVariantSuite::Create }
+ , { IDM_SUITE_SAFEARRAY, CSafeArraySuite::Create }
+ , { IDM_SUITE_NLS, CNlsSuite::Create }
+// # if HC_MPW
+ , { IDM_SUITE_BIND, CBindSuite::Create }
+ , { IDM_SUITE_INVOKE_BYVAL, CInvokeByValSuite::Create }
+ , { IDM_SUITE_INVOKE_BYREF, CInvokeByRefSuite::Create }
+ , { IDM_SUITE_INVOKE_SAFEARRAY, CInvokeSafeArraySuite::Create }
+ , { IDM_SUITE_INVOKE_EXCEPINFO, CInvokeExcepinfoSuite::Create }
+ , { IDM_SUITE_COLLECTION, CCollectionSuite::Create }
+// # endif
+#else
+ { IDM_SUITE_BSTR, CBstrSuite::Create }
+ , { IDM_SUITE_TIME, CTimeSuite::Create }
+ , { IDM_SUITE_DATECNV, CDateCoersionSuite::Create }
+ , { IDM_SUITE_VARIANT, CVariantSuite::Create }
+ , { IDM_SUITE_SAFEARRAY, CSafeArraySuite::Create }
+ , { IDM_SUITE_NLS, CNlsSuite::Create }
+ , { IDM_SUITE_BIND, CBindSuite::Create }
+ , { IDM_SUITE_INVOKE_BYVAL, CInvokeByValSuite::Create }
+ , { IDM_SUITE_INVOKE_BYREF, CInvokeByRefSuite::Create }
+ , { IDM_SUITE_INVOKE_SAFEARRAY, CInvokeSafeArraySuite::Create }
+ , { IDM_SUITE_INVOKE_EXCEPINFO, CInvokeExcepinfoSuite::Create }
+ , { IDM_SUITE_COLLECTION, CCollectionSuite::Create }
+ , { IDM_SUITE_EARLY, CEarlySuite::Create }
+#endif
+};
+
+
+/***
+*PRIVATE ITestSuite *ITestSuiteFromIDM(int)
+*Purpose:
+* Create an ITestSuite* from the given message ID.
+*
+*Entry:
+* idm = the message ID.
+*
+*Exit:
+* return value = ITestSuite*, NULL if unable to create.
+*
+***********************************************************************/
+HRESULT
+ITestSuiteFromIDM(int idm, ITestSuite FAR* FAR* pptst)
+{
+ int ix;
+
+ for(ix = 0; ix < DIM(g_rgTestSuite); ++ix){
+ if(g_rgTestSuite[ix].idm == idm){
+ return((*pptst = g_rgTestSuite[ix].create()) != NULL
+ ? NOERROR : RESULT(E_OUTOFMEMORY));
+ }
+ }
+ return RESULT(E_FAIL); // test suite not found
+}
+
+
+#if OE_WIN32
+
+/***
+*DWORD ThreadDoSuite
+*Purpose:
+* Run a test inside it's own thread.
+*
+*Entry:
+* Pointer to a TEST_INFO structure.
+*
+*Exit:
+* returns 0.
+*
+***********************************************************************/
+DWORD ThreadDoSuite(LPDWORD lpdwParam)
+{
+ TEST_INFO FAR* ptinfo = (TEST_INFO FAR *)lpdwParam;
+ HRESULT hresult;
+
+ hresult = OleInitialize(NULL);
+ ASSERT(SUCCEEDED(hresult));
+
+ if (InitAppData()) {
+ ptinfo->hresult = DispTestDoSuite(ptinfo->ptst, NULL);
+ ReleaseAppData();
+ }
+
+ OleUninitialize();
+
+ return 0;
+}
+#endif // OE_WIN32
+
+
+/***
+*HRESULT DispTestAll(HWND)
+*Purpose:
+* Execute All IDispatch tests in all suites.
+*
+*Entry:
+* hwnd = window handle
+* fShowDialog = TRUE if we should display a dialog on a failure.
+* fMultiThread = TRUE if we should multithread the tests.
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDAPI
+DispTestAll(HWND hwnd, int fShowDialog, int fMultiThread)
+{
+ int i;
+ HRESULT hresult = NOERROR;
+
+ TEST_INFO rgtinfo[DIM(g_rgTestSuite)];
+
+#if OE_WIN32
+ HANDLE rghThread[DIM(g_rgTestSuite)];
+ DWORD rgThreadId[DIM(g_rgTestSuite)];
+
+ HRESULT hRet;
+#endif // OE_WIN32
+
+ // Set up all of the tests.
+ for(i = 0; i < DIM(g_rgTestSuite); ++i) {
+ rgtinfo[i].hwnd = hwnd;
+ rgtinfo[i].ptst = g_rgTestSuite[i].create();
+ if(rgtinfo[i].ptst == NULL) {
+ hresult = RESULT(E_OUTOFMEMORY);
+ goto LError0;
+ }
+
+ IfFailGo(rgtinfo[i].ptst->GetNameOfSuite(&rgtinfo[i].bstr), LError0);
+ }
+
+ // Run the suites.
+ for(i = 0; i < DIM(g_rgTestSuite); ++i) {
+#if OE_WIN32
+ if (fMultiThread) {
+ rghThread[i] = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)ThreadDoSuite,
+ &rgtinfo[i],
+ 0,
+ &rgThreadId[i]);
+
+ if (rghThread[i] == NULL) {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+ }
+ else
+#endif // OE_WIN32
+ {
+ rgtinfo[i].hresult = DispTestDoSuite(rgtinfo[i].ptst, hwnd);
+
+ // E_ABORT means the test was aborted by the user.
+ //
+ if(GetScode(rgtinfo[i].hresult) == E_ABORT) {
+ hresult = ResultFromScode(E_ABORT);
+ goto LError0;
+ }
+ }
+ }
+
+#if OE_WIN32
+ // Wait for all of the threads to finish.
+ if (fMultiThread) {
+ hRet = WaitForMultipleObjects(DIM(g_rgTestSuite),
+ rghThread,
+ TRUE,
+ INFINITE);
+
+ ASSERT(SUCCEEDED(hRet));
+ }
+#endif // OE_WIN32
+
+ // Check the results.
+ for (i = 0; i < DIM(g_rgTestSuite) && fShowDialog; ++i) {
+ if (FAILED(rgtinfo[i].hresult)) {
+ PassFail(rgtinfo[i].hresult, rgtinfo[i].bstr, hwnd);
+ hresult = ResultFromScode(S_FALSE);
+ }
+ }
+
+LError0:;
+ for (i = 0; i < DIM(g_rgTestSuite) && rgtinfo[i].ptst; ++i) {
+ rgtinfo[i].ptst->Release();
+ SysFreeString(rgtinfo[i].bstr);
+ }
+
+ return hresult;
+}
+
+
+/***
+*PRIVATE HRESULT DispTestOne(int)
+*Purpose:
+* Execute the test suite associated with the given message ID.
+*
+*Entry:
+* idm = the message id
+*
+*Exit:
+* return value = HRESULT
+*
+***********************************************************************/
+STDAPI
+DispTestOne(HWND hwnd, int idm)
+{
+ BSTR bstr;
+ HRESULT hresult;
+ ITestSuite FAR* ptst;
+
+ ptst = NULL;
+ bstr = NULL;
+
+ IfFailGo(ITestSuiteFromIDM(idm, &ptst), LError0);
+
+ IfFailGo(ptst->GetNameOfSuite(&bstr), LError0);
+
+ hresult = DispTestDoSuite(ptst, hwnd);
+
+LError0:;
+ PassFail(hresult, bstr, hwnd);
+
+ if(bstr != NULL)
+ SysFreeString(bstr);
+
+ if(ptst != NULL)
+ ptst->Release();
+
+ return hresult;
+}
+
diff --git a/private/oleauto/tests/disptest/timer.c b/private/oleauto/tests/disptest/timer.c
new file mode 100644
index 000000000..1b28ca802
--- /dev/null
+++ b/private/oleauto/tests/disptest/timer.c
@@ -0,0 +1,29 @@
+/***
+*timer.c - Timing functions.
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+*
+*Revision History:
+*
+* [00] 02-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#include <stdio.h>
+#include <sys/timeb.h>
+
+double
+GetTime()
+{
+ double secs;
+ struct _timeb t;
+
+ _ftime(&t);
+ secs = t.time + (t.millitm/1000.0);
+ return secs;
+}
diff --git a/private/oleauto/tests/disptest/tstsuite.h b/private/oleauto/tests/disptest/tstsuite.h
new file mode 100644
index 000000000..5fe433bd9
--- /dev/null
+++ b/private/oleauto/tests/disptest/tstsuite.h
@@ -0,0 +1,119 @@
+/***
+*tstsuite.h
+*
+* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
+* Information Contained Herein Is Proprietary and Confidential.
+*
+*Purpose:
+* Definition of the ITestSuite interface.
+*
+*Revision History:
+*
+* [00] 30-Oct-92 bradlo: Created.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+DEFINE_OLEGUID(IID_ITestSuite, 0x00020440, 0, 0);
+
+DECLARE_INTERFACE_(ITestSuite, IUnknown)
+{
+
+ // IUnknown methods
+ //
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv) = 0;
+ STDMETHOD_(unsigned long, AddRef)(void) = 0;
+ STDMETHOD_(unsigned long, Release)(void) = 0;
+
+ // Introduced methods
+ //
+ STDMETHOD(GetNameOfSuite)(BSTR FAR* pbstr) = 0;
+ STDMETHOD(GetNameOfLogfile)(BSTR FAR* pbstr) = 0;
+ STDMETHOD(GetTestCount)(unsigned int FAR* pcTests) = 0;
+ STDMETHOD(GetNameOfTest)(unsigned int iTest, BSTR FAR* pbstr) = 0;
+ STDMETHOD(DoTest)(unsigned int iTest) = 0;
+};
+
+
+// Standard CTestSuite definition used by all TestSuite objects.
+//
+#define DEFINE_SUITE(CLASS) \
+ class CLASS : public ITestSuite { \
+ public: \
+ static ITestSuite FAR* Create(void); \
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv); \
+ STDMETHOD_(unsigned long, AddRef)(void); \
+ STDMETHOD_(unsigned long, Release)(void); \
+ STDMETHOD(GetNameOfSuite)(BSTR FAR* pbstr); \
+ STDMETHOD(GetNameOfLogfile)(BSTR FAR* pbstr); \
+ STDMETHOD(GetTestCount)(unsigned int FAR* pcTests);\
+ STDMETHOD(GetNameOfTest)(unsigned int iTest, BSTR FAR* pbstr); \
+ STDMETHOD(DoTest)(unsigned int iTest); \
+ private: \
+ CLASS(); \
+ ~CLASS(); \
+ unsigned long m_refs; \
+ }
+
+// Default creation an destruction routines
+// used by all test suite objects.
+//
+#define SUITE_CONSTRUCTION_IMPL(CLASS) \
+ CLASS::CLASS() \
+ { m_refs = 0; } \
+ CLASS::~CLASS() \
+ { } \
+ ITestSuite FAR* CLASS::Create() \
+ { \
+ CLASS FAR* pclass; \
+ pclass = new FAR CLASS(); \
+ if(pclass == NULL) \
+ return NULL; \
+ pclass->AddRef(); \
+ return pclass; \
+ }
+
+
+// Default implementation of IUnknown used by
+// all test suite objects.
+//
+#define SUITE_IUNKNOWN_IMPL(CLASS) \
+ STDMETHODIMP CLASS::QueryInterface( \
+ REFIID riid, void FAR* FAR* ppv) \
+ { \
+ if(!IsEqualIID(riid, IID_IUnknown)) \
+ if(!IsEqualIID(riid, IID_ITestSuite)) \
+ return RESULT(E_NOINTERFACE); \
+ *ppv = this; \
+ ++m_refs; \
+ return NOERROR; \
+ } \
+ STDMETHODIMP_(unsigned long) CLASS::AddRef() \
+ { return ++m_refs; } \
+ STDMETHODIMP_(unsigned long) CLASS::Release() \
+ { \
+ if(--m_refs == 0){ \
+ delete this; \
+ return 0; \
+ } \
+ return m_refs; \
+ }
+
+
+DEFINE_SUITE(CBstrSuite); // cbstr.cpp
+DEFINE_SUITE(CTimeSuite); // ctime.cpp
+DEFINE_SUITE(CDateCoersionSuite); // cdatecnv.cpp
+DEFINE_SUITE(CVariantSuite); // cvariant.cpp
+DEFINE_SUITE(CSafeArraySuite); // csarray.cpp
+DEFINE_SUITE(CNlsSuite); // cnls.cpp
+DEFINE_SUITE(CBindSuite); // cbind.cpp
+DEFINE_SUITE(CInvokeByValSuite); // cinvval.cpp
+DEFINE_SUITE(CInvokeByRefSuite); // cinvref.cpp
+DEFINE_SUITE(CInvokeMultipleSuite); // cinvmult.cpp
+DEFINE_SUITE(CInvokeSafeArraySuite); // cinvsary.cpp
+DEFINE_SUITE(CInvokeExcepinfoSuite); // cinvex.cpp
+DEFINE_SUITE(CCollectionSuite); // ccollect.cpp
+#if VBA2
+DEFINE_SUITE(CEarlySuite); // cearly.cpp
+#endif