Dec 112017
The mystery of how to call a DOS app from an OS/2 session ala the program manager is explained in this facinating file. Great piece of detective work to explain one of life’s mysteries. | |||
---|---|---|---|
File Name | File Size | Zip Size | Zip Type |
CALLDOS.TXT | 11967 | 3671 | deflated |
Download File DOSSYS.ZIP Here
Contents of the CALLDOS.TXT file
==========================
ibm.os2/long.messages #200, from jgilliland, 11358 chars, Wed Sep 12 09:55:43 19
90
--------------------------
TITLE: OS/2 1.2 DOS.SYS interface
Yet another of OS/2's mysteries has been unraveled. OS/2 1.2 allows the
Task Manager to initiate programs in the DOS box, but does not document
the mechanism that is used, so it has not been possible to do the same
thing from other applications. Here is set of messages from the FidoNet
OS/2 echo that documents the DOS.SYS driver interface that performs this
magic, and sample code to show its use. You'll also find a paragraph
from Peter Fitzsimmons describing how he figured this all out.
Credit goes to Peter Fitzsimmons for doing the original research, and to
Bill Andrus for tying together the loose ends and creating a usable
program out of it.
309/366 09 Sep 90 08:12:06
From: Peter Fitzsimmons
To: All
Subj: new trick
Attr:
------------------------------------------------
I've figured out a little bit about DOS.SYS....
This little sample program uses DOS.SYS to change to C:, change to \OS2, and
run "edlin \config.sys".
When you Q)uit edlin, the session that was in the foreground prior to flipping
to the dos box (not nec the session that 2dos.exe was running in) is restored
to the foreground.
I have not yet figured out how to reboot through DOS.SYS -- but this is an easy
thing to code yourself (such a program is included with Maximus).
-[2dos.c beings]----------------------------------
#include
#include
#include
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WINSWITCHLIST
#include
void jump2dos(void);
static char *cmd = "\x80 C:\r"
"\x80 CD\\OS2\r"
"\x80 edlin \\config.sys\r";
void cdecl main(void)
{
HFILE hf;
USHORT rc, dummy;
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
rc = DosWrite(hf, cmd, strlen(cmd)+1, &dummy);
DosClose(hf);
if(!rc)
jump2dos();
else if(rc == ERROR_NOT_READY)
printf("A program is already running in the DOS box\n");
else
printf("Unexpected OS/2 error SYS%04u\n", rc);
}
else
printf("DOS.SYS not installed (sys%04u)\n", rc);
DosBeep(1000, 100);
}
void jump2dos(void)
{
USHORT num, i;
void *buf = malloc(32000);
SWENTRY *swe;
HSWITCH fgHandle;
SEL selGlobalSeg, selLocalSeg;
GINFOSEG FAR * volatile pgis;
UCHAR sgDos;
/* find out who is in the foregound, so we know who to switch
* back to after the dos box is done. This method only works
* if the foreground session is NOT a pm program. If it is a
* pm program, the "Task List" will be the active app after
* the task switch
*/
DosGetInfoSeg(&selGlobalSeg, &selLocalSeg);
pgis = MAKEPGINFOSEG(selGlobalSeg);
fgHandle = WinQuerySwitchHandle(0L, pgis->pidForeground);
/* Find the switch list handle of the DOS box: */
num = WinQuerySwitchList(0L, buf, 32000);
swe = (SWENTRY *)((USHORT *)buf + 1);
for(i=0; i if(!strcmp("DOS", swe[i].swctl.szSwtitle)){
WinSwitchToProgram(swe[i].hswitch);
break;
}
}
free(buf);
if(i==num){
printf("This system is configured without a dos box!\n");
return;
}
if(fgHandle){
DosSleep(100L); /* give a moment for the task switch */
sgDos = pgis->sgCurrent;
/*
* Wait (poll) current screen group -- waiting for the DOS
* program to end. I don't like polling, but this is the only
* solution I can come up with. If you don't mind the "Task
* List" always being brought the the fore after the dos progam
* ends, you can forget about all of this and exit() after the
* WinSwitchToProgram(), above.
*/
while( sgDos == pgis->sgCurrent )
DosSleep(500L);
WinSwitchToProgram(fgHandle); /* back to where we started */
}
}
#if 0
Comments
--------
The only reason this program works is becuase WinSwitchToProgram()
allows you to:
1) Switch a session to the foreground which is not one of your own
child sessions.
2) Switch a session to the foreground when you are not running
in the foreground yourself.
Acording to the documentation (IBM, v1.20), you are not supposed to
be able to do either of these things. However, the "File Manager",
from what I can figure out, uses this method to switch to the DOS
box too, so I am confident that this program will continue to work
under OS/2 1.2x.
Peter Fitzsimmons, A:WARE Inc. Thu 09-06-1990 22:15:11
#endif
-[2dos.c ends]----------------------------------
--- Maximus-CBCS v1.02-OS/2-r2
* Origin: Pete's Point (1:250/628.1)
311/366 09 Sep 90 08:12:29
From: Peter Fitzsimmons
To: All
Subj: new trick part 2
Attr:
------------------------------------------------
And here is how to reboot via dos.sys:
----[reboot.c begins]----
#include
#define INCL_DOS
#include
void cdecl main(void)
{
HFILE hf;
USHORT rc, dummy;
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
DosShutdown(0L);
DosDevIOCtl(NULL, NULL, 0xab, 0xd5, hf); /* reboot */
DosClose(hf);
}
else
printf("DOS.SYS not installed (sys%04u)\n", rc);
}
----[reboot.c ends]------
How did I figure all of this DOS.SYS stuff out, you ask? I wrote my own DOS$
device driver, and simply had it report what the programs that use the real
DOS$ (boot.com, pmfile.exe) were trying to do with it. (I was bored one day at
work).
Pete.
--- Maximus-CBCS v1.02-OS/2-r2
* Origin: Pete's Point (1:250/628.1)
361/366 10 Sep 90 23:14:13
From: Bill Andrus
To: Peter Fitzsimmons
Subj: new trick part 3
Attr:
------------------------------------------------
Okay, here's the complete program that everyone says can't be done with the
current documentation:
=== CALLDOS.C ========================================================
/* Compiles with IBM C/2 1.1 and its MAKE/2 2.0 using:
###############################################################
# Make file for CALLDOS.C #
# #
# use MAKE CALLDOS.C #
# #
###############################################################
model=S # use large model when debugging -- bugs JUMP out at you
mode=p
linklibs=$(model)libce$(mode).lib os2.lib
CFLAGS=-A$(model) -Lp -Oxrn -Zpel -W3 -G2 -Gw -J -nologo
LINK=D:\C\Bin\Link
calldos.exe : calldos.obj
$(LINK)
calldos.obj,calldos.exe/A:16/FAR/NOD/PACKD/ST:3000,NUL.MAP,$(linklibs);
calldos.obj : calldos.c
!CL $(CFLAGS) -c $?
*/
/* Merge of Peter Fitzsimmons' CALLBOX.C and 2DOS.C programs */
#include
#include
#include
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WINSWITCHLIST
#include
void jump2dos(void)
{
USHORT num, i;
void *buf = malloc(32000);
SWENTRY *swe;
HSWITCH fgHandle;
SEL selGlobalSeg, selLocalSeg;
GINFOSEG FAR * volatile pgis;
UCHAR sgDos;
/* find out who is in the foregound, so we know who to switch
* back to after the dos box is done. This method only works
* if the foreground session is NOT a pm program. If it is a
* pm program, the "Task List" will be the active app after
* the task switch
*/
DosGetInfoSeg(&selGlobalSeg, &selLocalSeg);
pgis = MAKEPGINFOSEG(selGlobalSeg);
fgHandle = WinQuerySwitchHandle(0L, pgis->pidForeground);
/* Find the switch list handle of the DOS box: */
num = WinQuerySwitchList(0L, buf, 32000);
swe = (SWENTRY *)((USHORT *)buf + 1);
for(i=0; i if(!strcmp("DOS", swe[i].swctl.szSwtitle)){
WinSwitchToProgram(swe[i].hswitch);
break;
}
}
free(buf);
if(i==num){
printf("This system is configured without a dos box!\n");
return;
}
if(fgHandle){
DosSleep(500L); /* give a moment for the task switch */
sgDos = pgis->sgCurrent;
/*
* Wait (poll) current screen group -- waiting for the DOS
* program to end. I don't like polling, but this is the only
* solution I can come up with. If you don't mind the "Task
* List" always being brought the the fore after the dos progam
* ends, you can forget about all of this and exit() after the
* WinSwitchToProgram(), above.
*/
while( sgDos == pgis->sgCurrent )
DosSleep(500L);
WinSwitchToProgram(fgHandle); /* back to where we started */
}
}
#if 0
Comments
--------
The only reason this program works is becuase WinSwitchToProgram()
allows you to:
1) Switch a session to the foreground which is not one of your own
child sessions.
2) Switch a session to the foreground when you are not running
in the foreground yourself.
Acording to the documentation (IBM, v1.20), you are not supposed to
be able to do either of these things. However, the "File Manager",
from what I can figure out, uses this method to switch to the DOS
box too, so I am confident that this program will continue to work
under OS/2 1.2x.
Peter Fitzsimmons, A:WARE Inc. Thu 09-06-1990 22:15:11
#endif
void main(int argc, char **argv)
{
HFILE hf;
USHORT rc, dummy;
static char cmd[256];
int i;
if( argc < 2 ){
printf("\nUsage CALLDOS\n\n");
printf(" Each with blanks should be enclosed by quotes\n\n");
printf("For example:\n");
printf("CALLDOS C: \"CD \\OS2\" \"DIR > \\DIR.LST\" \"CD \\\"\n\n");
printf("Will make C:\\OS2 current, list the files to C:\\DIR.LST,\n");
printf("and switch back to C:\\.\n\n");
printf("If invoked while a PM session is current, the focus returns,\n");
printf("to the Task List, else returns to the current session.\n\n");
exit (255);
}
cmd[0] = '\0';
for(i=1; i strcat(cmd, "\x80 ");
strcat(cmd, argv[i]);
strcat(cmd, "\r");
if( i != (argc-1) )
strcat(cmd, " ");
}
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
rc = DosWrite(hf, cmd, strlen(cmd)+1, &dummy);
DosClose(hf);
if(!rc)
jump2dos();
else if(rc == ERROR_NOT_READY) {
printf("A program is already running in the DOS box\n");
exit (1);
}
else {
printf("Unexpected OS/2 error SYS%04u\n", rc);
exit (2);
}
}
else {
printf("DOS.SYS not installed (sys%04u)\n", rc);
exit (3);
}
DosBeep(1000, 100);
}
=== End of CALLDOS.C ===============================================
--- msged 2.00 OS/2
* Origin: RC13's OS/2 Point in the Pit (1:109/[email protected])
No more unread messages in this topic
Hit for next active conf/topic.
Read:
ibm.os2/long.messages #200, from jgilliland, 11358 chars, Wed Sep 12 09:55:43 19
90
--------------------------
TITLE: OS/2 1.2 DOS.SYS interface
Yet another of OS/2's mysteries has been unraveled. OS/2 1.2 allows the
Task Manager to initiate programs in the DOS box, but does not document
the mechanism that is used, so it has not been possible to do the same
thing from other applications. Here is set of messages from the FidoNet
OS/2 echo that documents the DOS.SYS driver interface that performs this
magic, and sample code to show its use. You'll also find a paragraph
from Peter Fitzsimmons describing how he figured this all out.
Credit goes to Peter Fitzsimmons for doing the original research, and to
Bill Andrus for tying together the loose ends and creating a usable
program out of it.
309/366 09 Sep 90 08:12:06
From: Peter Fitzsimmons
To: All
Subj: new trick
Attr:
------------------------------------------------
I've figured out a little bit about DOS.SYS....
This little sample program uses DOS.SYS to change to C:, change to \OS2, and
run "edlin \config.sys".
When you Q)uit edlin, the session that was in the foreground prior to flipping
to the dos box (not nec the session that 2dos.exe was running in) is restored
to the foreground.
I have not yet figured out how to reboot through DOS.SYS -- but this is an easy
thing to code yourself (such a program is included with Maximus).
-[2dos.c beings]----------------------------------
#include
#include
#include
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WINSWITCHLIST
#include
void jump2dos(void);
static char *cmd = "\x80 C:\r"
"\x80 CD\\OS2\r"
"\x80 edlin \\config.sys\r";
void cdecl main(void)
{
HFILE hf;
USHORT rc, dummy;
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
rc = DosWrite(hf, cmd, strlen(cmd)+1, &dummy);
DosClose(hf);
if(!rc)
jump2dos();
else if(rc == ERROR_NOT_READY)
printf("A program is already running in the DOS box\n");
else
printf("Unexpected OS/2 error SYS%04u\n", rc);
}
else
printf("DOS.SYS not installed (sys%04u)\n", rc);
DosBeep(1000, 100);
}
void jump2dos(void)
{
USHORT num, i;
void *buf = malloc(32000);
SWENTRY *swe;
HSWITCH fgHandle;
SEL selGlobalSeg, selLocalSeg;
GINFOSEG FAR * volatile pgis;
UCHAR sgDos;
/* find out who is in the foregound, so we know who to switch
* back to after the dos box is done. This method only works
* if the foreground session is NOT a pm program. If it is a
* pm program, the "Task List" will be the active app after
* the task switch
*/
DosGetInfoSeg(&selGlobalSeg, &selLocalSeg);
pgis = MAKEPGINFOSEG(selGlobalSeg);
fgHandle = WinQuerySwitchHandle(0L, pgis->pidForeground);
/* Find the switch list handle of the DOS box: */
num = WinQuerySwitchList(0L, buf, 32000);
swe = (SWENTRY *)((USHORT *)buf + 1);
for(i=0; i
WinSwitchToProgram(swe[i].hswitch);
break;
}
}
free(buf);
if(i==num){
printf("This system is configured without a dos box!\n");
return;
}
if(fgHandle){
DosSleep(100L); /* give a moment for the task switch */
sgDos = pgis->sgCurrent;
/*
* Wait (poll) current screen group -- waiting for the DOS
* program to end. I don't like polling, but this is the only
* solution I can come up with. If you don't mind the "Task
* List" always being brought the the fore after the dos progam
* ends, you can forget about all of this and exit() after the
* WinSwitchToProgram(), above.
*/
while( sgDos == pgis->sgCurrent )
DosSleep(500L);
WinSwitchToProgram(fgHandle); /* back to where we started */
}
}
#if 0
Comments
--------
The only reason this program works is becuase WinSwitchToProgram()
allows you to:
1) Switch a session to the foreground which is not one of your own
child sessions.
2) Switch a session to the foreground when you are not running
in the foreground yourself.
Acording to the documentation (IBM, v1.20), you are not supposed to
be able to do either of these things. However, the "File Manager",
from what I can figure out, uses this method to switch to the DOS
box too, so I am confident that this program will continue to work
under OS/2 1.2x.
Peter Fitzsimmons, A:WARE Inc. Thu 09-06-1990 22:15:11
#endif
-[2dos.c ends]----------------------------------
--- Maximus-CBCS v1.02-OS/2-r2
* Origin: Pete's Point (1:250/628.1)
311/366 09 Sep 90 08:12:29
From: Peter Fitzsimmons
To: All
Subj: new trick part 2
Attr:
------------------------------------------------
And here is how to reboot via dos.sys:
----[reboot.c begins]----
#include
#define INCL_DOS
#include
void cdecl main(void)
{
HFILE hf;
USHORT rc, dummy;
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
DosShutdown(0L);
DosDevIOCtl(NULL, NULL, 0xab, 0xd5, hf); /* reboot */
DosClose(hf);
}
else
printf("DOS.SYS not installed (sys%04u)\n", rc);
}
----[reboot.c ends]------
How did I figure all of this DOS.SYS stuff out, you ask? I wrote my own DOS$
device driver, and simply had it report what the programs that use the real
DOS$ (boot.com, pmfile.exe) were trying to do with it. (I was bored one day at
work).
Pete.
--- Maximus-CBCS v1.02-OS/2-r2
* Origin: Pete's Point (1:250/628.1)
361/366 10 Sep 90 23:14:13
From: Bill Andrus
To: Peter Fitzsimmons
Subj: new trick part 3
Attr:
------------------------------------------------
Okay, here's the complete program that everyone says can't be done with the
current documentation:
=== CALLDOS.C ========================================================
/* Compiles with IBM C/2 1.1 and its MAKE/2 2.0 using:
###############################################################
# Make file for CALLDOS.C #
# #
# use MAKE CALLDOS.C #
# #
###############################################################
model=S # use large model when debugging -- bugs JUMP out at you
mode=p
linklibs=$(model)libce$(mode).lib os2.lib
CFLAGS=-A$(model) -Lp -Oxrn -Zpel -W3 -G2 -Gw -J -nologo
LINK=D:\C\Bin\Link
calldos.exe : calldos.obj
$(LINK)
calldos.obj,calldos.exe/A:16/FAR/NOD/PACKD/ST:3000,NUL.MAP,$(linklibs);
calldos.obj : calldos.c
!CL $(CFLAGS) -c $?
*/
/* Merge of Peter Fitzsimmons' CALLBOX.C and 2DOS.C programs */
#include
#include
#include
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WINSWITCHLIST
#include
void jump2dos(void)
{
USHORT num, i;
void *buf = malloc(32000);
SWENTRY *swe;
HSWITCH fgHandle;
SEL selGlobalSeg, selLocalSeg;
GINFOSEG FAR * volatile pgis;
UCHAR sgDos;
/* find out who is in the foregound, so we know who to switch
* back to after the dos box is done. This method only works
* if the foreground session is NOT a pm program. If it is a
* pm program, the "Task List" will be the active app after
* the task switch
*/
DosGetInfoSeg(&selGlobalSeg, &selLocalSeg);
pgis = MAKEPGINFOSEG(selGlobalSeg);
fgHandle = WinQuerySwitchHandle(0L, pgis->pidForeground);
/* Find the switch list handle of the DOS box: */
num = WinQuerySwitchList(0L, buf, 32000);
swe = (SWENTRY *)((USHORT *)buf + 1);
for(i=0; i
WinSwitchToProgram(swe[i].hswitch);
break;
}
}
free(buf);
if(i==num){
printf("This system is configured without a dos box!\n");
return;
}
if(fgHandle){
DosSleep(500L); /* give a moment for the task switch */
sgDos = pgis->sgCurrent;
/*
* Wait (poll) current screen group -- waiting for the DOS
* program to end. I don't like polling, but this is the only
* solution I can come up with. If you don't mind the "Task
* List" always being brought the the fore after the dos progam
* ends, you can forget about all of this and exit() after the
* WinSwitchToProgram(), above.
*/
while( sgDos == pgis->sgCurrent )
DosSleep(500L);
WinSwitchToProgram(fgHandle); /* back to where we started */
}
}
#if 0
Comments
--------
The only reason this program works is becuase WinSwitchToProgram()
allows you to:
1) Switch a session to the foreground which is not one of your own
child sessions.
2) Switch a session to the foreground when you are not running
in the foreground yourself.
Acording to the documentation (IBM, v1.20), you are not supposed to
be able to do either of these things. However, the "File Manager",
from what I can figure out, uses this method to switch to the DOS
box too, so I am confident that this program will continue to work
under OS/2 1.2x.
Peter Fitzsimmons, A:WARE Inc. Thu 09-06-1990 22:15:11
#endif
void main(int argc, char **argv)
{
HFILE hf;
USHORT rc, dummy;
static char cmd[256];
int i;
if( argc < 2 ){
printf("\nUsage CALLDOS
printf(" Each
printf("For example:\n");
printf("CALLDOS C: \"CD \\OS2\" \"DIR > \\DIR.LST\" \"CD \\\"\n\n");
printf("Will make C:\\OS2 current, list the files to C:\\DIR.LST,\n");
printf("and switch back to C:\\.\n\n");
printf("If invoked while a PM session is current, the focus returns,\n");
printf("to the Task List, else returns to the current session.\n\n");
exit (255);
}
cmd[0] = '\0';
for(i=1; i
strcat(cmd, argv[i]);
strcat(cmd, "\r");
if( i != (argc-1) )
strcat(cmd, " ");
}
rc = DosOpen("DOS$", &hf, &dummy, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
if(!rc){
rc = DosWrite(hf, cmd, strlen(cmd)+1, &dummy);
DosClose(hf);
if(!rc)
jump2dos();
else if(rc == ERROR_NOT_READY) {
printf("A program is already running in the DOS box\n");
exit (1);
}
else {
printf("Unexpected OS/2 error SYS%04u\n", rc);
exit (2);
}
}
else {
printf("DOS.SYS not installed (sys%04u)\n", rc);
exit (3);
}
DosBeep(1000, 100);
}
=== End of CALLDOS.C ===============================================
--- msged 2.00 OS/2
* Origin: RC13's OS/2 Point in the Pit (1:109/[email protected])
No more unread messages in this topic
Hit
Read:
December 11, 2017
Add comments