OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
autosym.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectComponents
3// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// OLE Automation Server Implementation, except TServedObject (in typelib.cpp)
7//----------------------------------------------------------------------------
8#include <ocf/pch.h>
9
10#include <ocf/appdesc.h>
11#include <ocf/ocreg.h>
12#include <ocf/occtrl.h>
13
14namespace ocf {
15
16using namespace owl;
17
18TAutoType TAutoVoid ::ClassInfo = {atVoid};
19TAutoType TAutoByte ::ClassInfo = {atByte};
20TAutoType TAutoShort ::ClassInfo = {atShort};
21TAutoType TAutoLong ::ClassInfo = {atLong};
22TAutoType TAutoFloat ::ClassInfo = {atFloat};
23TAutoType TAutoDouble ::ClassInfo = {atDouble};
24TAutoType TAutoCurrency ::ClassInfo = {atCurrency};
25TAutoType TAutoDate ::ClassInfo = {atDatetime};
26TAutoType TAutoString ::ClassInfo = {atString};
27TAutoType TAutoBool ::ClassInfo = {atBool};
28TAutoType TAutoUnknown ::ClassInfo = {atUnknown};
29TAutoType TAutoDispatch ::ClassInfo = {atObject};
30TAutoType TAutoVariant ::ClassInfo = {atVariant};
31TAutoType TAutoSafeArray ::ClassInfo = {atSafeArray};
32TAutoType TAutoShortRef ::ClassInfo = {atByRef|atShort};
33TAutoType TAutoLongRef ::ClassInfo = {atByRef|atLong};
34TAutoType TAutoFloatRef ::ClassInfo = {atByRef|atFloat};
35TAutoType TAutoDoubleRef ::ClassInfo = {atByRef|atDouble};
37TAutoType TAutoDateRef ::ClassInfo = {atByRef|atDatetime};
38TAutoType TAutoStringRef ::ClassInfo = {atByRef|atString};
39TAutoType TAutoVariantRef ::ClassInfo = {atByRef|atVariant};
40TAutoType TAutoBoolRef ::ClassInfo = {atByRef|atBool};
41TAutoType TAutoByteRef ::ClassInfo = {atByRef|atByte};
42
43
44_OCFFUNC(void) SendObituary(const void * obj, const std::type_info& typeInfo)
45{
47 if (appDesc)
48 appDesc->InvalidateObject(ocf::MostDerived(obj, typeInfo));
49}
50//----------------------------------------------------------------------------
51// TAutoClass implementation
52//
53
54TAutoClass::TClassList TAutoClass::ClassList = {0,0,0};// MUST BE MODULE GLOBAL
55
57 const std::type_info& typeInfo, TAggregator aggregator)
58 : Table(table), ClassSymbol(classSymbol), TypeInfo(typeInfo),
59 Aggregator(aggregator), AutoIds (TRUE)
60{
62 NextClass = ClassList.List;
63 ClassList.List = this;
64 ClassList.Count++;
65}
66
67TAutoClass::~TAutoClass() // do we really need to support dynamic AutoClass?
68{
69 for (TAutoClass** link = &ClassList.List; *link != 0; link = &(*link)->NextClass)
70 if (*link == this) {
71 *link = NextClass;
72 break;
73 }
74}
75
77{
78 TAutoSymbol* sym;
79 if (!CommandCount) {
80 for (sym = Table; !sym->IsTerminator(); sym++) {
81 int attr = sym->GetFlags();
82 if (attr & asAnyCommand) {
84 if (attr & asOleType) {
85 if ((attr & asGetSet) == asGetSet)
87 else
89 }
90 } else if (sym->TestFlag(asClass)) {
91 TAutoClass* cls = sym->GetClass();
92 if (!sym->SymCount)
93 sym->SymCount = cls->CountCommands();
97 }
98 }
99 }
100 return CommandCount;
101}
102
104{
105 TAutoSymbol* sym;
106 long cmdId;
107 if ((id <= 0) || !(AutoIds)) {
108 // reserved dispatch ID if negative or zero or AutoIDs is false
109 for (sym = Table; !sym->IsTerminator(); sym++) {
110 if (sym->TestFlag(asAnyCommand) && sym->DispId == id)
111 return sym;
112
113 if (sym->TestFlag(asClass)) {
114 ObjectPtr adjObj = sym->Convert(obj); // this pointer adjustment
115 TAutoSymbol* fsym = sym->GetClass()->FindId(id, adjObj);
116 if (fsym) {
117 obj = adjObj;
118 return fsym;
119 }
120 }
121 }
122 } else {
123 for (cmdId = 0, sym = Table; !sym->IsTerminator(); sym++) {
124 if (sym->TestFlag(asClass)) {
125 if (!sym->SymCount)
126 sym->SymCount = sym->GetClass()->CountCommands();
127 if (cmdId + sym->SymCount >= id) { // symbol in nested class
128 obj = sym->Convert(obj);
129 return sym->GetClass()->FindId(id-cmdId, obj);
130 }
131 cmdId += sym->SymCount;
132 }
133 else if (sym->TestFlag(asAnyCommand)) {
134 cmdId++;
135 if (cmdId == id) {
136 if (sym->DispId == -1)
137 return sym;
138 else
139 break;
140 }
141 }
142 }
143 }
144 return 0;
145}
146
147TAutoSymbol* TAutoClass::FindFunction(unsigned index, MEMBERID& retId)
148{
149 TAutoSymbol* sym;
150 int funcCount = 0;
151 long cmdId = retId;
152 for (sym = Table; !sym->IsTerminator(); sym++) {
153 int attr = sym->GetFlags();
154 if (attr & asAnyCommand) {
155 cmdId++;
156 if ((attr & asOleType) != 0 && (attr & asGetSet) != asGetSet) {
157 if (funcCount++ == (int)index) {
158 retId = (sym->DispId == -1L) ? cmdId : sym->DispId;
159 return sym;
160 }
161 }
162 } else if (sym->TestFlag(asClass)) {
163 TAutoClass* cls = sym->GetClass();
164 if (!sym->SymCount)
165 sym->SymCount = cls->CountCommands();
166 if (funcCount + cls->FunctionCount > (int)index) {
167 retId = int(cmdId);
168 return cls->FindFunction(index - funcCount, retId);
169 }
170 funcCount += cls->FunctionCount;
171 cmdId += cls->CommandCount;
172 }
173 }
174 return 0; // should never happen unless caller overruns total count
175}
176
177TAutoSymbol* TAutoClass::FindVariable(unsigned index, MEMBERID& retId)
178{
179 TAutoSymbol* sym;
180 int varCount = 0;
181 long cmdId = retId;
182 for (sym = Table; !sym->IsTerminator(); sym++) {
183 int attr = sym->GetFlags();
184 if (attr & asAnyCommand) {
185 cmdId++;
186 if ((attr & asGetSet) == asGetSet) {
187 if (varCount++ == (int)index) {
188 retId = (sym->DispId == -1L) ? cmdId : sym->DispId;
189 return sym;
190 }
191 }
192 } else if (sym->TestFlag(asClass)) {
193 TAutoClass* cls = sym->GetClass();
194 if (!sym->SymCount)
195 sym->SymCount = cls->CountCommands();
196 if (varCount + cls->VariableCount > (int)index){
197 retId = int(cmdId);
198 return cls->FindVariable(index - varCount, retId);
199 }
200 varCount += cls->VariableCount;
201 cmdId += cls->CommandCount;
202 }
203 }
204 return 0; // should never happen unless caller overruns total count
205}
206
208{
209 short count = 0;
210 TAutoSymbol* arg = &sym;
211 while ((++arg)->TestFlag(asArgument))
212 count++;
213 return count;
214}
215
216TAutoSymbol* TAutoClass::Lookup(_TCHAR * name, TLangId lang, short symflags,
217 long & retid)
218{
219 long cmdId = 0;
220 for (TAutoSymbol* sym = Table; !sym->IsTerminator(); sym++) {
221 if (sym->TestFlag(asAnyCommand))
222 cmdId++;
223 if (sym->TestFlag(symflags) && sym->Name.Compare(name, lang) == 0) {
224 retid = sym->DispId == -1 ? cmdId : sym->DispId;
225 return sym;
226 }
227 else if (sym->TestFlag(asClass)) {
228 TAutoClass* cls = sym->GetClass();
229 if (!sym->SymCount)
230 sym->SymCount = cls->CountCommands();
231 long id;
232 TAutoSymbol* found = cls->Lookup(name, lang, symflags, id);
233 if (found) {
234 retid = id > 0 ? id + (long)cmdId : id;
235 return found;
236 }
237 cmdId += sym->SymCount;
238 }
239 }
240 return 0;
241}
242
244 TAutoSymbol* sym, long & retid)
245{
246 PRECONDITION(sym);
247
248 for (int i = 0; (++sym)->TestFlag(asArgument); ++i)
249 if (sym->Name.Compare(name, lang) == 0) {
250 retid = (long)i;
251 return sym;
252 }
253 return 0;
254}
255
257 TUnknown& owner, int attr,
258 TAutoStack& args, TAutoVal* retval)
259{
260 TAutoCommand* cmdobj = 0;
261 TAutoIterator* iterator = 0;
262 try {
263 if (args.Symbol->IsIterator()) {
264 iterator = args.Symbol->BuildIter(obj, creator, owner, args.LangId);
265 iterator->SetSymbol(args.Symbol);
266 iterator->Init();
267 *retval = (IUnknown*)*iterator; // remains until RefCnt->0
268 } else {
269 cmdobj = args.Symbol->Build(obj, attr, args);
270 cmdobj->SetSymbol(args.Symbol);
271 if (args.ArgCount>0 && !cmdobj->Validate()) {// no validate for prop get
272 delete cmdobj;
274 }
275 cmdobj->Invoke();
276 if ((args.ErrorCode = cmdobj->Report()) != 0) {
278 if (!args.ErrorMsg && args.Symbol) // if no error message available
279 args.ErrorMsg = args.Symbol->Name.Translate(args.LangId);
280 delete cmdobj;
282 }
283 if (retval) {
284 cmdobj->Return(*retval);
285 if (args.Symbol->IsEnum())
286 args.Symbol->GetEnum()->Convert(*retval, args.LangId);
287 TObjectDescriptor objDesc;
288 if (retval->GetObjDesc(objDesc)) {
289 if (!objDesc.Object) // null pointer returned from function
290 // there are three choices for behavior here:
291 // 1. Allow a dead object to be returned, fail when passed back
292 // 2. Fail now, however this prevents testing for null pointer
293 // 3. Return an empty variant, causing script to fail when used
294 *retval = TAutoVoid(); // return an empty value if no object
295 else
296 *retval = creator.CreateDispatch(objDesc);
297 }
298 }
299 delete cmdobj;
300 }
301 }
302 catch(TXAuto& xobj) {
303 delete cmdobj;
304 delete iterator;
305 return xobj.ErrorCode;
306 }
307 return TXAuto::xNoError;
308}
309
310TAutoClass::TExtLink::TExtLink(TClassList* list, HINSTANCE module)
311 : Classes(list), Module(module), Next(0)
312{
313 for (Prev = &ClassList.Link; *Prev; Prev = &(*Prev)->Next)
314 ; // link to end of list
315}
316
317TAutoClass::TExtLink::~TExtLink()
318{
319 *Prev = Next;
320 if (Next)
321 Next->Prev = Prev;
322}
323
324//
325//
326//
327int
328TAutoClass::TClassList::CountAutoClasses()
329{
330 int count = Count;
331 for (TExtLink* link = Link; link; link = link->Next)
332 count += link->Classes->CountAutoClasses();
333 return count;
334}
335
336//
337//
338//
339TAutoClass::TAutoClassRef*
340TAutoClass::TClassList::MergeAutoClasses(TAutoClass::TAutoClassRef* array)
341{
342 for (TAutoClass* cls = List; cls; cls = cls->NextClass, array++)
343 array->Class = cls;
344 for (TExtLink* link = Link; link; link = link->Next)
345 array = link->Classes->MergeAutoClasses(array);
346 return array;
347}
348
349// ----------------------------------------------------------------------
350// Helper routines
351//
352
353//
354//
355TAutoCommand*
356AutoQuitBuild(ObjectPtr obj, int/*attr*/, TAutoStack& args)
357{
358 TServedObject& owner = *args.Owner;
359
360 // if the automation object is not in control of the app, execute a no-op
361 //
363 return new TAutoCommand(0);
364
365 // if registered as the active object, free it to release OLE's refcnt
366 //
367 if (owner.Creator.GetAppDesc().IsActiveObject(&owner))
369
370 // disconnect automation from app to prevent further access
371 //
372 owner.Object = 0;
373 owner.RootObject = 0;
374
375 // build command object for destructor, will either delete or PostQuitMsg
376 //
377 return owner.Class->GetDestructor()(obj, owner.Destruct);
378}
379
380#if defined(BI_COMP_BORLANDC) && defined(__clang__)
381} // OCF namespace
382//
383// The Clang-based compilers use the Itanium C++ ABI for RTTI, in which the type_info objects for
384// classes derive from __cxxabiv1::__class_type_info, and dynamic_cast is implemented by the runtime
385// function __dynamic_cast. The function is not declared in the standard library headers.
386//
387namespace __cxxabiv1 {
388class __class_type_info;
389extern "C" void* __dynamic_cast(const void* sub, const __class_type_info* src,
390 const __class_type_info* dst, std::ptrdiff_t src2dst);
391}
392namespace ocf {
393#elif defined(BI_COMP_BORLANDC)
394} // OCF namespace
395//
396// Temporary defines for using std::type_info with dynamic cast
397//
398void* __cdecl __DynamicCast(void* object, void* vtable,
399 void* srctyp, void* dsttyp,
400 int reference = 0);
401struct tpid {int s; short m; short n; int VptrOffs; int Flags;}; // partial
402namespace ocf {
403#endif
404//
405//
406const void*
407DynamicCast(const void* obj, const std::type_info& src, const std::type_info& dst)
408{
409#if defined(BI_COMP_BORLANDC) && defined(__clang__)
410 using namespace __cxxabiv1;
411 if (!obj || src == dst)
412 return obj;
413 return __dynamic_cast(obj, reinterpret_cast<const __class_type_info*>(&src),
414 reinterpret_cast<const __class_type_info*>(&dst), -1); // -1: No hint about the relationship.
415#elif defined(BI_COMP_BORLANDC)
416 int vtblOff;
417 if (!obj)
418 return obj;
419 else if ((vtblOff = src.tpp->VptrOffs) == -1)
420 return src==dst ? obj : 0;
421 else
422 return __DynamicCast(const_cast<void *>(obj),
423 *(void **)((char*)obj+vtblOff), src.tpp,dst.tpp);
424#else
425 return __RTDynamicCast((void*)obj,0,(void*)&src,(void*)&dst,0);
426#endif //BI_COMP_BORLANDC
427}
428
429
430//
431//
432const void *
433MostDerived(const void * obj, const std::type_info& src)
434{
435#if defined(BI_COMP_BORLANDC) && !defined(__clang__) // TODO: This needs review for Clang!
436 int vtblOff;
437 if (!obj || (vtblOff = src.tpp->VptrOffs) == -1)
438 return obj;
439 else
440 return __DynamicCast(const_cast<void *>(obj),
441 *(void **)((char*)obj+vtblOff), src.tpp, 0);
442#else
443 return obj;
444#endif
445}
446
447
448//____________________________________________________________________________
449//
450// TAutoCommand implementation - inlined to allow definition of _AUTOCLASS
451//____________________________________________________________________________
452
453_OCFDATA(TAutoCommand::TErrorMsgHook) TAutoCommand_ErrorLookup = 0; // module static
454_OCFDATA(TAutoCommand::TCommandHook) TAutoCommand_InvokeHook = 0; // module static
455
456} // OCF namespace
457
458//==============================================================================
459
460
TAppDescriptor - OLE application descriptor definitions.
#define PRECONDITION(condition)
Definition checks.h:227
bool IsActiveObject(TServedObject *obj)
Definition appdesc.h:132
void UnregisterObject()
Invalidates a helper object registers with RegisterObject earlier.
Definition appdesc.cpp:459
void InvalidateObject(const void *obj)
Definition appdesc.cpp:669
short CommandCount
command count including bases, 0 if uncounted
Definition autodefs.h:179
TAutoSymbol * Lookup(TCHAR *name, owl::TLangId lang, short symFlags, long &id)
Definition autosym.cpp:216
bool AutoIds
generate ID's automatically if true (default)
Definition autodefs.h:182
TAutoSymbol * ClassSymbol
pointer to class symbol (terminator)
Definition autodefs.h:184
TAggregator Aggregator
aggregator function for C++ COM classes
Definition autodefs.h:178
TAutoSymbol * FindVariable(unsigned index, MEMBERID &retId)
Definition autosym.cpp:177
TXAuto::TError Dispatch(ObjectPtr obj, TAutoCreator &creator, TUnknown &owner, int attr, TAutoStack &args, TAutoVal *retval)
Definition autosym.cpp:256
TAutoClass(TAutoSymbol *table, TAutoSymbol *classSymbol, const std::type_info &typeInfo, TAggregator aggregator=0)
Definition autosym.cpp:56
friend struct TClassList
access to TAutoClassRef
Definition autodefs.h:211
short CountCommands()
Definition autosym.cpp:76
TAutoSymbol * Table
pointer to array of symbol entries
Definition autodefs.h:183
short VariableCount
number of symbols exposed as typelib variables
Definition autodefs.h:181
TAutoSymbol * FindFunction(unsigned index, MEMBERID &retId)
Definition autosym.cpp:147
TAutoSymbol * LookupArg(TCHAR *name, owl::TLangId lang, TAutoSymbol *cmd, long &retid)
Definition autosym.cpp:243
TAutoCommandBuildDtr GetDestructor() const
Definition autodefs.h:1466
TAutoSymbol * FindId(long id, ObjectPtr &objptr)
Definition autosym.cpp:103
short FunctionCount
number of symbols exposed as typelib functions
Definition autodefs.h:180
const std::type_info & TypeInfo
for validating type of data pointers
Definition autodefs.h:185
short GetArgCount(TAutoSymbol &sym)
Definition autosym.cpp:207
Automation abstract base class for command objects.
Definition autodefs.h:846
TAutoCommand(int attr)
Definition autodefs.h:1820
virtual TAutoCommand & Invoke()
Definition autodefs.h:1931
static LPCTSTR LookupError(long errCode)
Definition autodefs.h:1827
virtual bool Validate()
Definition autodefs.h:1929
bool(*) TCommandHook(TAutoCommand &cmdObj)
Definition autodefs.h:866
virtual void Return(TAutoVal &v)
Definition autodefs.h:1947
void SetSymbol(TAutoSymbol *sym)
Definition autodefs.h:1826
LPCTSTR(*) TErrorMsgHook(long errCode)
Definition autodefs.h:863
virtual long Report()
Definition autodefs.h:1942
Object responsible for creating automation COM object.
Definition autodefs.h:924
virtual IDispatch * CreateDispatch(TObjectDescriptor objDesc, IUnknown *outer=0)=0
virtual bool Convert(TAutoVal &txtVal, TAutoVal &numVal)=0
automation collection iterator
Definition autodefs.h:1186
void SetSymbol(TAutoSymbol *sym)
Definition autodefs.h:1904
virtual void Init()=0
Automation argument stack abstraction.
Definition autodefs.h:813
owl::TLangId LangId
Definition autodefs.h:827
TServedObject * Owner
Definition autodefs.h:828
TAutoSymbol * Symbol
Symbol of method/prop, args follow.
Definition autodefs.h:822
long ErrorCode
Set if TXAuto::xErrorStatus returned.
Definition autodefs.h:829
LPCTSTR ErrorMsg
Set if TXAuto::xErrorStatus returned.
Definition autodefs.h:830
Automation data element (same data as OLE/BASIC VARIANT).
Definition autodefs.h:526
bool GetObjDesc(TObjectDescriptor &)
Definition autodefs.h:1759
TAppDescriptor & GetAppDesc()
Definition autodefs.h:943
OLE object exposed for automated access of internal object.
Definition autodefs.h:972
TServedObjectCreator & Creator
Definition autodefs.h:985
TObjectDescriptor::TDestruct Destruct
what to do with C++ object
Definition autodefs.h:988
void * Object
pointer to C++ object instance, 0 if deleted
Definition autodefs.h:982
const void * RootObject
pointer to object of most derived class
Definition autodefs.h:983
TAutoClass * Class
class of which object is an instance
Definition autodefs.h:984
Standard implementation of a controlling IUnknown for an object, to be inherited with other COM inter...
Definition oleutil.h:264
Automation exception object.
Definition autodefs.h:115
TError ErrorCode
Definition autodefs.h:135
@ xValidateFailure
Definition autodefs.h:126
Include for OC, gets common headers when precompiled headers are enabled.
Object Component Framework (COM encapsulation).
Definition appdesc.h:22
void * ObjectPtr
Definition autodefs.h:84
const void * MostDerived(const void *obj, const std::type_info &src)
Definition autosym.cpp:433
const owl::uint16 atAutoClass
Definition autodefs.h:347
const owl::uint16 atSafeArray
Definition autodefs.h:344
@ asClass
extension to another class symbol table
Definition autodefs.h:307
@ asGetSet
can get or set property(...GET + ...SET)
Definition autodefs.h:304
@ asOleType
method or property exposed for OLE
Definition autodefs.h:299
@ asAnyCommand
any command: method, property get/set, build
Definition autodefs.h:298
@ asArgument
property returning an object
Definition autodefs.h:308
const void * DynamicCast(const void *obj, const std::type_info &src, const std::type_info &dst)
Definition autosym.cpp:407
TAutoCommand * AutoQuitBuild(ObjectPtr obj, int attr, TAutoStack &args)
Definition autosym.cpp:356
IUnknown &(*) TAggregator(ObjectPtr obj, TUnknown &inner)
Definition autodefs.h:102
const owl::uint16 atByRef
Definition autodefs.h:345
TAppDescriptor * GetAppDescriptor()
Definition appdesc.h:203
@ atLong
Definition autodefs.h:326
@ atObject
Definition autodefs.h:332
@ atString
Definition autodefs.h:331
@ atByte
Definition autodefs.h:337
@ atVoid
Definition autodefs.h:323
@ atDatetime
Definition autodefs.h:330
@ atCurrency
Definition autodefs.h:329
@ atUnknown
Definition autodefs.h:336
@ atBool
Definition autodefs.h:334
@ atDouble
Definition autodefs.h:328
@ atVariant
Definition autodefs.h:335
@ atFloat
Definition autodefs.h:327
@ atShort
Definition autodefs.h:325
void SendObituary(const void *obj, const std::type_info &typeInfo)
Definition autosym.cpp:44
owl::uint16 TLangId
Holds a language ID, a predefined number that represents a base language and dialect.
Definition lclstrng.h:26
TModule * Module
Definition global.cpp:34
ulong TStaticSync< T >::Count
Definition thread.h:1354
Definition of TOcControl class - Proxy object representing a control in.
#define _OCFFUNC(p)
Definition defs.h:47
#define _OCFDATA(p)
Definition defs.h:46
OLE Registration definitions.
static TAutoType ClassInfo
Definition autodefs.h:280
Symbol table element.
Definition autodefs.h:404
bool IsIterator() const
Definition autodefs.h:1522
TAutoClass * GetClass() const
Definition autodefs.h:1531
bool TestFlag(owl::uint16 mask) const
Definition autodefs.h:1507
bool IsEnum() const
Definition autodefs.h:1513
owl::TLocaleString Name
name of symbol, initially untranslated
Definition autodefs.h:405
owl::uint16 GetFlags() const
Definition autodefs.h:1510
TAutoEnum * GetEnum() const
Definition autodefs.h:1534
bool IsTerminator() const
Definition autodefs.h:1525
owl::uint16 Type
Definition autodefs.h:144
const void * Object
< ONLY for use when storing in TAutoVal union
Definition autodefs.h:452
@ Quiet
behavior when an automation helper is freed
Definition autodefs.h:472
int Compare(const tchar *str, TLangId lang)
insensitive compare
Definition locale.cpp:434
const tchar * Translate(TLangId lang)
translate string
Definition locale.cpp:368