News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

ObjAsm64

Started by Biterider, January 01, 2018, 05:39:01 AM

Previous topic - Next topic

Biterider

Hi
The last weeks I started to work on the ObjAsm framework to support x64 using UASM.
It is a work in progress, since not all features are implemented yet. I choose using UASM, because it offers at least the same flexibility we are used to from ML 6.15 for x86.
The currently supported features are:
    ·  Object Oriented Programming (single inheritance)
    ·  Dual method tables:  simultaneous support of virtual method tables for "open interfaces" like COM and "not exposed" methods.
    ·  Native COM support (x64 virtual method table call and Dispatch)
    ·  Some prebuild objects like Collections, Linked Lists, Streams, Controls, Applications, etc.
    ·  Precompiled objects
    ·  Object templates, sub- and  super-classing capabilities
    ·  Virtual, dynamic, static, private methods
    ·  VARARG support
    ·  ANSI and UNICODE support
    ·  ObjMem64 library that covers most of the daily coding needs
    ·  Examples and projects
    ·  Automated compilation and build control
    ·  Etc.

Since ObjAsm64 is in beta stage, I want to ask if somebody is interested in testing it. I don't have an installer or a help file yet, but people coming from ObjAsm32 know how to use this model or you can read the old documentation. Since x64 import libraries and include files are spread around, there will be some path adjustments to do. Like ObjAsm32, ObjAsm64 has a single file that must be modified to specify your local configuration. I also added 2 new Environment Variables (OA64_PATH, MSVS_PATH) to allow the tool chain to work smoothly.
In addition to the last UASM version, you will need a proper linker and maybe some debug facilities. My choose fall on Visual Studio -Community Edition-, which comes with all necessary tools. As development editor I'm still using RadAsm (2), but you can use whatever you prefer. Each project comes with batch files to compile for release or debug targets (RLS, DBG).
Send me a PM if you are interested to participate!
Attached is one of the new translated projects.

Best regards, Biterider

Biterider

Hi
I finished the rework and migration of the OCX Container project to x64.
It proofs how well the new ObjAsm64 framework works and interacts with the x64 COM world.

At the moment, the application supports the following interfaces:

       
  • IConnectionPoint / IConnectionPointContainer
  • IEnumConnections / IEnumConnectionsPoints
  • IDispatch, IPersistStorage, IAdviseSink, IErrorInfo, IFontDisp
  • IOleObject, IOleContainer, IOleInPlaceObject, IOleWindow. IOleClientSite, IOleInPlaceSite, IOleInPlaceSite, IOleInPlaceSiteEx, IOleInPlaceActiveObject, IOleControlSite. IOleControl, IOleInPlaceSiteWindowless, IOleInPlaceFrame
  • IDataObject, IViewObject2, IProvideClassInfo, ISpecifyPropertyPages
  • ISimpleFrameSite, IPropertyNotifySink
  • IClassFactory2, IServiceProvider
All these interfaces work with several tested OCX controls. The supplied example uses a Flash Player OCX Component, which is almost present in every Windows system. The Container was tested on Win7-64 bit and Win10-64 bit systems.
Other OCX-Components like GUI-Controls (Checkbox, Combobox, etc.) work seamlessly together with the container. Also a Web-Browser Component and the Windows media Player react correctly when they are embedded.
Attached to this post are Flash Player Container and a test swf-file.

Best regards, Biterider

Biterider


Hi
I want to present one of the most used and ancient objects implemented in assembler, called "Collection".
Collections are, in first instance, repositories for any type of objects, including other collections. Mixing different type of objects in this repository is also allowed.

Collections are designed for administrative use, where very high performance is not required but a high degree of flexibility and processing capabilities. In this regard, Collections provide forward and backward searching, forward and backward iterators, stream serialization, insertion, deletion, positioning, etc. supported in the background by an automatic memory management.

Multithread synchronization is ensured, like OA32, due to the use of the low level build in synchronization call mechanism (xOCall).

There are specialized descendants of "Collection" like sorted collections, string collections, data collections, and many others for different management tasks. You can derive your own descendant, redefining the methods you want to change.

The interface of a Collection object class looks like:

Object Collection, CollectionID, Streamable

VirtualMethod    Delete,          POINTER
VirtualMethod    DeleteAt,        DWORD
VirtualMethod    DeleteAll
RedefineMethod   Deserialize,     PDESER_INFO
DynamicMethod    DeserializeItem, POINTER, PDESER_INFO
DynamicMethod    DestroyItem,     POINTER
VirtualMethod    Dispose,         POINTER
VirtualMethod    DisposeAt,       DWORD
VirtualMethod    DisposeAll
RedefineMethod   Done
VirtualMethod    FirstThat,       POINTER, QWORD, QWORD
VirtualMethod    FirstThatNot,    POINTER, QWORD, QWORD
VirtualMethod    ForEach,         POINTER, QWORD, QWORD
VirtualMethod    ForEachRev,      POINTER, QWORD, QWORD
DynamicMethod    GetItem,         POB_Stream, PDESER_INFO
VirtualMethod    IndexOf,         POINTER
RedefineMethod   Init,            POINTER, DWORD, DWORD, DWORD
VirtualMethod    Insert,          POINTER
VirtualMethod    InsertAt,        DWORD, POINTER
VirtualMethod    ItemAt,          DWORD
VirtualMethod    LastThat,        POINTER, QWORD, QWORD
VirtualMethod    LastThatNot,     POINTER, QWORD, QWORD
RedefineMethod   Load,            POB_Stream, PDESER_INFO
VirtualMethod    PutAt,           DWORD, POINTER
DynamicMethod    PutItem,         POB_Stream, POINTER
RedefineMethod   Serialize
DynamicMethod    SerializeItem,   POINTER
RedefineMethod   Store,           POB_Stream
Private
StaticMethod     SetLimit,        DWORD


DefineVariable   pItems,          POINTER,      NULL
DefineVariable   dCount,          DWORD,        0
DefineVariable   dLimit,          DWORD,        0
DefineVariable   dDelta,          DWORD,        0
DefineVariable   dMaxCapacity,    DWORD,        0
DefineVariable   ObjLock,         ObjectLock,   {}

ObjectEnd


It can be observed on the first line, started by the keyword "Object", 3 elements, the name of the object class (Collection), its unique ID and finally its ancestor. Deriving "Collection" from "Streamable" means, that it inherits all capabilities of a "Streamable" object. This way, we can store the whole content of the "Collection" on an arbitray "Stream". In most cases this is a disk file (DiskStream) but it can be a memory chunk or whatever is desired.


After the first definition line follow the methods. These define the procedural capabilities of this object. I'll not comment each one, since the names are self-explanatory. You'll notice the different method types supported by the ObjAsm64 framework.

Finally, after the method definitions follow the internal variables that are managed by "Collection" and their initial values when created.
If very high performance is an issue, other objects should be used like Linked-Lists or Red-Black-Trees.

I hope this post give you a brief insight to this important OO assembler element.

Best regards, Biterider


HSE

Fantastic Biterider!!

You are publishing the ObjAsm`s book by parts!  :t

I will expect  the part of "Red-Black-Trees" :biggrin:

Equations in Assembly: SmplMath

Biterider

Hi
I started to work on the Red-Black Tree. I have 80% ported at the moment, but before I release it, I want to test all methods and check the performance against other algorithms. In the meanwhile you can check some places on the web like:


http://www.cs.iupui.edu/~xkzou/teaching/CS580/Red-black_trees.ppt
http://en.wikipedia.org/wiki/Red-black_tree
http://en.wikipedia.org/wiki/Tree_traversal
http://en.wikipedia.org/wiki/Threaded_binary_tree
http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx


There are so many other binary trees like AA-Trees, AVL-Trees, B-Trees, etc. to mention only a few.
Biterider

HSE

It's just a funny name, I'm not using complex data structures  :t

But just yesterday I remember a more practical issue: in Debug System the colors are hardcoded. I change everithing to white foreground and black background in the dark machine (not so nice).

For now I only will read the book, because very infrequently I use a 64 bit machine. But it's very good to know that at some point I can update my ObjAsm32 code to ObjAsm64. Thanks.


Equations in Assembly: SmplMath

Biterider

Hi
One of the interesting features about ObjAsm is the build-in ability to emit information for debugging purposes. There are many other ways to achieve this using other tools or OS APIs. The advantage of using the ObjAsm approach is that it is completely transparent and can be simply modified to any new circumstance. The most used information destination on desktops is an application called "DebugCenter". In this case, the debugee communicates with "DebugCenter" using an OS IPC method. The current implementation can transmit colorized text using the known emphasis attributes and bitmaps.

The described feature is not intended as an alternative to an application debugger. It is intended as a complement to get rapidly information about the logic of the debugee and other information of interest.

Additionally, to the output to "DebugCenter", alternative destinations are implemented for a console window or a log file. In these cases, only plain text can be emitted.

If this feature is required, the debugged application needs to switch it on. These way, the macros that emit the requested information are expanded. Since the release version of the application doesn't need to emit the information, the switch can be simply be turned off.
For this purpose, the application needs to include the following line after the general Setup of the ObjAsm framework:

SysSetup OOP, WINDOWS, WIDE_STRING, DEBUG(WND)


SysSetup may contain several switches, but the one we are interested in is DEBUG(WND). This expression activates the Debugging output to WND. In this context, WND means "DebugCenter", CON a console window and LOG a log-file.

All Debugging macros are located in the Debug.inc file. A short view at the file beginning shows a list of all available macros. They are designed to emit warnings, numbers in different formats, memory dumps, bitmaps, API error descriptions, windows messages, GUID numbers, etc. Interesting to know is, that these macros preserve the complete state of the CPU. That means that they are absolutely transparent to the CPU execution.
At the moment, due to some limitations in the x64 world, not all features of ObjAsm32 are implemented. One of the most notorious is the method performance tracking.

The build process can be triggered for release of debug targets. For this purpose, each project comes with 2 batch files. The switch that controls the debug output is located in the "bin\OPT_ASM_RLS.txt file" (-DISABLE_DEBUG).

Best regards, Biterider

Biterider

Hi
A Red-Black Tree is a not perfect self-balancing binary tree. Each node of the binary tree has an attribute that is often interpreted as the color (red or black). These colors are used to ensure the tree remains approximately balanced during insertions and deletions.
Red-Black trees offer worst-case guarantees for insertion time, deletion time, and search time. In big O notation that would be O(log n) for these 3 operations. This make them valuable in time-sensitive applications such as real-time applications.
https://en.wikipedia.org/wiki/Red%E2%80%93black_tree

The ObjAsm64 object implementation is based on the following paper
http://www.cs.iupui.edu/~xkzou/teaching/CS580/Red-black_trees.ppt


Additional functionality for serialization is also provided without adding additional complexity.
The following DebugCenter output shows the structure of a Red-Black Tree of 16 elements.

QuoteObject at address 0000000202C1E700 => Key = 3
  Object at address 0000000202C1E4D0 => Key = 1
    Object at address 0000000202C1E840 => Key = 0
      Null
      Null
    Object at address 0000000202C1EAC0 => Key = 2
      Null
      Null
  Object at address 0000000202C1E890 => Key = 7
    Object at address 0000000202C1E8E0 => Key = 5
      Object at address 0000000202C1E430 => Key = 4
        Null
        Null
      Object at address 0000000202C1E980 => Key = 6
        Null
        Null
    Object at address 0000000202C1E660 => Key = 11
      Object at address 0000000202C1E390 => Key = 9
        Object at address 0000000202C1E610 => Key = 8
          Null
          Null
        Object at address 0000000202C1EA20 => Key = 10
          Null
          Null
      Object at address 0000000202C1E3E0 => Key = 13
        Object at address 0000000202C1E520 => Key = 12
          Null
          Null
        Object at address 0000000202C245A0 => Key = 14
          Null
          Object at address 0000000202C24140 => Key = 15
            Null
            Null

There are many ways to use a Red-Black Tree. In combination with a host object, a node (RBT_NODE ) must be added as variable. The controlling object (RedBlackTree) provides the functionality to insert, search, iterate, test and delete those objects that are linked together using the RBT_NODEs.
The current interface looks like


Object RedBlackTree, RedBlackTreeID, Streamable
  DynamicMethod     Compare,        POINTER, POINTER
  VirtualMethod     Delete,         POINTER
  VirtualMethod     DeleteAll
  VirtualMethod     Dispose,        POINTER
  VirtualMethod     DisposeAll
  VirtualMethod     Find,           POINTER
  VirtualMethod     FirstThat,      POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters
  VirtualMethod     FirstThatNot,   POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters
  VirtualMethod     ForEach,        POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters
  VirtualMethod     ForEachRev,     POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters
  VirtualMethod     GetFirst
  VirtualMethod     GetLast
  VirtualMethod     GetNext,        POINTER
  VirtualMethod     GetPrev,        POINTER
  RedefineMethod    Init,           POINTER, DWORD
  VirtualMethod     Insert,         POINTER
  VirtualMethod     LastThat,       POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters
  VirtualMethod     LastThatNot,    POINTER, QWORD, QWORD   ;-> Proc, 2x Parameters

  DynamicMethod     GetItem,        POB_Stream          ;-> Stream
  DynamicMethod     PutItem,        POB_Stream, POINTER ;-> Stream, -> Item
  RedefineMethod    Load,           POB_Stream, POINTER ;-> Stream, -> Owner
  RedefineMethod    Store,          POB_Stream          ;-> Stream

  DefineVariable    qNodeOffset,    QWORD,        0     ;Offset from host object to node
  DefineVariable    pRootNode,      PRBT_NODE,    NULL
  DefineVariable    dCount,         DWORD,        0

  DefineVariable    ObjLock,        OBJECT_LOCK,  {}    ;Locking structure for multithreaded access

ObjectEnd


It can be seen, that the object derives from Streamable, inheriting all necessary capabilities to save its content onto any type of stream.

Attached is the source file for those that want to look into the x64 code.


Biterider

Biterider


Hi
Over the time applications became more complex and their main interface also grew larger. They used tabbed toolbars and filled them with many graphical buttons and other control elements.
In 2007 Microsoft began to introduce a form of modular ribbon in which controls are grouped by functionality. Such ribbons use tabs to expose various sets of controls, eliminating the need for many parallel toolbars. Contextual tabs are tabs that are only displayed when user needs them.
For a complete historical description, read on here:


https://en.wikipedia.org/wiki/Ribbon_(computing)
https://msdn.microsoft.com/en-us/library/windows/desktop/dd371191(v=vs.85).aspx


Last week, I translated some Microsoft Ribbon Framework C files to incorporate this functionality into assembly applications. The end result is an x64 assembly ribbon application that can be seen in the attachment.


Basically, you need to establish communication between the Ribbon framework and the application using some COM interfaces. On the application side, you have to implement the IUIApplication COM interface and CoCreateInstance the Ribbon Framework according to these instructions:


https://msdn.microsoft.com/en-us/library/windows/desktop/dd316924(v=vs.85).aspx


All GUI controls created communicate through a COM application interface called IUICommandHandler. ObjAsm64 creates a COM component and interface for each control and adds them to the hosting component.


At this point, I have to warn of a Ribbon implementation issue that took some time to understand and find the right tools for. It is the transparency of the images used for the visual interface. Win7 handles it differently than Win8 and Win10. The former only understands BMP files in A8R8G8B8 format, while the other one can handle PNG files without problems.


https://msdn.microsoft.com/en-us/library/windows/desktop/dd316921(v=vs.85).aspx


Using a suitable image saving (BMP) tool in 32-bit ARGB format will save many headaches. I use the IcoFX freeware version to export these pictures in this format.
The ObjAsm64 implementation is extremely easy. If you insert the following code after the window creation code, the Ribbon framework and the connection between the ribbon controls and the application-side interface will automatically be started.

    mov [rsi].pUIApplication, $New(UIApplication)
    OCall rax::UIApplication.Init, rsi, [rsi].hWnd, $OfsCStrW("APPLICATION_RIBBON")



Shutdown is done by calling the following code
    OCall [rsi].pUIApplication::UIApplication.Release


I hope this will inspire someone to take a look into ribbons to modernize the GUI of assembly applications.  8)


Best regards,
Biterider


jj2007

This looks beautiful, biterider :t

(but functionality-wise, I hate the ribbon interface... it just looks good but you spend too much time guessing where the function you need is hidden; same for tab controls)

habran

Hi Biterider :biggrin:
ObjAsm64 looks very impressive and promising 8) :t
QuoteThe last weeks I started to work on the ObjAsm framework to support x64 using UASM.
It is a work in progress, since not all features are implemented yet. I choose using UASM, because it offers at least the same flexibility we are used to from ML 6.15 for x86.
I appreciate your proclivities for your choice 8)

I am to busy with the UASM to be able to study your libraries, however, it sounds very promising.

You have mentioned :
QuoteSome prebuild objects like Collections, Linked Lists, Streams, Controls, Applications, etc.
·        Precompiled objects
I sounds intersting, which gives me an idea:
It would be great if you could create some simple starting base for different types of APS, which would have precompiled headers in it so that we can just build on it, like a foundation for the building

I can see by number of downloads that a lot of people is interested in your work but they are to shy to give some feedback ::)

It would be maybe good idea to give some more source code examples, so that people get idea how it can be utilised. It would probably extract ObjAsm64 from Rarely Used Projects

Keep up good work

Best Regards


Cod-Father

Biterider

Hi Habran
Thanks for your replay.   :biggrin:
ObjAsm64 is basically a rework of ObjAsm32 for x64. The main work is done, but some features like "Performance Tracking" and "Buffer Security Check" (VS /gs switch) are still missing. The reason is mainly the x64 calling convention. I guess I'll need some help from the UASM team with the necessary Prolog and Epilog coding   8)

I'm thinking about writing a PDF describing the ObjAsm64 basics. Many things are already described in the source code, but the overview should also be written. At the moment I have 6 examples, but they do not cover all the basics. I think, I should revise them first.

Biterider

Biterider

#12
Hi
ObjAsm64 is a single inheritance OOP implementation for x64 assembler code. It is based on macros and therefore needs a MASM-compatible assembler such as UASM.
The ObjAsm64 package contains objects, libraries, include files and samples to build a framework that enables the coder to quickly create complete applications.

The OOP core is in the Objects.inc file. There are several macros that only serve to maintain lists of methods, variables, and so on, that are used to compile the code. This seems complicated, but the idea behind it is very simple. We want to cluster data and code together in form of a structure called object. Behind the scenes are a second structure called "object metadata" (OMD). This data holds the information of the object class, the "object template", the "virtual tables" and finally the "event translation table" (ETT).

The object template is an in-memory structure that is used to copy the initial data to a newly created object, the object instance. The object template can be seen as the source of all derived objects.
ObjAsm64 understands 2 virtual tables. The first is called Interface Method Table (IMT) and the second simply Virtual Method Table (VMT). Both together are called Dual Method Table (DMT). The first is a regular table, as known from other implementations, but the second is immediately before the first and therefore has negative offsets from the common entry point. This implementation with positive and negative offsets in the DMT allows the separation of public interfaces such as COM methods from object private virtual methods.

Object metadata (OMD) chain and layout:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
                          Object Metadata (OMD) #1                #2    ...    #n
  ??1stOMD   ——>   (+00h) POINTER to next OMD sibling      ——>    ...  ——> NULL = last OMD
                   (+08h) sizeof(TPL) (DWORD)                     ...          ...
                   (+0Dh) Alignment filler (DWORD = 0)            ...          ...
                   (+10h) Object Template (TPL)                   ...          ...
                   (+vvh) Object Dual Method Table (DMT)          ...          ...
                   (+xxh) Object class ID (DWORD)                 ...          ...
                   (+yyh) Ancestor class ID (DWORD)               ...          ...
  ——> ETT start:   (+zzh) # of following ??EventEntry (DWORD)     ...          ...
|    Event               ??EventEntry #1                         ...          ...
|    Translation         ??EventEntry #2                         ...          ...
|    Table               ??EventEntry #3                         ...          ...
|                        ...                                     ...          ...
|
|  Object structures:
|  ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|  Object Template (TPL)
|    (+00h) POINTER to the Dual Method Table (DMT) —————————
|    (+08h) Variables and dynamic methods                   |
|          ...                                              |
|  Dual Method Table (DMT)                                  |  Offset
|    (-20h) Virtual method 3     (...)                      |    -
|    (-18h) Virtual method 2     (...)                      |    |
|    (-10h) Virtual method 1     (Done destructor)          |    |  Virtual Method Table (VMT)
  ——— (-08h) POINTER to Event Translation Table (ETT)        |    |
ENTRY (+00h) Interface method 1   (QueryInterface method) <——'    0 Dual Method Table (DMT)
      (+08h) Interface method 2   (AddRef method)                 |
      (+10h) Interface method 3   (Release method)                |  Interface Method Table (IMT)
             ...                                                  |
                                                                  +


As can be seen, all new instances of an object share the same DMT. This means that calling a virtual method from each instance uses the same code. There are situations where customization of a single instance is required. For this case, dynamic methods were created. The execution pointer is now stored not in the DMT but in the object instance itself. ObjAsm64 handles this complexity transparently for the coder. The definition of the method type is done with keywords in the description of the objects.

Object Sample, SampleID, Primer
  VirtualMethod     Method1
  DynamicMethod     Method2
ObjectEnd


A regular object definition contains an ID to identify the instance at runtime and the name of its ancestor.
If we remember, an object is nothing more than a structure. This structure can be extended by additional fields to create a new structure with more information. The ancestor plays the role of the original structure and the object definition the way this structure needs to be expanded. The same applies to the DMT. In this way, the complete data and functions are passed to the new object.

The object data is defined with the keyword DefineVariable, followed by a name, a type and an initial value.

Object Sample, SampleID, Primer
  VirtualMethod     Method1
  DynamicMethod     Method2

  DefineVariable    MyVar,     DWORD,   123
ObjectEnd


Since objects are structures, complete other objects can be embedded like variables. ObjAsm64 does that with the keyword Embed:

Object Sample, SampleID, Primer
  VirtualMethod     Method1
  DynamicMethod     Method2

  DefineVariable    MyVar,     DWORD,   123
  Embed             MyObject   
ObjectEnd


In this example, MyObject must be previously defined, so that the assembler knows about it.

The method invocation is done using a macro called OCall. It has the following syntax:

OCall <instance>::<object name>.<method name>, <argument list>

OCall detects instance pointers as well as local names. In this case, it performs the necessary transformations for the method call. The target is the method associated with the object, which is declared as follows:

Method <object name>.<method name>, <options>, <argument list>
  SetObject <register>
  ...
MethodEnd


To save typing work, the passed instance pointer called pSelf is hidden by the method macro. Its type matches the type of the object. Most of the cases, a register is required to access an object member. The job of SetObject is to load this register with the value of pSelf and execute an the ASSUME directive.
MethodEnd restores all ASSUME directives and perform a ret instruction. A macro local label called EOM (end of method) is included to perform a clean method exit from elsewhere in the method code.

It is often necessary to call the code of the ancestor object, in particular when an object instance is initialized. In this case ObjAsm64 calls an ancestor using the ancestors DMT or template using using ACall:

ACall <instance>::<object name>.<method name>, <argument list>

A complete bypass of the DMT is also possible using a direct call (DCall) with exactly the same syntax.
ObjAsm64 also knows a sort of invocation for interfaces like those used by COM or ObjAsm64 itself called ICall. The syntax is also identical to OCall, ACall and DCall.

ICall <instance>::<object name>.<method name>, <argument list>

In a multithread environment, sometimes it is necessary grand exclusive access to a specific execution path to only one thread. ObjAsm64 requires 2 elements for this type of synchronization: an opaque object variable called OBJECT_LOCK and a special calling mechanism called xOCall or xACall. The prepended "x" stands for exclusive.

Regards, Biterider

Biterider

Hi
There is an important feature hidden behind the SysInit and SysDone macros, the run-time initialization and shutdown.
In some cases, objects may require a kind of initial setup before we start working with them. In addition to some basic tasks, such as application heap management, the SysInit macro goes through all declared object templates and calls a static method called Startup. Objects that do not define this method are simply skipped.
For example, you are in the situation where you have many instances of a MyWindow object in your application, but you typically register the window class only once. In this case, the MyWindow.Startup method is called at the very beginning when SysInit is called to perform the registration. The method must be declared in the object definition and has no arguments. The same applies to the Shutdown method.

Object MyWindow, MyWindowID, WinPrimer
StaticMethod      Startup
StaticMethod      Shutdown
...
ObjectEnd

...

Method MyWindow.Startup
local WC:WNDCLASSEX

mov WC.cbSize, sizeof(WNDCLASSEX)
...
invoke RegisterClassEx, addr WC
MethodEnd


When the application shuts down, the reverse scenario may occur. In this case, SysDone simply calls MyWindow.Shutdown.
At this point, you're probably wondering which object instance we're working on. The answer, as mentioned above, is the object template. This fact is important because it has consequences. Only objects created after the SysInit call are initialized properly!

Regards, Biterider

Biterider

#14
Hi
I am often in the situation that I have to visualize or export data. In most cases, the tool of my choice is EXCEL.
To facilitate the EXCEL programming, the way to go is using COM. EXCEL uses various standard interfaces and very intensively dispatch interfaces. I used the EXCEL version 10.0 definitions and translated the core elements with ComView. The rest was manually polished and put into Excel.inc and Excelc.inc.
For convenience, I created an object called ExcelHost that handles the most common tasks, such as opening, closing, data exchange, charting, and so on. This object can easily be extended to handle formulas, macros, pivot tables, and so on. It looks this way:

Object ExcelHost, ExcelHostID, Primer
  StaticMethod      CloseBook,                POINTER
  StaticMethod      DeleteSheet,              POINTER
  RedefineMethod    Done
  StaticMethod      GetCell,                  POINTER, DWORD, DWORD, POINTER, DWORD
  StaticMethod      GetRange,                 POINTER, BSTR
  StaticMethod      GetSheet,                 POINTER, BSTR
  StaticMethod      GetSheetName,             POINTER
  RedefineMethod    Init,                     POINTER
  StaticMethod      NewBook
  StaticMethod      NewChart,                 DWORD, DWORD, BSTR
  StaticMethod      NewSheet,                 POINTER, BSTR
  StaticMethod      Open,                     BSTR
  StaticMethod      SaveAs,                   POINTER, BSTR
  StaticMethod      SelectRange,              POINTER
  StaticMethod      SetCell,                  POINTER, DWORD, DWORD, BSTR
  StaticMethod      SetColumnWidth,           POINTER, BSTR, REAL4

  StaticMethod      GetBorder,                POINTER
  StaticMethod      SetBorderAttr,            POINTER, DWORD, DWORD, DWORD

  StaticMethod      GetFont,                  POINTER
  StaticMethod      SetFontAttr,              POINTER, BSTR, DWORD, DWORD, DWORD, DWORD

  StaticMethod      GetInterior,              POINTER
  StaticMethod      SetInteriorAttr,          POINTER, DWORD, DWORD, DWORD

  StaticMethod      SetChartData,             POINTER, POINTER, DWORD
  StaticMethod      HasChartTitle,            POINTER, DWORD
  StaticMethod      GetChartTitle,            POINTER
  StaticMethod      SetChartTitleText,        POINTER, BSTR
  StaticMethod      GetChartAxis,             POINTER, DWORD, DWORD
  StaticMethod      SetChartAxisAttr,         POINTER, DWORD, DWORD, DWORD, DWORD
  StaticMethod      SetChartAxisValues,       POINTER, DWORD, REAL8, DWORD, REAL8
  StaticMethod      SetChartAxisTicks,        POINTER, DWORD, DWORD, REAL8, DWORD, DWORD, REAL8
  StaticMethod      SetChartAxisGridlines,    POINTER, DWORD, DWORD, DWORD, DWORD, DWORD
  StaticMethod      GetChartLegend,           POINTER
  StaticMethod      GetChartArea,             POINTER
  StaticMethod      GetChartPlotArea,         POINTER
  StaticMethod      GetChartSeries,           POINTER, DWORD
  StaticMethod      SetChartSeriesAttr,       POINTER, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD
  StaticMethod      SetChartSeriesData,       POINTER, BSTR, POINTER, POINTER

  StaticMethod      SetRangeAlignHor,         POINTER, DWORD
  StaticMethod      SetRangeAlignVer,         POINTER, DWORD
  StaticMethod      GetRangeBorder,           POINTER, DWORD
  StaticMethod      GetRangeArray,            POINTER, POINTER
  StaticMethod      CreateArray,              DWORD, DWORD, POINTER

  StaticMethod      SetRowHeight,             POINTER, BSTR, REAL4
  StaticMethod      SetSavedFlag,             POINTER, DWORD
  StaticMethod      SetSheetName,             POINTER, BSTR
  StaticMethod      SetVisible,               DWORD
  StaticMethod      Quit

  DefineVariable    pIExcelApp,               POINTER,  NULL
ObjectEnd


As you can see above, the strings are BStrings as used in COM automation. ObjAsm provides all the necessary tools in the ObjMem64 library and BString.inc macros to handle these types of strings.
Attached is an executable that shows some of the possibilities using ExcelHost. There, you will also find the Excel interface definitions.
As a side note, I had to change the name of the interface definition macros to avoid conflict with other macros coming from other packages. The new format looks like this:


COM_INTERFACE_BEG IExcelFont, IDispatch, <0002084D-0001-0000-C000-000000000046>
COM_MTD_STD  get_Application, ptr ptr Application
...
COM_INTERFACE_END


The start of the interface is signaled with the macro COM_INTERFACE_BEG. It requires as argument a name, a predecessor interface and a GUID. It is convenient to include this last one here to have all relevant information together. The following lines specify the methods contained in the order of occurrence. These can be standard (COM_MTD_STD) or dispatch methods (COM_MTD_DSP). The end of the interface definition is signaled with the macro COM_INTERFACE_END.
If you want to use the interface definitions for your own implementation, you can easily change the above macros. It should be a simple task for a MASM coder   :biggrin:

Regards, Biterider