PDA

View Full Version : Help please: module classes - Properties



ReneMiner
08-04-2022, 02:46
Does anyone know how to use thinBasic_class_AddProperty() ?



'thinBasic_Class_AddProperty
'----------------------------------------------------------------------------
' Add a property to a class previously created with thinBasic_Class_Add
'----------------------------------------------------------------------------
DECLARE FUNCTION thinBasic_Class_AddProperty _
LIB "thinCore.dll" _
ALIAS "thinBasic_Class_AddProperty" _
( _
BYVAL pClass AS LONG , _ '---Poiter to a class. This is the value returned by thinBasic_Class_Add
BYVAL sPropertyName AS STRING , _ '---Name of the Class to be created
BYVAL PropertyReturnType AS LONG , _
BYVAL PtrToPropertyFunction AS LONG _ '---Pointer to a method function that will handle method execution
) AS LONG




'============================================================================================


:scenic:this seems incomplete to me.

Properties as i kniow have usually 3 procedures Let, Get and Set that are present or not present for every UDT-Subelement and the presence of the
property-procedure determinesif there is a default value and if access allowed to read or write at all.


Let := the initial, predefined, default setting applied on creation to any new object of the type, inherited from prototypes if no own dedicated Let is present for the inherited property. An empty Let-procedure will override the inherited setting just because it is present. Without a Let-procedure a property will contain Nothing
when the object that owns the propertyt is created.


Get := request to pass the data that is stored for this property. Required within the Get-procedure is a read-only- reference that holds full Function-name (stacklevel below this) which in case UDT-function will also hold the type of the invoker of that call. To assure it's not a virtual fake using a layover the call-invokers varptr mus be followed down all stack levels and if the stack level above the first appearance of the caller is _CREATE and the name of the variable on that level is "ME" then for sure the call is invoked by the referenced object that was dimensioned on the memory-position which matches the current varptr. Without a Get-procedure the property is limited to a public "Can Set if condition"-state and the owner can still decide no, the condition is not valid for you since its not possible from outside to check the properties current state.

Set := request to fill a passed value into the memory-position that represents the properties data. Of course data must match in type, size and count if property were an array. If not matching - bye bye. Caller can not alter properties by pushing a value in to make it fit but request the owner to shape the property in a way that the data will fit. In case the owner expects it the property will be prepared anyway or there is a dedicated method that were known to the calls-invoker. Without a Set-procedure the data at most public read-only , if none of the both is present the property is totally private.




Property <propertyname> Let(byRef data as Typeof(This.<propertyname>))
data = <InitialSetting and one more if sunday>
End Property

Property <propertyname> Get(Byval Invoker As thinbasic_ObjectSecuritycheckresultEx) As TypeOf(This.<propertyname>)
if (Typeof(me) <> Invoker.DetectedType Then
SendMessage(hSecurity, %SM_Intruder, "attempt", Invoker.CurrentLocation)
Exit Property
endif
End Property

Property <propertyName> Set( Byval Invoker As As thinbasic_ObjectSecuritycheckresultEx, Byref data As Typeof(this.<propertyname>)

if condition=OK Then This.Property=data
End Property


the "thnBasic_ObjectSecurityCeckResultt" :wizard: were a small udt that provides infformation as TypeOf(Invoker), Varptr(Invoker) , FunctionName of the lowest stacklevel where a variable at same position appears for the firrst time. Must be down from current stack level and stop where no variable is dimensioned on this position and go 1 level up again . There we have the function where the caller was created in. if one more level up is no function that ends with "_CREATE" means if the type of the property-owner has a create-function the invoker of the call is not real. If the function ends with "_Create" it also tells the type as that the variable was created when we remove 7 chars on the right. ("_CREATE") remains a type-name, ideally the name of the variable as what the typename is replaced when a function is called on a type.
However, security-information is combined of :comp5:


3 sdk-functions:

thinBasic_VariableGetList retrieve list of all variable names on a stack-levels below starting level, i.e. at the callers level

thinBasic_StackGetList retrieve the function-name on all stack-levels below current (= callers level)

thinBasic_VariableGetInfoEX actually we are interested only in 3 values searchkey, dataptr and stacklevel


2 thinbasic-functions

VarPtr() required the varptr of the call-invoker. as a type function requires a reference it should not be difficult
to retrieve from where in memory the call was made.

Function_StackGetLevel assure the current stack level is the one above starting investigation.


ATTENTION: If you pass Function_GetStacklevel as a parameter it will not return the stacklevel of the caller
but is evaluated on arrival and returns the called stacklevel but not the callers level. Conserve the result
-before you pass it - into a variable to pass the real value of your current stacklevel


:locomotive:
How it works: As first determine varptr of the caller and get the current stacklevel
then get the stacklist as



String sFunc()
Long nLevels = Parse Ucase$(thinBasic_StackGetList($NUL), sFunc, $NUL


nLevels should equal current stacklevel, sFunc(nLevels) should hold the functions name where inside you are.
if its shifted by 1 there might be an unforseen app_entry through a side-entrance ,

that can be abusing _Create-function as app_entrypoint,

no tbMain present or never entered ( it would usually appear in sFunc(2) )
the never-exit from a callback by buillding a mainloop inside a callback-function
(- bad idea - windows will shut you down soon as not responding app)

or with some suicidalwild approach catapulting yourself
using codepointers of dlls to jump from function to function -

testing a dubious module that will implement finally the long time missed
- but by some genius brand-new developed GOTO-statement for thinbasic
where you exit another function as the one that as entered before.

Risky, hot stuff that can shoot not just your tb-installation
including the destruction of the root-folder in thats subdir your script or dll is located.
If your scripts are saved to "%systemdrive%\Users\Username\whatever"
the effect is hitting the most vulnerable spot - of the os,

say "good bye users" and your only chance is reduced to the fact that you have
a 3rd party tool as 7zFM , Multicommander or TotalCommander opened which could
rescue something through exraction of a backup that contains also the users folder.
It will not rescue the content of the users folder nor your data inside, but save you
the complete re-install-procedure of windows
:offtopic:

OOps... sorry-... :blind:

yes...err where was i ... the invoker of the call to a type function - determine list of functions that build the current "stack-level-ladder"
then go down 1 level,
obtain list of variables on the level, iterate the variable-names pass the names to thinBasic_GetVariableInfoEx and also the current stack level and compare the DataPtr that is filled in by the function.
If it matches, then you passed the name that the invoker has on this stacklevel .
continue and repeat the same procedure
get variable names and pass them to compare dataptr with the varptr. if there is no match on this level means you are below the level where the invoker was dimensioned. So you find already function of first appearance and the name as that thew suspect was dimensioned.

A lot of useful information you will get if you go 2 levels up again when you are below the first appearance level. the functions name con that level can tell you if the invoker is a virtual or a real variable. If the name of the function ends with "_CREATE" you have found a real variuable, remove the 7 chars from the right, i.e. Left$(s, Lenf(s)-7) : that reveals the udt as that the suspect was dimensioned. . The not-presence of a create-function is not necessarily a sign of evil. But if a create-function is present for the type and our invoker is not member of an array it remains the virtual variable that is used by someone with no good intentions.

Accidental no one will make any effort for disguise of some variable being another one. There are already tools available and we have the additional option to use iinheritage of some secret security-features that a native classification in thinbasic could have. For the classification required are the properties that will elevate types to become prototypes =templates of cllass-objects. the other thing is the script structure which is currently procedural mainly. Some UI-items as the webbrowser-control contains the requiremnents to make an app event-driven - no own mainloop but all is reaction on user-actions. a very stable and simple way of building an app. Threadsafe by nature and actually fits the behaviour if a script runs window-bound in thinbasic. Losing focus halts the execution . Good for windows but we can get over this already using all kinds of triggers (timers not bound to a window, sending of callback messages in an endless loop of one calls two-two calls three,.three calls four...) and there are couple of more ways to stay in race without having a windows-focus. :offtopic:

Again?

sorry... :rulez: i know...
the scriptfiles themselves must have written something on the first and last line of the file. Using invisible ink, and the line on top were


Type fullpath_scriptfilename.tBasic[C|I|U]?

and the last line were


End Type

now scriptfiles were to classify into a MainScript and only the one with the app-entry-point has the very special rights to acccess all that is created by the main-function ("GOD-MODE") , other functions contained within the Main-scriptfile have limited rights as they share a common variable-scope that is not shared with any other file what is defined PUBLIC or COMMON were shared by the functions that are located within same Script-Area which ends if physically another scope is errected

. Type-definitions, Unions, ergo classes and callback functions are barriers that limit the valid range where the scriptfile itself is an udt.
Same rule for all: no udt can intersect the borders of another udt. if the script is an udt the mainscript centralizes the valid area of the major-app-scope
special declarations-section - the part of any udt-definition between the first line "Type tTypename" and the headline of the first Method where for an udt where the subelements are defined anbut only definitions, dimensionss, declaration, enumerations, namelists etc.

the scope-free area of the main-scriptfile is where DIM will by default create global variables. Privates can not be for non-property-owners but functions within the main-scriptfile share the subelements of a hidden type that are assigned to this hidden udt when using the keyword PUBLIC and in all functions that share the Public range on all the hidden utds properties are virtual variables local dimensioned over the subelements of the hidden udt as soon any function is entered that is defined within this "public" udts invisible Typ-End Type range, creating the illusion that same named variables of same type as outside of the function would survive what usually happens to any local variables when a function is terminated.

Public is an illusion , created by virtual alias/layover with same name as the udt-elements of thew hidden type that wears a scriptname and that is not to be dimensioned as a variable. There is no further protection required functtions and anything else of the project that is not connected to the "Aura of TBMain" will not be supplied with the virtual pre-dimensioned variables upon the scriptname-type.
There is another type of scripts that could have a scope . the unit. pretty simple . if contains not a type- statement in the first and end type in the last line but is called unit (tBasicU) the requiremmeents are simple: No UDT/class/Union end Type/class/ Unionblock allowed. Only functions and subs. Outside of functions and subs declarations, definitions, enumerations, resource-blocks only but no executed code that exceeds initial assignment for that simple core-functions are ok as Hex$, ASC, ABS, Fix, MinMax . Also preparsing statements, directives all what starts with a #-char is only a allowed outside of scriptfunctions and ignores any scope range- Not influencd as these keywords do not interact with variables content but theirs availability.
in no case the mainscript nor a unit must expose major structural keywords utsidw of a function/sub- end function/sub frame. this means Do/While/For/Repeat loop-conditionals and If, Select Case, Try-Catch, Call - pretty much all core keywords that alone will raise an error. -
exceptions are lines starting Declare, Alias Uses, Module that actually were to place in global scope areas.

:stamp: Enough na- too much!

Really? but am not finished. Maybe you continue reading another time...

When the whole script is divided to aereas that have own variable scopes , units that either contain one real type/class/union only or none are elevated to kind of pseudo-class - wait -remove the unions or add functions to them . without functions the unions are nothing equal to types nor classes but the closes relatives of arrays that suffer the same faith.

properties to types ... make prototypes.

Prototype never Extends any other Type and all elevated types (name them class now when their ancestor is a prototype)
Any class can have different types of objects. and all objects of a class can have the inherited properties which make them the same class . Some objects will have the same additional properties that are not inherited but lets these seem to have a similar layout or equal appearance. And these not-inherited properties that similar objects have in common can not be inherited from non-prototypes. inheritable is only what is individual attached. Properties from a pool are not individual. The way to create a new prototype from an existing object is cloning. A clone will not have inherited connections to any previous prototype. It's a clone. Artificial reconstructed. All its properties are created as new from scratch. That base makes it a valid prototype and can implement also properties that the original object received before it was cloned . Cloning implements copys of methods, properties and variables that are attached to other objects in non-inheritable manner and allows to inherit them from the clone as prototype. Cloning really means to copy the code that assembles the final layout with all and every bit - and here is an unbeatable advantage that an interpreter has - especially when it is able not only to assemble the unit-file for the new prototype on the fly but can also shell a new process async , drop required information to a file it shares with the new process and the user will not even know that the program he was still looking at 1 second ago has ended and what he looks at now is another process. And if you woul tell him-he 'd just smile at you and say something like

"you're kidding me. i know you're fun-type. Kind a fun-tastic touched Grow up kiddo this is serious work i'm doing here go and play sum-thin harhar got it? wordplay ?sum --- thin - Im a fun-type two . Point zero harhar..."


within Prototype udtName -End Prototype the Keyword Function becomes Method




...oh yeah where was i ? Guess i had a vision or sum-thin...

Anyone knows what rules are to play for these PROPERTIES?




[/code]

For Array-elements it's not possible to request information as this because new Array-elements could come and go by redim, means also an array can never be prototype nor an object but at most mimic the data-structure. Elemets of Arrays will be sorted and carry an "Exit Property"-sign that will become valid and is executed as soon the condition "inside property-procedure" is met. functions that are not scoped through a Type-End Type frame surrounding them

Petr Schreiber
19-04-2022, 21:36
Hi Rene,

if I may, I can offer you example of thinBasic_Class_AddProperty in the source code of thinBasic StringBuilder module:
https://github.com/petrSchreiber/thinBasic_StringBuilder


Petr