- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
214 lines
5.1 KiB
C++
214 lines
5.1 KiB
C++
//
|
|
//----------------------------------------------------------------------------
|
|
// ObjectComponents
|
|
// (C) Copyright 1994 by Borland International, All Rights Reserved
|
|
//
|
|
// OLE Automation Client Implementation
|
|
//----------------------------------------------------------------------------
|
|
#include <ocf/ocfpch.h>
|
|
#include <ocf/autodefs.h>
|
|
|
|
TAutoProxyArgs::~TAutoProxyArgs()
|
|
{
|
|
while (Count >= 0)
|
|
::VariantClear((VARIANT far*)((TAutoVal*)(this+1)+Count--));
|
|
}
|
|
|
|
void TAutoProxy::Bind(const char far* progid)
|
|
{
|
|
PRECONDITION(progid);
|
|
|
|
GUID guid;
|
|
TXOle::Check(CLSIDFromProgID(OleStr(progid), &guid), progid);
|
|
Bind(guid);
|
|
}
|
|
|
|
void TAutoProxy::Bind(const GUID& guid)
|
|
{
|
|
IUnknown* unk;
|
|
HRESULT stat = ::CoCreateInstance(guid,0,CLSCTX_SERVER,IID_IUnknown,(void FAR*FAR*)&unk);
|
|
if (stat != HR_NOERROR) {
|
|
char guidBuf[60];
|
|
TClassId copy(guid);
|
|
lstrcpy (guidBuf, copy);
|
|
TXOle::Check(stat, guidBuf);
|
|
}
|
|
Bind(unk);
|
|
}
|
|
|
|
void TAutoProxy::Bind(IUnknown* unk)
|
|
{
|
|
if (!unk)
|
|
return;
|
|
IDispatch* dsp;
|
|
HRESULT stat = unk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&dsp);
|
|
unk->Release();
|
|
TXOle::Check(stat, "IUnknown");
|
|
Bind(dsp);
|
|
}
|
|
|
|
void TAutoProxy::Bind(IDispatch* dsp)
|
|
{
|
|
Unbind();
|
|
That = dsp;
|
|
}
|
|
|
|
void TAutoProxy::Bind(IUnknown& unk)
|
|
{
|
|
IDispatch* dsp;
|
|
TXOle::Check(unk.QueryInterface(IID_IDispatch, (void FAR* FAR*)&dsp), "IUnknown");
|
|
Bind(dsp);
|
|
}
|
|
|
|
void TAutoProxy::Bind(IDispatch& obj)
|
|
{
|
|
Unbind();
|
|
obj.AddRef();
|
|
That = &obj;
|
|
}
|
|
|
|
void TAutoProxy::Bind(TAutoVal& val)
|
|
{
|
|
if (val.GetDataType() == atVoid)
|
|
That = 0;
|
|
else
|
|
Bind((IDispatch&)val); // throws exception if fails
|
|
}
|
|
|
|
void TAutoProxy::MustBeBound()
|
|
{
|
|
if (!That)
|
|
throw TXAuto(TXAuto::xNotIDispatch);
|
|
}
|
|
|
|
long TAutoProxy::Lookup(const char far* name)
|
|
{
|
|
if (!name)
|
|
name = "(null)"; // force controlled failure
|
|
long id;
|
|
|
|
MustBeBound();
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
TString tsname(name);
|
|
wchar_t* wname = tsname;
|
|
TXOle::Check(That->GetIDsOfNames(IID_NULL, &wname, 1, Lang, &id), name);
|
|
#else
|
|
TXOle::Check(That->GetIDsOfNames(IID_NULL, &const_cast<char far*>(name), 1, Lang, &id), name);
|
|
#endif
|
|
return id;
|
|
}
|
|
|
|
void TAutoProxy::Lookup(const char far* names, long* ids, unsigned count)
|
|
{
|
|
MustBeBound();
|
|
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
const char far* pc = names;
|
|
for (int i = 0; i < count; i++) {
|
|
pc += strlen(pc) + 1;
|
|
}
|
|
wchar_t* wnames = TUString::ConvertAtoW(names, pc-names-1);
|
|
wchar_t** args = new wchar_t far*[count];
|
|
wchar_t* pw = wnames;
|
|
for (i = 0; i < count; i++) {
|
|
args[i] = pw;
|
|
pw += lstrlenW(pw) + 1;
|
|
}
|
|
HRESULT stat = That->GetIDsOfNames(IID_NULL, args, count, Lang, ids);
|
|
delete wnames;
|
|
#else
|
|
char far** args = new char far*[count];
|
|
const char far* pc = names;
|
|
for (int i = 0; i < count; i++) {
|
|
args[i] = (char far*)pc; // for non-unicode, names separated by null bytes
|
|
pc += strlen(pc) + 1;
|
|
}
|
|
HRESULT stat = That->GetIDsOfNames(IID_NULL, args, count, Lang, ids);
|
|
#endif
|
|
delete [] args;
|
|
if (stat) {
|
|
int bad = 0;
|
|
if ((stat = HR_DISP_UNKNOWNNAME) != HR_NOERROR)
|
|
while (bad < count && ids[bad] != DISPID_UNKNOWN) {
|
|
bad++;
|
|
names += (strlen(names) + 1);
|
|
}
|
|
TXOle::Check(stat, names);
|
|
}
|
|
}
|
|
|
|
TAutoVal&
|
|
TAutoProxy::Invoke(uint16 attr, TAutoProxyArgs& args, long* ids, unsigned named)
|
|
{
|
|
EXCEPINFO errinfo;
|
|
unsigned int errarg;
|
|
VARIANT far* retval = 0;
|
|
|
|
MustBeBound();
|
|
if (!(attr & (acPropSet | acVoidRet))) {
|
|
retval = args;
|
|
::VariantInit(retval);
|
|
}
|
|
DISPID funcId = ids[0];
|
|
DISPPARAMS params;
|
|
params.cArgs = args;
|
|
params.cNamedArgs = named;
|
|
params.rgvarg = args;
|
|
params.rgdispidNamedArgs = ids;
|
|
if (attr & acPropSet) {
|
|
ids[0] = DISPID_PROPERTYPUT;
|
|
params.cNamedArgs++;
|
|
params.cArgs++;
|
|
} else {
|
|
params.rgdispidNamedArgs++;
|
|
params.rgvarg++;
|
|
}
|
|
HRESULT stat = That->Invoke(funcId, IID_NULL, Lang,
|
|
uint16(attr & (acMethod | acPropSet | acPropGet)),
|
|
¶ms, retval, &errinfo, &errarg);
|
|
ids[0] = funcId; // restore function id incase PropSet
|
|
if (stat != HR_NOERROR) {
|
|
char buf[50];
|
|
wsprintf(buf, "Invoke Id = %ld", funcId);
|
|
TXOle::Check(stat, buf);
|
|
}
|
|
return args;
|
|
}
|
|
|
|
TAutoEnumeratorBase::TAutoEnumeratorBase(const TAutoEnumeratorBase& copy)
|
|
{
|
|
Current.Copy(copy.Current);
|
|
Iterator = copy.Iterator;
|
|
if (Iterator)
|
|
TXOle::Check(Iterator->Clone(&Iterator));
|
|
}
|
|
|
|
void TAutoEnumeratorBase::operator =(const TAutoEnumeratorBase& copy)
|
|
{
|
|
Current.Copy(copy.Current);
|
|
Unbind();
|
|
Iterator = copy.Iterator;
|
|
if (Iterator)
|
|
TXOle::Check(Iterator->Clone(&Iterator));
|
|
}
|
|
|
|
void TAutoEnumeratorBase::Bind(TAutoVal& val)
|
|
{
|
|
Unbind();
|
|
IUnknown& unk = val;
|
|
TXOle::Check(unk.QueryInterface(IID_IEnumVARIANT, (void far* far*) &Iterator),
|
|
"_NewEnum");
|
|
}
|
|
|
|
bool TAutoEnumeratorBase::Step()
|
|
{
|
|
Clear();
|
|
if (!Iterator)
|
|
TXOle::Check(HR_NOINTERFACE, "_NewEnum");
|
|
else if (HRIsOK(Iterator->Next(1,(VARIANT far*)&Current,0)))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|