VOGONS

Common searches


First post, by Marula

User metadata
Rank Newbie
Rank
Newbie

Hi,

got a small problem with DOSbox: I have a 32-bit program running on a Windows 64-bit computer, which is no problem. But the program offers an export-routine realized by a 16-bit executable called readseq.exe, which isn't supported by the 64-bit system.

I installed DOSbox, the readseq.exe now works, but I can't execute the readseq.exe "alone" because input from the 32-bit program is needed. What I would like to know: Is there any possibility to change settings so that each time my 32-bit program accesses the readseq.exe, the latter is automatically run with DOSbox?

In know that I can configure a DOSbox shortcut so that DOSbox automatically executes the respective program, but can I also configure my program to start with DOSbox?

I am new to this forum and not familiar with the topic; I hope my question is not a silly one.

Thanx!

Reply 2 of 7, by HunterZ

User metadata
Rank l33t++
Rank
l33t++

Does the 32-bit program pass any command-line parameters/arguments or environment variables to readseq.exe, or does readseq.exe know what to do on its own when it gets called?

Also, if the 32-bit program is also DOS-based then it may run inside of DOSBox as well.

Reply 3 of 7, by Marula

User metadata
Rank Newbie
Rank
Newbie

Hi, sorry I wasn't able to deal with the problem for a few days. I don't know anything about the communication between the two programs, but the 32-bit program surely passes information on to readseq.exe when it launches it. In a way, the procedure readseq.exe has to do is always the same, but the input is different. The 32-bit program is also DOS-based, but I suppose executing the 32-bit-program .exe in DOSbox won't lead to other .exes in the same folder being executed in DOSbox as well, or am I mistaken?

What I thought about was a change in the launching process of the readseq.exe, but maybe this is impossible because I cannot modify the 32-bit-program source code. Ideally, DOSbox should start automatically and provide a framework for readseq.exe every time readseq.exe gets called by the 32-bit-program...

Reply 4 of 7, by Yushatak

User metadata
Rank Member
Rank
Member

Yes - I made a two tools that achieve this. They replace the internal Windows ".EXE" handler with themselves, and upon running an EXE file check to see if it's a 16-bit DOS EXE, 16-bit Windows EXE, or other type. If it's 16-bit DOS it executes it through DOSBox passing command line parameters along, if it's 16-bit Windows it attempts to load win.com <yourapp.exe> (in DOSBox), which loads Windows (under DOS) and runs the app, intended for Win3x.

The original project was called "DIED" for "DOSBox Identifier and Executable Dispatcher" (iirc) and was written in Python. It was buggy and had flawed detection, so I rewrote it FAR better in AutoHotKey (AHK) as "NTVDM64". Due to a few bugs I never released it, but I'd be willing to. It also has some other features, like .PIF file parsing -> DOSBox, DOSBox shortcut autocreation, etc.

Nobody I've talked to has expressed much interest so I haven't been able to squash the remaining bugs (all of which are a few 32/64-bit programs that don't like being passed through like this - very rare).

Reply 6 of 7, by Yushatak

User metadata
Rank Member
Rank
Member
;
; AutoHotkey Version: 1.x
; Language: English
; Platform: Win9x/NT
; Author: J. "Yushatak" S. <t6600c@gmail.com>
; With Help From: "RaptorX"
; License: This program is intellectual property of the above author, so treat it as such. You may use, modify, and distribute it how you wish, but only for private purposes and not without the information about it's author (this license, my name, and email) accompanying it.
;
; Script Function:
; Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
;SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.

; --------------------------------------------------------------------
; Purpose: Return all of the script's command line
; arguments in their original form.
; Input:
; SkipParameters - The number of parameters to remove
; from the front of the returned string.
; Output:
; RETURN - The command line arguments.
; --------------------------------------------------------------------
GetCommandLine( SkipParameters = 0 )
{
AllCommandLine := SplitCommandString( DllCall( "GetCommandLineA", "Str" ), false, false )

; Set the size beforehand to avoid multiple resizings while assembling it.
VarSetCapacity( CommandLine, StrLen( AllCommandLine ) )

;Scripts support command line parameters. The format is:
;AutoHotkey.exe [Switches] [Script Filename] [Script Parameters]

;And for compiled scripts, the format is:
;CompiledScript.exe [Switches] [Script Parameters]

InSwitches := true
if ( !A_IsCompiled )
SkipParameters++
Loop, Parse, AllCommandLine, `n
{
if ( A_Index = 1 )
continue
StrippedCommand := StripWhitespace( A_LoopField )
if ( InSwitches )
{
InSwitches := false
if ( SubStr( StrippedCommand, 1, 1 ) = "/" )
{
; Just basing the switches on the slash is not enough.
; The script might have its own slash parameters.
; Ensure we only strip known AHK switches.
if ( StrippedCommand = "/f"
|| StrippedCommand = "/r"
|| StrippedCommand = "/force"
|| StrippedCommand = "/restart"
|| StrippedCommand = "/ErrorStdOut" )
{
Show last 300 lines
               InSwitches := true
continue
}
}
}
if ( SkipParameters > 0 )
{
SkipParameters--
continue
}
CommandLine .= A_LoopField
}
CommandLine := StripWhitespace( CommandLine, true, false )
return CommandLine
}


; --------------------------------------------------------------------
; Purpose: Read a Windows Command Line styled string and
; break it down into seperate arguments.
; Each argument will go on a seperate line.
; Input:
; String - The string to parse.
; StripQuotes - Remove quotes from the command line.
; StripWhitespace - Remove the whitespace between the arguments.
; If false, whitespace will go at
; the start of each line.
; Output:
; RETURN - The parsed commands.
; --------------------------------------------------------------------
SplitCommandString( String, StripQuotes = true, StripWhitespace = true )
{
InQuotes := false
NewLine := true

; Set the probable/maximum size beforehand to avoid multiple resizings while assembling it.
VarSetCapacity( OutString, StrLen( String ) )

Loop, Parse, String
{
if ( !InQuotes )
{
if A_LoopField is space
{
if ( !NewLine )
{
NewLine := true
OutString .= "`n"
}
if ( StripWhitespace )
continue
}
}
if A_LoopField is not space
NewLine := false
if ( A_LoopField = """" )
{
InQuotes := !InQuotes
if ( StripQuotes )
continue
}
OutString .= A_LoopField
}
return OutString
}


; --------------------------------------------------------------------
; Purpose: Removes whitespace from the edges of a string.
; Input:
; String - The string to parse.
; Front - Remove whitespace from the starting edge.
; Back - Remove whitespace from the trailing edge.
; Output:
; RETURN - The stripped string.
; --------------------------------------------------------------------
StripWhitespace( String, Front = true, Back = true )
{
if String is space ; Those loops can't properly handle an entirely blank string.
return ""

if ( Front )
{
Loop, % StrLen( String ) ;%
{
Character := SubStr( String, A_Index, 1 )
if Character is not space
{
StringTrimLeft, String, String, A_Index - 1
break
}
}
}
if ( Back )
{
Length := StrLen( String )
Loop, %Length%
{
Character := SubStr( String, Length - ( A_Index - 1 ), 1 )
if Character is not space
{
StringTrimRight, String, String, A_Index - 1
break
}
}
}
return String
}
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
| - Open binary file
| - Read n bytes (n = 0: all)
| - From offset (offset < 0: counted from end)
| - Close file
| data (replaced) <- file[offset + 0..n-1]
| Return #bytes actually read
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinRead(file, ByRef data, n=0, offset=0)
{
h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
IfEqual h,-1, SetEnv, ErrorLevel, -1
IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file

m = 0 ; seek to offset
IfLess offset,0, SetEnv,m,2
r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
IfEqual r,0, SetEnv, ErrorLevel, -3
IfNotEqual ErrorLevel,0, {
t = %ErrorLevel% ; save ErrorLevel to be returned
DllCall("CloseHandle", "Uint", h)
ErrorLevel = %t% ; return seek error
Return 0
}

TotalRead = 0
data =
IfEqual n,0, SetEnv n,0xffffffff ; almost infinite

format = %A_FormatInteger% ; save original integer format
SetFormat Integer, Hex ; for converting bytes to hex

Loop %n%
{
result := DllCall("ReadFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Read,"UInt",0)
if (!result or Read < 1 or ErrorLevel)
break
TotalRead += Read ; count read
c += 0 ; convert to hex
StringTrimLeft c, c, 2 ; remove 0x
c = 0%c% ; pad left with 0
StringRight c, c, 2 ; always 2 digits
data = %data%%c% ; append 2 hex digits
}

IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

h := DllCall("CloseHandle", "Uint", h)
IfEqual h,-1, SetEnv, ErrorLevel, -2
IfNotEqual t,,SetEnv, ErrorLevel, %t%

SetFormat Integer, %format% ; restore original format
Totalread += 0 ; convert to original format
Return TotalRead
}
base(num,inputbase,outputbase){
VarSetCapacity(S,65,0)
toDec := DllCall("msvcrt\_strtoui64", Str,num, Uint,0, Int,inputbase, "CDECL Int64")
DllCall("msvcrt\_i64toa", Int64,toDec, Str,S, Int,outputbase)
return, S
}
EXEiD()
{
dosbox:="c:\program files (x86)\dosbox-0.74\dosbox.exe"
args:=GetCommandLine()
argso=%args%
StringReplace,args,args,", ,All
If (SubStr(args,1,InStr(args,a_space)-1) = "shortcut")
{
argsep:=SplitCommandString(args)
StringSplit,argsep,argsep,`n
SplitPath,argsep2,filename,dir
if !dir
{
FileCreateShortcut,%argsep2%,%filename%.lnk
}
Else
{
FileCreateShortcut,%argsep2%,%dir%\%filename%.lnk
}
exit
}
else If (SubStr(args,1,InStr(args,a_space)-1) = "doscut")
{
argsep:=SplitCommandString(args)
StringSplit,argsep,argsep,`n
SplitPath,argsep2,filename,dir
if !dir
{
FileCreateShortcut,%dosbox%,%filename%.lnk,,%argsep2% -noconsole -exit
}
Else
{
FileCreateShortcut,%dosbox%,%dir%\%filename%.lnk,%dir%,%argsep2% -noconsole -exit
}
exit
}
else If (SubStr(args,1,InStr(args,a_space)-1) = "deskdoscut")
{
argsep:=SplitCommandString(args)
StringSplit,argsep,argsep,`n
SplitPath,argsep2,filename,dir
if !dir
{
FileCreateShortcut,%dosbox%,%a_desktop%\%filename%.lnk,,%argsep2% -noconsole -exit
}
Else
{
FileCreateShortcut,%dosbox%,%a_desktop%\%filename%.lnk,%dir%,%argsep2% -noconsole -exit
}
exit
}
;Debug Line
;MsgBox,%args%
DllCall("GetBinaryTypeA",str,args,uintp,result)
If(result=0)
{
output:="Win32"
;msgbox,%args%
Run,%argso%
}
else If(result=1)
{
output:="DOS"
;Launch in DOSBox
Run,%dosbox% %args% -noconsole -exit
FileDelete,std???.txt ;Delete DOSBox logs due to lack of console
}
else if(result=2)
{
output:="Win16"
;Launch in Win3x DOSBox
Loop,%args%
ShortPath=%A_LoopFileShortPath%
SplitPath,ShortPath,fn,dir
;The renaming is due to a Windows bug/feature where it redirects calls to read/write system.ini for legacy apps
;We need it to read/write where we're telling it..
FileMove,c:\ntvdm64\vhd\windows\system.ini,c:\ntvdm64\vhd\windows\temp.ini,1
IniWrite,d:\%fn%,c:\ntvdm64\vhd\windows\temp.ini,boot,shell
FileMove,c:\ntvdm64\vhd\windows\temp.ini,c:\ntvdm64\vhd\windows\system.ini,1
RunWait,%dosbox% -c "mount c: c:\ntvdm64\vhd" -c "mount d: %dir%" -c "path c:\;d:\;z:\;" -c "c:\windows\win :" -noconsole -exit
FileMove,c:\ntvdm64\vhd\windows\system.ini,c:\ntvdm64\vhd\windows\temp.ini,1
IniWrite,progman.exe,c:\ntvdm64\vhd\windows\system.ini,boot,shell
FileMove,c:\ntvdm64\vhd\windows\temp.ini,c:\ntvdm64\vhd\windows\system.ini,1
FileDelete,std???.txt
}
else if(result=3)
{
output:="PIF"
;Parse PIF file and then Launch EXE in DOSBox
datalen:=BinRead(args,data)

;This loop converts the raw hex to decimal and then to ACSII so we can work with it.
loop parse, data
{
count += 1
hex .= a_loopfield
if count = 2
{
textdata.= chr(base(hex, 16, 10))
count :=
hex :=
}
}
;Find the first path in the PIF and use that.
RegexMatch(textdata, "\w:.+?\.(\w{3})", Match)
Run,%dosbox% %Match% -noconsole -exit

}
else if(result=4)
{
output:="POSIX"
MsgBox,"There's no handler for %output% executables yet, sorry!"
}
else if(result=5)
{
output:="OS/2"
MsgBox,"There's no handler for %output% executables yet, sorry!"
}
else if(result=6)
{
output:="Win64"
;msgbox,%args%
Run,%argso%
}

;MsgBox,%args% is a %output% binary, AKA type %result%.

}
EXEiD()

In the above code block you can find a copy of the source to my NTVDM64, which when replacing the default EXE handler in the registry (by default it's %1 %% iirc, just prefix it with the path to this file once it's compiled with AHK - be sure to set DOSBox path in the source file first) will allow you to run 16-bit apps not only by clicking on them, but even from other apps as you describe, due to the fact that other apps call Windows's EXE handler to run these other apps. You'd also need to place it as the .COM file handler, .PIF file handler, etc. for any of those filetypes - those are the only three it covers.

My code is licensed such that it's my intellectual property - anyone has permission to use and modify it for personal reasons but I haven't released it under an open source license *YET*.

(sorry that it's so huge, but I didn't want to host it externally and have it disappear from search reference, and there doesn't seem to be a "spoiler" bbcode here)

I am currently translating the code over to Python and integrating it into my file manager/shell combo program "Periscope"... (it's on Google Code as periscope-file-manager if anyone is interested)

Edit: Oh, and it's hardcoded at the moment for the EXE to be located at c:\ntvdm64, and for the installation of Win3x (if you desire the capability to run Win16 programs under Win64 through DOSBox automatically) to be in c:\ntvdm64\vhd\windows.

Reply 7 of 7, by Marula

User metadata
Rank Newbie
Rank
Newbie

@ Yushatak: The idea is great, cool prog! Unfortunately I think I would need further instructions on how to integrate this into my system, as I am not really an expert on computing...
Furthermore, in the meanwhile the whole 32bit-program doesn't work correctly in Win7 64bit any more, so the whole thing is getting more complicated.

For this reason, I have now installed an XP running in a virtual machine and I will reinstall the program in this environment, which I hope will work completely correct then. (thanks, HunterZ!)

Thanks for all of your advices!