- 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>
337 lines
8.0 KiB
C++
337 lines
8.0 KiB
C++
//
|
|
//**************************************************************************
|
|
//
|
|
// BOleFact.cpp -- Implements the server-side helper for allowing OLE2 to
|
|
// create objects made available by Bolero server apps.
|
|
//
|
|
// Copyright (c) 1993,94 by Borland International, Inc. All rights reserved
|
|
//
|
|
//**************************************************************************
|
|
|
|
#include "BOleFact.h"
|
|
#include "BOleSvc.h"
|
|
#include "BOleIPS.h"
|
|
#include "BOleCMan.h"
|
|
|
|
|
|
//
|
|
// DllGetClassObject
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
|
|
{
|
|
HRESULT hRes = ResultFromScode(E_OUTOFMEMORY);
|
|
return hRes;
|
|
}
|
|
|
|
|
|
STDAPI DllCanUnloadNow()
|
|
{
|
|
return ResultFromScode( S_OK );
|
|
}
|
|
|
|
|
|
BOleFact::BOleFact(BOleClassManager * pFact, IBUnknownMain *pOuter):
|
|
RefCnt (1),
|
|
pObjCM(NULL),
|
|
hReg (0L),
|
|
regId (0),
|
|
dwRegisterActiveObject (0),
|
|
id (CLSID_NULL),
|
|
BOleComponent(pFact, (IBUnknownMain *) this),
|
|
pIPEFact (NULL)
|
|
{
|
|
}
|
|
|
|
BOleFact::~BOleFact()
|
|
{
|
|
if (pIPEFact) {
|
|
pIPEFact->Release();
|
|
pIPEFact = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::QueryInterfaceMain(REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
HRESULT hr = ResultFromScode(E_NOINTERFACE);
|
|
*ppv = NULL;
|
|
|
|
// interfaces
|
|
|
|
SUCCEEDED(hr = IBClass_QueryInterface(this, iid, ppv))
|
|
|
|
// base classes
|
|
|
|
|| SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(iid, ppv))
|
|
|
|
// helpers
|
|
;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::Init (BOOL fInProc, LPCOLESTR szProgId, IBClassMgr *pCM, BCID rid)
|
|
{
|
|
pObjCM = pCM;
|
|
regId = rid;
|
|
|
|
// If the user's object is capable of being instantiated in its own
|
|
// container, create a special BOleInProcFactory
|
|
//
|
|
if (fInProc) {
|
|
pIPEFact = new BOleInProcFactory (pFactory, this, id);
|
|
if (!pIPEFact)
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
}
|
|
|
|
return CLSIDFromProgID(szProgId, &id);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::Register (BOOL fSingleUse)
|
|
{
|
|
HRESULT hErr;
|
|
|
|
// register the class factory for this id
|
|
//
|
|
if (!SUCCEEDED(hErr = CoRegisterClassObject(
|
|
id,
|
|
(IClassFactory *)this,
|
|
CLSCTX_LOCAL_SERVER,
|
|
fSingleUse ? REGCLS_SINGLEUSE : REGCLS_MULTI_SEPARATE,
|
|
&hReg))) {
|
|
OLEHRES("Failed Registering", hErr);
|
|
}
|
|
|
|
// Register the embedding helper factory if we embed in ourselves
|
|
if (pIPEFact) {
|
|
if (!SUCCEEDED(hErr = pIPEFact->Register (fSingleUse)))
|
|
return hErr;
|
|
}
|
|
|
|
// The online dox for CoLockObjectExternal say we should do this here
|
|
//
|
|
if (SUCCEEDED(hErr)) {
|
|
LPCLASSFACTORY pWorkAround = this;
|
|
CoLockObjectExternal (pWorkAround, TRUE, TRUE);
|
|
}
|
|
|
|
// if the class manager supports automation let's register it as "Active"
|
|
//
|
|
IDispatch *pDispatch;
|
|
if (SUCCEEDED(pObjCM->QueryInterface(IID_IDispatch, &(LPVOID)pDispatch))) {
|
|
RegisterActiveObject (pDispatch, id, NULL, &dwRegisterActiveObject);
|
|
pDispatch->Release();
|
|
}
|
|
return hErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::Revoke ()
|
|
{
|
|
if (hReg) {
|
|
LPCLASSFACTORY pWorkAround = this;
|
|
CoLockObjectExternal (pWorkAround, FALSE, TRUE);
|
|
CoRevokeClassObject( hReg);
|
|
hReg = 0;
|
|
}
|
|
|
|
if (dwRegisterActiveObject) {
|
|
RevokeActiveObject (dwRegisterActiveObject, NULL);
|
|
dwRegisterActiveObject = 0;
|
|
}
|
|
|
|
if (pIPEFact) {
|
|
pIPEFact->Revoke ();
|
|
pIPEFact->Release ();
|
|
pIPEFact = NULL;
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::GetClassID (LPCLSID pClass)
|
|
{
|
|
*pClass = id;
|
|
return NOERROR;
|
|
}
|
|
|
|
BOOL _IFUNC BOleFact::IsA (REFCLSID cid)
|
|
{
|
|
return IsEqualCLSID(cid, id);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleFact::CreateInstance(IUnknown FAR* pUnk, REFIID iid, LPVOID FAR* ppv)
|
|
{
|
|
HRESULT hr = ResultFromScode(E_FAIL);
|
|
*ppv = 0L;
|
|
|
|
PIUnknown pObj;
|
|
IBClassMgr * pICM;
|
|
|
|
if (SUCCEEDED(pObjCM->QueryInterface(IID_IBClassMgr, &(LPVOID)pICM))) {
|
|
if (SUCCEEDED(pICM->ComponentCreate(&pObj, pUnk, regId))) {
|
|
if (pUnk && iid == IID_IUnknown) {
|
|
hr = NOERROR;
|
|
*ppv = pObj; // always give out main IUnknown
|
|
}
|
|
else {
|
|
hr = pObj->QueryInterface(iid, ppv);
|
|
pObj->Release(); // QI bumps
|
|
}
|
|
}
|
|
pICM->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT _IFUNC BOleFact::LockServer( BOOL fLock )
|
|
{
|
|
LPCLASSFACTORY pICF = this;
|
|
CoLockObjectExternal(pICF, fLock, TRUE);
|
|
pFactory->ServerCount( fLock ? 1L : -1L);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
// Used by DllGetClassObject to return the interface to the factory which
|
|
// creates the default handler which will create the in-proc server object.
|
|
//
|
|
HRESULT _IFUNC BOleFact::GetEmbeddingHelperFactory (LPUNKNOWN *ppF)
|
|
{
|
|
if (pIPEFact) {
|
|
*ppF = pIPEFact;
|
|
(*ppF)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
else {
|
|
*ppF = NULL;
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
}
|
|
|
|
// When Bolero container-side dialog boxes need to know whether to put the
|
|
// CLSID for our own factories in the dialog box, this is how they find out
|
|
//
|
|
BOOL _IFUNC BOleFact::AllowEmbedFromSelf ()
|
|
{
|
|
return pIPEFact ? TRUE : FALSE;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// BOleInProcFactory -- The role of this factory is to load the default
|
|
// handler on the server side when the container
|
|
// side of an app needs to instantiate an object it
|
|
// serves.
|
|
//
|
|
// If we don't do this, the RPC/handler system
|
|
// creates the server object as if it were an inproc
|
|
// server with no handler, but our EXE-based objects
|
|
// must use the default handler.
|
|
//
|
|
//**************************************************************************
|
|
|
|
//***********************************
|
|
//
|
|
// Implementation methods
|
|
//
|
|
//***********************************
|
|
|
|
BOleInProcFactory::BOleInProcFactory (BOleClassManager *pCM, BOleFact FAR *pF, REFIID iid) : BOleComponent(pCM, NULL),
|
|
iidServer (iid),
|
|
nRef (1),
|
|
pRealFactory (pF),
|
|
regCookie (0)
|
|
{
|
|
pF->AddRef();
|
|
}
|
|
|
|
BOleInProcFactory::~BOleInProcFactory ()
|
|
{
|
|
if (pRealFactory) {
|
|
pRealFactory->Release();
|
|
pRealFactory = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT _IFUNC BOleInProcFactory::Register (BOOL fSingleUse)
|
|
{
|
|
HRESULT hr = ::CoRegisterClassObject (
|
|
iidServer, this, CLSCTX_INPROC_SERVER,
|
|
fSingleUse ? REGCLS_SINGLEUSE : REGCLS_MULTI_SEPARATE, ®Cookie);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
LPCLASSFACTORY pWorkAround = this;
|
|
CoLockObjectExternal (pWorkAround, TRUE, TRUE);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleInProcFactory::Revoke ()
|
|
{
|
|
if (regCookie) {
|
|
LPCLASSFACTORY pWorkAround = this;
|
|
CoLockObjectExternal (pWorkAround, FALSE, TRUE);
|
|
return ::CoRevokeClassObject (regCookie);
|
|
}
|
|
|
|
if (pRealFactory) { // this breaks a cycle when we're
|
|
pRealFactory->Release(); // in the embed from file "registered case"
|
|
pRealFactory = NULL;
|
|
}
|
|
// if we don't register we expect releasing BOleInProcFactory
|
|
// to release BOleFact (since BOleInProcFactory is returned
|
|
// from DllGetClassObject)
|
|
//
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
//***********************************
|
|
//
|
|
// IUnknown methods
|
|
//
|
|
//***********************************
|
|
|
|
HRESULT _IFUNC BOleInProcFactory::QueryInterfaceMain(REFIID riid, LPVOID FAR *ppObj)
|
|
{
|
|
HRESULT hr;
|
|
*ppObj = NULL;
|
|
if (SUCCEEDED(hr = IClassFactory_QueryInterface (this, riid, ppObj))) {
|
|
}
|
|
else if (SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(riid, ppObj))) {
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//***********************************
|
|
//
|
|
// IClassFactory methods
|
|
//
|
|
//***********************************
|
|
|
|
HRESULT _IFUNC BOleInProcFactory::CreateInstance (LPUNKNOWN pUnkOuter,
|
|
REFIID iidContainer, LPVOID FAR* ppv)
|
|
{
|
|
// We ask OLE2 to create an instance
|
|
// of the default handler. The default handler uses pRealFactory to
|
|
// call back to us when it's time to create the real server object.
|
|
//
|
|
return ::OleCreateEmbeddingHelper (iidServer, pUnkOuter,
|
|
EMBDHLP_INPROC_SERVER | EMBDHLP_DELAYCREATE, pRealFactory,
|
|
iidContainer, ppv);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleInProcFactory::LockServer (BOOL fLock)
|
|
{
|
|
::CoLockObjectExternal (this, fLock, TRUE);
|
|
pFactory->ServerCount (fLock ? 1L : -1L);
|
|
return NOERROR;
|
|
}
|
|
|
|
|