Thursday, November 22, 2007

[Ada (GNAT/GPL)] Creating DLLs for VB6

As promised, the GNAT/GPL code. Based on Roger Pearse's The Noddy Guide to using ADA code with Visual Basic.

How I ended up with the names api.ads, api.adb and api.def is an artefact from something I was reading. [This space set aside for an attribution.]

First up, api.ads, which declares the functions and exports them.
  • function Factorial, which accepts a C.int and returns a C.int
  • procedure Mangle, which accepts a Win32.LPWSTR and attempts the same dangerous stuff that Bob6 does in the ObjectAda version. Still working on this one.
  • function Pattern, which returns a Win32.LPWSTR
  • procedures Initialize_API, and Finalize_API, which I understand are mandatory. (If someone knows better, please tell me.)


Next, api.adb, where the declarations are explained.

Mangle replaces the incoming string with something of its own. If the incoming string is larger or the same size then everything's more or less okay. (Less in the latter case, but at least it doesn't crash.) However, if the incoming string is shorter, VB truncates up to the length it knows about, and who knows what damage we've done with whatever gets overwritten by the rest of foo.

Pattern returns a pointer to the string data. Not knowing a lot about Ada, I don't know if the contents of foo will still be there by the time VB looks it and reads out.


api.def lists the symbols exported, and is needed by gnatdll.


Now, pulling it all together requires some handwaving on the commandline.


The output from a run of these is as follows:


Now the VB code. Take note of a few things:
  • Exporting as DLL generates decorated names, but gnatdll was able to resolve the decorated ones with the undecorated ones specified in api.def
  • For reasons I remember reading somewhere, initialize_api and finalize_api are mandatory, and must be the first and last calls to the DLL
  • Seeing as woof woof woof woof is longer than foo man chew, s ends up containing foo man chew woof


Next stop is to get this working with "GNAT/GCC MS-Windows MinGW 4.2.1 R0". I would prefer to be working under the GMGPL.


© Copyright Bruce M. Axtens., 2007

Tuesday, November 20, 2007

[Ada (ObjectAda 7.2.2)] Creating VB6 DLLs

Creating DLLs for use by VB6 seems to be somewhat of a dark art. From what Roger Pearse, in his The Noddy Guide to using ADA code with Visual Basic says, it doesn't appear to be something easily achieved.

So far I've achieved it, to a certain extent, with ObjectAda and GNAT/GPL. The code for the ObjectAda implementation is below. I'll post the GNAT/GPL stuff in the next couple of days, God willing.

BO_DLib.adb, BO_D.adb and BO_D.ads are all based, albeit rather loosely, on sample files in winapi\samples\petzold\ch19\edrlib\

First up, BO_DLib.adb



Next, the spec file, BO_D.ads

There are six routines:
  • procedure Bob1 calls dobox to show a messagebox.
  • function Bob2 returns a long value, 1.
  • function Bob3 receives a long and adds 21 to it.
  • procedure Bob4 receives a long pointer to a string and passes it to dobox for display.
    I can pass Unicode to it and have it rendered appropriately.
  • function Bob5 receives a long pointer to a string and returns a long being the length of the string.
  • function Bob6 receives a long pointer to a string and catenates a string to it.
    "Danger, Will Robinson!" ... this is not how to do it and VB complains bitterly.
Okay, there are seven routines, but dobox isn't exported. It takes a pointer to a wide string and passes it to Win32.Winuser.MessageBoxW. I got dobox from a sample file as well.



And, finally, BO_D.adb, where the definitions given in BO_D are fleshed out.



Now the VB code. Take note of a few things:
  • I declared the functions and procedures as DLL_Stdcall in BO_D.ads so the routines come in decorated, thus the use of Alias in the Declare line. I used Microsoft's Dependency Walker to discover to what extent the names had been mangled.
  • A reference to SCRRUN.DLL was added to the project, making possible the use of the FileSystemObject.
  • Bob6 barges past the limit set for the string by VB, so things get a bit unstable. I'm still working through how to pass strings back.


By the way, if you think my code sucks, say so. I'm a total newb when it comes to Ada. Critiques are always welcome. King Solomon said, "The wise person accepts instructions." and also "Better is open rebuke than hidden love."


© Copyright Bruce M. Axtens., 2007

Tuesday, October 23, 2007

[Protium] Splitting

Here's a short script for splitting a file. The file in this case is the perl language data file from the PLEAC website. pleac_perl.data contains sections marked with "# ^^PLEAC^^_" followed by a number. The section applies until the next section is marked. The script splits each section out of pleac_perl.data into pleac_perl_number.p. I'm working through these files and re-expressing the intent of the perl code in Protium.

The code may be described as follows:
  1. Define a work area, or alias, for the data file, calling it 'pleac'.
  2. Open the text file within that work area, using define-file-lit.
  3. Start a loop which iterates through an enumeration of the lines of data in the work area.
  4. Let a variable contain the data in the current line of the work area.
  5. Test whether the regular expression works for the current line.
  6. If it does work, let a variable contain the number found, ...
  7. ... turn off any output redirection, ...
  8. ... and redirect output to the file 'pleac_perl_' + the number found (in the same directory as the script).
  9. End of the if.
  10. Output the contents of the line.
  11. End of the iteration.
Simple ... and way powerful!

© Copyright Bruce M. Axtens, 2007

Saturday, September 08, 2007

[Protium] 'Assert' as a User-Defined Syllable (UDS)

From time to time, during development, it helps to have an assert. That is, a means of checking whether you got the answer you were expecting, but without having to write lots of repetitive code in the process. To that end, therefore, I've come up with a UDS, an user defined syllable, which implements the concept (and demonstrates other Protium functionality as well.)

For the sake of clarity, I've put each syllable, or "opcode", in title case. This is not something that must be done; Protium cares not what case or mix of cases the instructions are in.
A UDS is 'defined', thus the DEF at the beginning. An UDS has 3 parameters: the syllable itself, then the kind of UDS (more about that later), and then the Protium code which is processed each time the syllable is used. In this case, the syllable is ASR, the type is '__Transformer' and the code starts with <@ SAO> (more about SAO later, too).

Parameters may be passed to UDSes, and retrieved using PAR. In this case, the variable lhs is given the value of the first parameter, and the variable rhs the value of the second.

Next comes the test which forms the basis of an assert: does what is contained in lhs equal what is contained in rhs? The fourth line's opcodes implement this test: if not exact-match variable variable literal, with the arguments lhs, rhs and then another Protium instruction which is only evaluated if the test for exact-match fails.

If lhs does not match rhs, an EKM (Expand Macro Key And Memory) of the literal string "Assertion error: '&lhs;' <> '&rhs;'" is performed. lhs and rhs are bracketed by ampersand and comma, with the result that these symbols are replaced with the values of the variables themselves. The result is stored in the RES (the result) of the UDS, which is handed back to the calling code. Next comes a block wrapped in IGN. This is an artefact from the development of ASR. Code inside an IGN is ignored, that is, not executed. IGNs are predominantly used for documentation but can just as easily be used to isolate parts of the code.
Here are two invocations of the ASR syllable. The first generates nothing because the actioned RMD, the reverse-mid, actually does convert "Once a jolly swagman camped by a billabong" into "Once a jolly squatter camped by a billabong". The second invocation gives the error message because there's no way that that reverse-mid is going to be able to produce "all your base are belong to us".

Now SAO, aside from being the name of an Arnott's biscuit, also stands for "Suppress All Output". Usually text outside the <@> and </@> of a Protium instruction is echoed to the relevant transput (read input-output device). SAO suppresses that echoing. This explains why you don't see 'lhs=' and 'rhs=' each time ASR is invoked. SAO also suppresses everything output by SAY.

Regarding __Transformer, every syllable opcode belongs to a particular group of syllables and each group has certain specific behaviours. Other groups include __Modifier, __Alternator, __Evaluator and __Locator. Read the friendly manual.

Finally, a word about testing. It was the developer's original design to separate testing from branching, and it was due to pressure from the Protium user community which forced the merging of the two into the form seen in most other programming languages. According to the original design, the test and branch code should have looked like this:
Both ways of doing it work. I'm starting to come round to the idea that the original design is the better one, especially seeing that Protium supports ternary logic (true, false, unknown). More about that some other time.

This article can also be found at
Isotopes of Hydrogen on the Protium Blue Forum.

© Copyright Bruce M. Axtens, 2007

Friday, August 31, 2007

[Protium] Templating

Finally, after much talk, here's some action on the Protium front. This the first posting in the 'Isotopes of Hydrogen' series, on the subject of Templating. IoH is housed at the Protium Blue Forum.

If you don't want to go through the process of forum registration, the article is reproduced below.

We're implementing a SOAP interface to Google's AdWords. There are a number of services and subroutines. The following code was developed to speed up the implementation by taking the service and subroutines names and turning them into VB6 subs.
First there's the definition of template. Note that some parts of the template are Visual BASIC and some are something else: an ampersand, a word and a semicolon. These will be replaced with the text in the following list.
params contains, as a first item, the name of the service. After it are all the routines germane to that service. I got these by copying and pasting from Google's AdWords API website.
This bit takes the variable params, and converts it to a list, splitting on newlines. CND means 'construct delimited'. The list is called L (really original, I know.)
Next we iterate by enumeration of the L list. Here we see one of the special qualifiers that can be used with iteration, INI, that only fires on the first pass through the iteration and is ignored otherwise. In this case, its 'payload' is to define a macro where Service contains the current (in this case, the first) element of the L list.

ONG means 'ongoing' and fires on the second and subsequent iterations. The payload is in two parts. The first is to define another macro, Function, with the value of the current element of L. The second is to evaluate template, using EKM, substituting &Service; and &Function; with the values stored in the Service and Function macros.

By using INI, Service gets set only once. ONG ensures that Function will never contain the name of the service, and always contain the current name of the function.

An abbreviated sample of the output is below. There are 11 services and over 40 subs in total. Granted, there's still quite a bit of work to make these subs useful, but a lot of the hack work has been done by the computer, which is what it's there for.
© Copyright Bruce M. Axtens, 2007

Monday, May 07, 2007

[Visual Basic 6] Boost again, but as a binary

As nice as the VBScript version of BOOST is, some people prefer a compiled binary. So, here's the VB6 version.

But first, credit where credit is due:
*
Ultimate Packer for eXecutables which compresses binaries;
*
Euphoria programming language website for the SETSUBSYS tool which I use to turn a GUI applications into a console ones;
*
Experts Exchange for their ParseCommandLineValue function; and
*
vb.mvps.org for their sample on how to make console applications

Okay, now to the code. The algorithm is very similar to the VBScript project, but there are some new things.

First the constants:


Here are two functions vital to making the application function appropriately in a command line environment. The first discovers the handle for StdOut. The second writes to a file handle, in this case the handle for StdOut.

After the function declarations is a user-defined wrapper. Interesting how the output of the WriteFile function is transmitted to the return value of the wrapper (the last argument in the call is the name of the wrapper function -- I'd never seen that before.)


This is the SetPriority function pulled straight out of the VBScript project. Notice I haven't even been polite enough to VB6 to specify sProcess As String and nPriority As Integer. I haven't typed any of the variables local to the function either. It doesn't matter: VB6 types them all as Variant and takes care of my carelessness (and I have put them in since.)


Next comes the Experts Exchange code for parsing the command line.


Now the Main. For ease of access to the relevant values for the SetPriority function, I've used a Collection. I could have used VBScript's Dictionary (by adding a reference to SCRRUN.DLL in the Projects menu) but the Collection works well enough.


Now we parse the commandline and output a message about syntax if things aren't correctly specified there.


Assuming that the commandline is okay, we then attempt to figure out the runlevel value from the user-supplied specification, and show an appropriate error if it doesn't make sense.


And, finally, where it is all made to happen. If everything's set up right and there is in fact a process running that matches what's stored in sProcess, then it gets boosted and the user is informed. If there's no match, the message says that the process wasn't boosted.


Having compiled the code to an .EXE, I used the setsubsys tool to change the binary from a GUI app to a console app


I also compressed it using UPX,
taking a 24576 byte application and leaving me with an 8192 byte one.

If anyone's interested in downloading the BOOST binary (which now contains a KILL_PROCESS 'level'), please leave a comment to that effect and I'll put up a download link.

By the way, if you think my code sucks, say so. Critiques are always welcome. King Solomon said, "The wise person accepts instructions." and also "Better is open rebuke than hidden love."


Friday, March 16, 2007

[VBScript] Boost - changing process priority using WMI

I have little sh script on my iBook which changes the priority of a given process so that the OS services it more frequently, giving the impression of faster execution. Below is a re-implementation in VBScript of a similar tool for Windows. First a few constants and the arrays that handle the commandline options.
Next, the real meat of this tool: the Windows Management Interface (WMI) call which takes a string and a numeric defining the process name and the priority level.
Next a few less inspiring routines: IIF (available in VB but not in VBScript), ArrayOffset, and HelpText.
Finally the main routine, which uses Named and Unnamed Arguments to handle command line parameters. The name of the process is pulled out of the command line using an Unnamed Argument, and the text representation of the priority is pulled out using a Named Argument ("L"). If the priority is acceptable the name and priority are passed to the SetPriority routine.
A further refinement of this tool might be to provide for one other possibility for /L: 'KILL' or 'TERMINATE'. By way of comparison here's the original sh script.

Tuesday, February 27, 2007

[Observation] A Programmer's Bill of Rights

A Programmer's Bill of Rights

by Diarmuid J. Pigott


  • To be able to instruct a computer in their own native language
    • Have variables, field names, and attributes in their own native language
    • Have the programming lexemes semantically significant in their own language
    • Have programmatic components interrelated in a manner significant in their own language
    • Not to have to learn a foreign language to get by
  • To be able to share their work with other people without loss of expressivity or meaning

  • © Copyright Diarmuid J. Pigott, 2007

    Thursday, November 23, 2006

    [VBScript] Configure

    Below is retake on the Include subroutine which heads up the vast majority of my scripts. This incarnation puts a wrapper around Include and is called, for want of a better word, Configure. This subroutine takes no parameters at all. Rather, it builds up a filename based on WScript.ScriptFullName with ".cfg" tagged on, reads it in and then hands it over to ExecuteGlobal. This means that the .cfg file must contain functioning VBScript code.

    Provided the .cfg sits side-by-side with the .vbs, the .vbs should work. And if you change locations, change the .cfg code. If the .cfg can't be found, you get an error message. I haven't put in any error trapping yet.

    Had fun with "With"/"End With" on this one.

    So in the .vbs we have
    and in the .cfg we have (for example)

    Saturday, November 11, 2006

    [Observation] freshmeat, no. CodePlex, yes?

    Seems that freshmeat don't want Windows-only projects. So it may be CodePlex you'll find the project on. More details when they come to hand.

    [Delphi] COM of libiconv

    I have just finished my first serious bit of Delphi programming, using Turbo Delphi Explorer. As a RAD/IDE it's pretty good. However, given the limitations of the Explorer version, I'll upgrade to the Pro version fairly soon.

    COMlibiconv is an in-process COM object and was born out of the company's need to convert some multibyte encodings into Unicode. It's based on DIConverters, a unit made available by Ralf Junker of
    The Delphi Inspiration. DIConverters is licensed as LGPL. COMlibiconv will also be LGPL.

    (Did I mention that I'm working again? No? Okay, well now I work as a software engineer for Strapper Technologies, of Fremantle, WA, Australia, makers of the Protium language.)

    I'll be posting version 1.0 of the project up on Freshmeat by the end of next week, God willing.

    COMlibiconv appears to work. I've used it in VBScript, late-bound, as
    and I think my boss has used it, early-bound, in VB6.

    At this stage the methods and properties exposed are as follows (taken from the source):
    The function iconv_toUnicode takes a string defining the name of the multibyte encoding, the string to be converted, and two integers stating where to start and when to finish. I should probably give those default values so that the method can be called with just the encoding and the string.

    ErrorCode contains an integer value which, when Success is false, represents what went wrong. An enumeration of possible error values is indicated and may make it into the next version.

    Aliases gives all the various names for an encoding, indexed by a number from zero to the number of encodings (which can be found using Count).

    CNames is also indexed in a similar way, and returns what I have called the 'CName' of the encoding. It's stuff that was in the DIConverters unit. I haven't found a use for it, but included it anyway.

    The next version will, God willing, contain a method to allow conversions from Unicode back to multibyte.

    If you're interested in this, and it hasn't appeared on Freshmeat by 18th November 2006, write a comment to remind me.

    © Copyright Bruce M. Axtens, 2006

    Thursday, September 21, 2006

    [Observations] Microsoft Changes Attitude Toward FOSS?

    After years of looking on FOSS as a disease, Microsoft have started talking with, and indeed collaborating with, the FOSS commmunity. For some the change is too unreal, with many taking a cynical, unbelieving attitude. For others, it's a godsend.

    Check out Port 25's posting about a recent cooperation between Microsoft and Mozilla, titled
    Why I invited Mozilla

    Then, if you have the time and bandwidth, there's a 1 hour video interview with Bill Hilf of the Open Source Software Lab at Microsoft

    It seems almost too good to be true. What do you think?

    Thursday, September 07, 2006

    [Observations] Wardriving

    Last night I went war ... er ... bussing. From part way through the 879's route as far as the stop nearest home, there must have been over 30 hot spots. At least three weren't encrypted, and "offered" subnets to the passerby.

    I'm on an 879 again this morning (2006-09-07, Thursday, after 09:00.) We haven't gone three kilometres yet and already
    NetStumbler has a list of over 50 hits. About half have WEP and the rest don't. And again about 1 in 10 of the total are open to the public.

    Pardon my naivety, but is this the usual state of affairs?

    It introduces an interesting ethical issue: no one can stop you stealing another's bandwidth if they don't take steps to protect it. It seems that you can sit in a tree outside their front gate, downloading to your heart's content and they wouldn't know it, until their ISP bills them for exceeding their download allowance, or they ring the ISP to ask why they've been shaped only to be told that one day last week they downloaded 5G of something or other.

    NetStumbler's own help file says, under the heading "Wardriving", "... To avoid using the networks that you observe, go to the Network Control Panel and unbind TCP/IP from your wireless LAN card." (Inevitably?) ethics aren't mentioned.

    [Later, 09:30] On the way into the Busport (inner city Perth) the list expanded rather dramatically. Some of the SSID's are more meaningful: PCEC_Dimension_Data and BHPB_NiW_Avaya_Voip, for instance. The name "metromesh" keeps coming up ... eight times so far. I wonder what that's all about?

    Waiting for a 36 to take me to Midland. May start cycling there next week ... only about 30 kilometres each way.

    Now working for Strapper Technologies. More about that later.

    Wednesday, August 30, 2006

    [VBScript] StandardLibrary.zip

    As promised in the previous posting, Standard Library is now available as a ZIP. Thanks to Perth Linux Users Group for the storage space.

    Saturday, August 12, 2006

    [VBScript] Standard Library

    My apologies for the hiatus between entries. I have been struggling with the "black dog."

    Recently, I was asked to make the Standard Library available, so here it it. For ease of digestion, I have segmented it, though you will find that some functions make use of routines in other segments. I will in due course make the whole file available in a single ZIP. Until then, you'll have to navigate as best you can.

    Cheers, comments, creative criticism and corrections all gratefully received. It's been a few months since I last used the library; you may find the odd rough edge. (I have edited the file a little for publication, but only to remove references to previous employers' sites, and a few redundant comments.)

    As knife manufacturers have no way of controlling how people use their knives, so I have no control over where and how you use the code on this weblog. I have tried as much as possible to acknowledge my sources. I would appreciate it if you also would do the same.

    Okay, with that out of the way, let's begin.

    I have adopted an Hungarian variable naming regime that is a bit different to the usual given in VBScript examples from Microsoft. Objects start with "o", collections with "c", strings with "s", numbers with "n", booleans with "b", dates with "d", arrays with "a", and variants with "v". I must confess, however, that I have not always followed my own standards.

    First, a few symbols and standard objects.
    Next a symbol table class, similar to that used in CLIVE.
    Next, String manipulation tools. There are lots of things in here: LeftOf, RightOf, CountFields, NthField, BeginsWith, EndsWith, Contains, ForceExtension, Subst, Subst2, DQ, Between, Wrap (which puts HTML markup around text), RemoveSpaces, Zerofill2, RightFill, and LeftFill.
    The one date manipulation function came out of a problem with encoding dates in Access. See the link for a fuller description.
    Arrays: AAdd, InArray, StrInArray, AMax and Amin.
    File manipulation code: CollectFiles, ReadFile, ReadFirstLine, Exists, WriteFile, Env and IncludeClass. Essentially wrappers around existing functionality, but with more flavour.
    How do you classify the "mexican if"?
    Now we get into some serious Active Directory (AD) and Windows Management Interface (WMI) code. As much as possible I've included the relevant attributions for stuff I have lifted and/or adapted.

    First, domain access: GetAvailableNTDomains
    Then computers: GetRemoteEnvironment, GetOnlineComputers, GetNetView, GetComputers, GetNBT, GetNBTA, GetDomainComputers, GetSpecs, ResolveIP, DetectTempFolder, and ExistsFolder.
    Also user-specific tools: GetOUofUser, GetLoginProfiles, GetMac, GetComputerUsers, GetComputerUsers2, GetDomainUser, and GetNameAndDescription.
    I didn't use them often, but there are function here for Group access as well: GetComputerGroups and GetGroups.
    Okay, now we get onto the application control routines, starting with Excel: ExcelStart, ExcelNewSheet and ExcelColumnNames.
    Then, Access routines: CreateDatabase, OpenDatabase, OpenRecordSet, CreateStructure and CreateIndex.
    One lonely email-specific tool: ErrorEmail.
    Internet Explorer tools: ModalDialog, ModalText, ModalThing, ReadClipboard, WriteClipboard.
    An LDAP function: GetDefaultNamingContext
    A function, CaptureDOS. It runs a command in the CMD shell, captures the output to a text file, and then sucks the data into a string variable.
    Logging variables and functions: LogTo, Log, Die and Faint.
    Next comes a testing module which is only executed if the library itself is executed directly. For example:
        CSCRIPT StandardLibrary.vbs

    Anything goes in this section, and the stuff below is what was in there the last time I tested the file, which was sometime in January 2006.
    Okay, that's the end of it.

    I don't know when I'll be doing VBScript again; I have designed the Sudoku solver but haven't coded it yet. I had thought of doing it as an HTA.

    At the moment I'm looking into the ISIS database technology (a friend has developed a Win32 Unicode-enabled version), serial i/o, FreeBASIC, and xbScript.

    I hope to recommence regular postings soon, likely in support of a new language, Protium. Until then.

    © Copyright Bruce M. Axtens, 2006