1

Experimenting Visual Basic 4 in DosBox + Windows 3.1 running on Windows 10. While I have installed SHARE.exe from MS-DOS 6.22 and it seems to run OK, it still fails to detect it.

The error I get is : "SHARE.exe must be installed in order to run Visual Basic"

I wanted to work out how the SHARE.exe detection works. I installed the Windows 3.1 SDK and tried to debug with CodeView. However I can't figure out how to set a breakpoint on MESSAGEBOX, and I can't use the keyboard shortcut to "halt" the system and break into CodeView as it seems to be passed to Windows host instead of Dosbox.

An analysis of VBIDE.dll I can find the error message:

res098:0000 ; Resource, type (8006): String table
res098:0000 ; File offset      : 26CB0h  Length: 0100h
res098:0000 ; Attributes (1C30): Movable Pure
res098:0000 ; Resource ID      : 3143
res098:0000 ; ===========================================================================
res098:0000
res098:0000 ; Segment type: Regular
res098:0000 res098          segment para public 'RESOURCE' use16
res098:0000                 assume cs:res098
res098:0000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
res098:0000 a8shareExeMustB db '8SHARE.EXE must be installed in order to run Visual Basic',0
res098:003A aRecordsourcePr db '>RecordSource property of the associated data control is empty.MV'
res098:003A                 db 'isual Basic was not able to start up due to an invalid system con'

The VBIDE.dll is referenced in VB.exe this way:

cseg15:2EBF                 mov     es, [bp+var_4+2]
cseg15:2EC2                 mov     byte ptr es:[si+1], 0
cseg15:2EC7                 lea     ax, [bp+var_17A]
cseg15:2ECB                 push    ss
cseg15:2ECC                 push    ax              ; LPCSTR
cseg15:2ECD                 push    ds
cseg15:2ECE                 push    offset aVbideDll ; "VBIDE.DLL"
cseg15:2ED1                 call    sub_37E70
cseg15:2ED6                 mov     word_10C9DC, ax
cseg15:2ED9                 or      ax, ax
cseg15:2EDB                 jnz     short loc_389CC
cseg15:2EDD                 push    ds
cseg15:2EDE                 push    offset aVbideDll_0 ; "VBIDE.DLL"
cseg15:2EE1                 push    ds
cseg15:2EE2                 push    offset aTheLanguageDll ; "The language DLL '%s' could not be foun"...
cseg15:2EE5                 lea     ax, [bp+var_27A]

I suspect this word_10C9DC location is important, and it's referenced when calling LOADSTRING (Some examples there are many more)

cseg09:269A                 enter   50h, 0
cseg09:269E                 push    word_10C9DC     ; HINSTANCE
cseg09:26A2                 push    7D0h            ; UINT
cseg09:26A5                 lea     ax, [bp+var_28]
cseg09:26A8                 push    ss
cseg09:26A9                 push    ax              ; LPSTR
cseg09:26AA                 push    28h ; '('       ; int
cseg09:26AC                 call    LOADSTRING
cseg09:26B1                 push    word_10C9DC     ; HINSTANCE
cseg09:26B5                 push    [bp+arg_2]      ; UINT
cseg09:26B8                 lea     ax, [bp+var_50]
cseg09:26BB                 push    ss
cseg09:26BC                 push    ax              ; LPSTR
cseg09:26BD                 push    28h ; '('       ; int
cseg09:26BF                 call    LOADSTRING
cseg09:26C4                 lea     ax, [bp+var_28]
cseg09:26C7                 push    ss
cseg09:26C8                 push    ax              ; LPCSTR
cseg09:26C9                 lea     ax, [bp+var_50]
cseg09:26CC                 push    ss
cseg09:26CD                 push    ax              ; LPCSTR
cseg09:26CE                 push    [bp+arg_0]      ; int
cseg09:26D1                 push    seg cseg04
cseg09:26D4                 push    offset aVbIni   ; "VB.INI"
cseg09:26D7                 call    GETPRIVATEPROFILEINT
cseg09:26DC                 leave

There is a few MESSAGEBOX references:

MessageBox #1

cseg05:0EC8                 push    0               ; HWND
cseg05:0ECA                 les     bx, dword_10C1F8
cseg05:0ECE                 add     bx, es:[bx+9Ah]
cseg05:0ED3                 push    es
cseg05:0ED4                 push    bx              ; LPCSTR
cseg05:0ED5                 push    0
cseg05:0ED7                 push    0               ; LPCSTR
cseg05:0ED9                 push    10h             ; UINT
cseg05:0EDB                 call    MESSAGEBOX

MessageBox #2

cseg15:2FE2                 push    0               ; HWND
cseg15:2FE4                 les     bx, dword_10C1F8
cseg15:2FE8                 add     bx, es:[bx+9Eh]
cseg15:2FED                 push    es
cseg15:2FEE                 push    bx              ; LPCSTR
cseg15:2FEF                 push    seg cseg02
cseg15:2FF2                 push    offset byte_9EC8 ; LPCSTR
cseg15:2FF5                 push    1010h           ; UINT
cseg15:2FF8                 call    MESSAGEBOX

MessageBox #4 & 5

cseg47:297E                 push    bp
cseg47:297F                 mov     bp, sp
cseg47:2981                 push    di
cseg47:2982                 push    si
cseg47:2983                 mov     di, [bp+6]
cseg47:2986                 mov     es, word ptr [bp+8]
cseg47:2989                 push    word ptr es:[di]
cseg47:298C                 push    word ptr es:[di+4]
cseg47:2990                 push    word ptr es:[di+2]
cseg47:2994                 push    word ptr es:[di+8]
cseg47:2998                 push    word ptr es:[di+6]
cseg47:299C                 push    word ptr es:[di+0Ah]
cseg47:29A0                 call    MESSAGEBOX
cseg47:29A5                 mov     si, ax
cseg47:29A7                 or      si, ax
cseg47:29A9                 jnz     short loc_B517F
cseg47:29AB                 mov     es, word ptr [bp+8]
cseg47:29AE                 and     word ptr es:[di+0Ah], 0CF0Fh
cseg47:29B4                 push    word ptr es:[di]
cseg47:29B7                 push    word ptr es:[di+4]
cseg47:29BB                 push    word ptr es:[di+2]
cseg47:29BF                 push    word ptr es:[di+8]
cseg47:29C3                 push    word ptr es:[di+6]
cseg47:29C7                 or      word ptr es:[di+0Ah], 1010h
cseg47:29CD                 push    word ptr es:[di+0Ah]
cseg47:29D1                 call    MESSAGEBOX

I couldn't work out which messagebox was displaying the message, so I replaced them all with int 3, this allowed me to break into the CodeView debugger. From this I worked out relevant MESSAGEBOX code displaying error was:

cseg47:297E                 push    bp
cseg47:297F                 mov     bp, sp
cseg47:2981                 push    di
cseg47:2982                 push    si
cseg47:2983                 mov     di, [bp+6]
cseg47:2986                 mov     es, word ptr [bp+8]
cseg47:2989                 push    word ptr es:[di]
cseg47:298C                 push    word ptr es:[di+4]
cseg47:2990                 push    word ptr es:[di+2]
cseg47:2994                 push    word ptr es:[di+8]
cseg47:2998                 push    word ptr es:[di+6]
cseg47:299C                 push    word ptr es:[di+0Ah]
cseg47:29A0                 call    MESSAGEBOX

However there was no xref to this section of code, the only reference I could find to this location was these push statements:

loc_B51AB:
mov     ax, [bp+arg_6]
mov     dx, [bp+arg_8]
mov     [bp+var_A], ax
mov     [bp+var_8], dx
mov     ax, [bp+arg_2]
mov     dx, [bp+arg_4]
mov     [bp+var_6], ax
mov     [bp+var_4], dx
mov     ax, [bp+arg_0]
mov     [bp+var_2], ax
push    seg cseg47
push    297Eh
lea     ax, [bp+var_C]
push    ss
push    ax
push    ss
push    ax
call    sub_B4F7C
leave
retf    0Ch
sub_B5188 endp

What code set up the message box string here, and is there a way by knowing the details in resource DLL what assembly I should look for when then string is loaded.

1

From the code you posted, it seems that sub_B4F7C is a function registering handlers, in this case, function at 297Eh. This address (function pointer) is probably being saved somewhere by sub_B4F7C and will be called when SHARE.EXE is not detected.

Thus, this handler won't be called directly; when the event occurs, the code will just check at relevant address for a function registered for that event and call it. It will use the address previously put into memory by sub_B4F7C, instead of hardcoded value.

In short: don't worry, this function will be called. You can verify it by putting a breakpoint at its beginning. It is also worth to mark this handler as a function (select the relevant fragment and press P). You can then right click at 297Eh, select offset and select the offset of the newly created function to display.

Note: According to documentation (for 32bit, but signature seems to be the same), word_10C9DC is the identifier of module containing the strings to load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.