CallWin32

v1.00 (15 March 2009)
(C) 2002 Niall Douglas

CallWin32 is a podule emulator for Red Squirrel v0.6 or later (or VirtualAcorn). It permits any RISC-OS code to execute arbitrary Win32 calls via a SWI interface and is compatible with the Wimp2 preemptive multitasker for RISC-OS. It futhermore permits any Windows code you write to invoke preinstalled code within RISC-OS.

All files or additions created by myself (ie; under my copyright) are hereby placed under the GNU Library General Public Licence. You can find it in a License.txt file within the archive.

From hereafter, when we refer to Red Squirrel, we also mean VirtualAcorn.

NOTE: This code is designed to work with v0.6 of RS or VA only. Attempting to use it with later versions almost certainly with fail. That's why the source is provided, so you can fix any problems which arise yourselves! Failing that, use v0.6 of RS!

Red Squirrel Tools:

Bundled into the podule ROM with CallWin32 are a number of utilities which make use of it. Collectively, they are referred to as Red Squirrel Tools, or RSTools for short.

RSTools currently performs a number of functions:

RSTools runs as a module task so you can quit it from the Task Manager if you ever need to (unlikely). Furthermore it offers two *Configure options, RSTools_SleepFactor & RSTools_WheelTranslation which permit you to customise its operation - use *Help on these as usual for usage information.

One very useful thing which I won't be doing is exposing the Win32 clipboard to RISC-OS. It's not difficult for basic things like text (graphics are a bit harder), but someone else can do it. I suggest a little window with an icon you can drag out (import clipboard) and drag into (export clipboard).

Another part of RSTools is the MouseSync module, also included in the podule ROM. This uses CallWin32 to install an intercept on Red Squirrel to filter window messages as so to:

You can disable MouseSync two ways: *Unplug MouseSync or else delete the MouseSync.dll in the same directory as RedSquirrel.exe. MouseSync also provides a service call you can intercept to provide your own mouse driver and thus overriding MouseSync's default one.

As with all code for RISC-OS ever written by myself, everything works from RISC-OS 2 onwards. A caveat is enabling returning of spare time as this calls code not written by me which uses RO3 only code.

Installation:

To install, copy the CallWin32 directory from this archive into the Plugins directory within the Red Squirrel. Modify your model config file which resides in the Models directory to include the following lines:

[CallWin32Podule]
podule = <n>

... where <n> is a free podule slot.

To optionally install the mouse synchroniser, copy the MouseSync.dll file into the same directory as RedSquirrel.exe.

Usage:

When you now boot using your modified model, a new module called CallWin32 will be present. It provides the following SWI's:

  1. CallWin32_Info
  2. CallWin32_Immediate
  3. CallWin32_ParsInit
  4. CallWin32_ParsAddInt32
  5. CallWin32_ParsAddInt16
  6. CallWin32_ParsAddInt8
  7. CallWin32_ParsAddMemBlk
  8. CallWin32_ParsAddString
  9. CallWin32_WithPars
  10. CallWin32_VectorAllocate
  11. CallWin32_VectorDeallocate

See each SWI individual documentation page for more information. The following error codes can also be returned:

Also:

  1. MouseSync_WheelDelta
  2. Service_MouseChanged

You will probably want some examples to show you how it works:

PRINT TIME
SYS "CallWin32_Immediate","stdcall:kernel32::Sleep",1,3000
PRINT TIME
PRINT "Note the entire VM stops"

A more complicated example is as follows:

REM > TestCWR3
SYS "CallWin32_Info" TO ,size%
DIM q% size%
SYS "CallWin32_ParsInit",q%
:
REM To fetch an OSVERSIONINFO struct
DIM osv% 256
!osv%=148:REM sizeof(OSVERSIONINFO)
SYS "CallWin32_ParsAddMemBlk",q%,1,osv%,256
SYS "CallWin32_WithPars",q%,"stdcall:kernel32::GetVersionExA" TO 
success%,errcode%
IF success% THEN
major%=osv%!4
minor%=osv%!8
build%=osv%!12
PRINT "Your version of Windows is ";major%;".";minor%;" (build ";build%;": ";FNgetz(osv%+20);")"
ELSE
PRINT "Call failed with error code ",errcode%
ENDIF
END
:
DEF FNgetz(a%)
a$=""
WHILE ?a%
a$+=CHR$(?a%)
a%+=1
ENDWHILE
=a$

You can find these programs in the archive. You may need to set their filetype before they will run.

How Windows code can call RISC-OS code

A much less trivial example is how to have windows code call RISC-OS code. We suggest you consult the BBC Basic program TestMouse and see how it's done in practice. Be sure to run this outside the desktop and make sure the MouseSync module has been killed.

Basically your DLL windows side needs to export an initialisation and deinitialisation function. In your RISC-OS code, you must allocate a vector and install your handler using CallWin32_VectorAllocate and pass the returned vector number to your initialisation function which then sets up the calling of your handler.

On the Windows side of your handler being invoked, you should prepare any data you wish to send to RISC-OS in some static buffer and then call CallWinPodule_SignalVector() passing the allocated vector number. This then invokes your handler which then must call a special function in your DLL to retrieve the stored data, after which it can be discarded.

This rather convoluted process is further complicated by the fact that much code you may wish to call is not reentrant. Hence you can specify your vector handler routine is to be called via OS_AddCallBack ie; as a transient callback.

One point to mention is that vectors are a finite resource (currently with a maximum of 64). Failing to deallocate them will cause them to become exhausted with time.

Comments:

Y'know, four years ago I never ever envisaged myself ever programming for the Acorn again. And then in 1999 I released Wimp2, my preemptive multitasker for RISC-OS, to an Acorn scene which was clearly near-dead as indeed I had predicted many years before during the ill-fated Tornado project. The huge backward compatibility in RISC-OS was a bad thing, not a good thing - without advance, things wither. Still, after 1999 I really really never thought I'd use another Acorn again.

And well, here I am July 2002 writing relocatable modules once again. Strange how fate can be so strange. The rest of the world has caught up with RISC-OS but still, even in 2002, there are quite a number of things RISC-OS does better than anyone else - KDE, Linux, Win32 or MacOS X. It's been strange to be back in that environment again - nowadays little things about RISC-OS annoy me, but still even now it is a superior environment. Even after the countless systems I have programmed for professionally in the last five years, I still find good things in RISC-OS I wish I could use every day.

Furthermore, ex-RISC-OS programmers have proven to be some of the best on the planet. They are extremely flexible programmers, happy to tackle all sorts of weird systems and produce code of second-to-none quality. I find it strange when I talk with managers from around the world that they know of Acorn not because its technical superiority in the 80's, but because consistently their best remembered employees had an Acorn background. If nothing else, RISC-OS is an excellent teacher of good programming, and it is an excellent testament to the seven or so original programmers who wrote it some of whom it has been my good fortune to work with.

But what of the future? Well, so long as some things remain easier to do in RISC-OS, I shall be using the Acorn emulator by Graeme Barnes to work in conjunction with Windows and Linux. Believe it or not, I have worked some projects with Linux running in VMWare and VirtualAcorn on files mapped using HostFS off a samba share in VMWare. Now if only I could drag enough money together for three monitors, I could have all three systems on a monitor each ...

Obviously, the success of any emulated system is its integration with the host OS. VMWare does a minimum of this, and it is my intention to get Red Squirrel up to at least that point. To that end, the first step is clearly a method of RISC-OS being able to call Win32 and it is my hope that that has been done with CallWin32.

History:

20th October 2002 v1.00: Rebound DLL with latest RS 0.6 SDK (binary incompatibilities mean newer RS's will provoke various strange crashes in either RISC-OS or RS). Added support for disabling mouse input when MouseSync is being used. Fixed bug where mouse movement outside a bounded box didn't work. Fixed another bug where negative mouse bounding box values where getting converted into really big positive ones instead. Added support for new full screen upcall. Fixed bug in mapping pointer coords in double eigen modes (eg; mode 13). Released publicly.

24th September 2002 v0.95: Fixed bug where mouse movement over the RS window when RS window didn't have focus still caused RO ptr to move. Coded up the RSTools BBC Basic program as a module task. Added wheel movement to scroll translation. Added * commands to configure features. Made * commands into *configure commands. Had mouse movement issue a service call which if unclaimed then moved mouse. Fixed bug where CallWin32 crashed old IOC machine models. Released publicly.

20th September 2002 v0.90: Graeme finally added a method of obtaining the RS window handle, so debugged everything and turned TestMouse into a module. Released publicly.

1st September 2002 v0.75: Added vector support. Updated these docs. Changed memory copy back routine to use 4 byte transfers instead of 16 so buffers didn't get corrupted (copy out still uses optimised copy routine). Wrote MouseSync.dll & TestMouse but couldn't test it.

20th July 2002 v0.55: Added memory block support and fixed quite a few bugs. Upped to v0.55. Made a little app to return idle RISC-OS time. Released publicly for the first time

19th July 2002 v0.50: Released as beta to Red Squirrel mailing list

Todo:

Lastly:

My thanks to Graeme Barnes for his invaluable help in developing CallWin32. My thanks also to David J. Ruck for his RTC synchronisation code.

Niall Douglas
15 March 2009

http://www.nedprod.com/programs/RISC-OS/CallWin32/
CallWin32Support@nedprod.com