Updated May 18, 1997
One of the questions I see posted very often on comp.lang.basic.visual.misc
is "How do I call this 16-bit DLL/VBX" from 32-bit VB4?".
The purpose of this document is explain how to use Visual Basic and OLE
as a thunking layer to allow 16-bit components to be used from 32-bitVB4.
As we all know Windows started off in the 16-bit world (actually in the 8-bit world, but Windows wasn't popular back then). In the 16-bit model introduced in Windows 3.0, a common memory space was available to all applications and hardware was unprotected. Put simply, this meant that you could just about any low-level operation you can think of, but at the same time, programs could step on top of each other or write some value to a sensitive hardware register, therefore bringing down the entire system. The typical end result was a lot of UAFs, which became GPFs or General Protection Faults in Windows 3.1.
With the introduction of Windows NT, a new model was chosen based on 32-bit instructions and memory addressing schemes available only on 386 and higher processors (remember that when Windows 3.0 was introduced, the predominant processor was the 286). Because of the more advanced memory management unit in the 386, protected memory could be enabled, which protected 32-bit applications from each other and also prevented applications from stepping on the hardware when they weren't supposed to.
In order to get developers to switch over from 16-bit to 32-bit, the big incentive that Microsoft offered was a much easier to program "flat memory" model where if you need 5Mb of RAM, you just allocate it (in 16-bit code, programmers still have to deal with 64K chunks of memory at a time), preemptive scheduling and a host of other features.
However, in making the move to 32-bit code, programmers lost the ability to talk directly to hardware or directly use 16-bit DLLs (which could of course talk directly to the hardware and therefore potentially crash the system). While this can impact people that have a legitimate reason to talk directly to the hardware, generally speaking it's a good thing because true 32-bit operating systems like Windows NT, running 32-bit applications do not crash and if a single app goes haywire, it doesn't bring down the entire system. The Windows NT Server I have at the office has crashed once in the year or more that it's been up and that's because the hard drive failed!
Since one of the reasons that people want to use a 16-bit DLL from VB4/32 is to do low level I/O, lets talk about that for a second. Without a lot of programming work, 32-bit applications cannot talk directly to hardware. For Windows 95, this means writing a VxD to interface to hardware and under Windows NT, a device driver must be written. Both of these require the DDK (Device Driver Kit) and a lot of knowledge of how Windows internally operates.
Because Microsoft wants to maintain backward compatibility with older 16-bit applications on Windows 95, 16-bit code can talk directly to hardware. However, on Windows NT, the same proviso applies - no application can talk directly to hardware without a device driver.
There are a number of commercial products available for 32-bit development that allow low-level I/O by providing either a VxD or device driver, but these aren't cheap. A list of the ones I've seen advertised are:
OK, so despite all the reasons why you can't use your 16-bit DLL from VB4/32 and the fact that if you're doing hardware I/O and it'll work only on Windows 95, you still want it to happen. How do you go about making a thunking layer using OLE? The first thing you'll need is either the Professional or Enterprise Edition of VB4. The Standard Edition is 32-bit only, so you can't do this with that version.
The next step involves thinking about which calls to the DLL you use from your application. These will become either properties or methods in the 16-bit OLE server, called from the 32-bit application much like any other OLE automation process.
In this example, we'll use Jonathan Wood's VBASM.DLL. This DLL allows 16-bit applications to do all kinds of low-level stuff including DOS interrupts, hardware I/O and so on. The OLE server will allow a read and write to any hardware port.
Declare Function vbInp Lib "VBASM.DLL" (ByVal nPort
As Integer) As Integer
Declare Sub vbOut Lib "VBASM.DLL" (ByVal nPort As Integer, ByVal
nData As Integer)
Sub Main()
End Sub
(General) (Declarations)
Dim PortAddress as integer
Public Property Let Port(vNewValue As Integer)
PortAddress = vNewValue
End Property
Public Property Get Port() As Integer
Port = PortAddress
End Property
Public Property Get ByteIO() As Integer
ByteIO = vbInp(PortAddress)
End Property
Public Property Let ByteIO(vNewValue As Integer)
vbOut PortAddress, vbnewvalue
End Property
Dim IO As Thunker.IO
Set IO = New Thunker.IO
IO.Port = &H90
MsgBox Hex$(IO.ByteIO)
Set IO = Nothing
IO.Port selects the port
you want to communicate with. Reading IO.ByteIO causes the
port to be read and writing to IO.ByteIO, causes the port
to be written to. For example:IO.Port = &H90
IO.ByteIO = &HFF
The reason why the 16-bit project gets built twice (once into bServer.EXE and then into ioserver.EXE) is to prevent the GUID of the OLE server from changing each time. When you compile an OLE automation server, a new GUID (Globally Unique ID) is generated, unless the "Compatible OLE Server" field is filled in. What this means is that every time you re-compile the OLE Server without this field, the GUID will change and you will then need to re-reference the OLE Server in each project that uses it, which is a royal pain because it takes so long to do!
Also note that each time you click on the command button, the 16-bit OLE server gets created, used and then deleted. If you're going to be using the 16-bit OLE server throughout your 32-bit program, Dim the IO object variable at the form level and put the creation of the server at the Form Load time and it's removal (i.e. Set IO = Nothing) in the Form Unload event.
I hope this article explains how to use 16-bit code from 32-bit VB4.
It's not exactly fast, but it does work and is a better alternative than
not being able to do it at all!
Copyright © 1996 Rod Hewitt