Working with the Microsoft Programmer’s Library

OS/2 Programmers Ref

Well recently I did manage to get some GREAT books on OS/2, going back to the Microsoft days.. And they contain a lot of information, which was actually quite substantial.

Although there is the impression after the fact that Microsoft really wasn’t that dedicated to OS/2 the wealth of information in these books seem to be otherwise..

Anyways there is four volumes in the set, 1-3 going over version 1.1, and volume 4 with the 1.2 release of OS/2.

As luck would have it, someone gave me a lead on an ISO that contained not only these, but all of the programming documentation of the time on a CD.  No doubt this was the predecessor to the excellent MSDN.

There of course, is just one catch.  It uses the .hlp files, but not from Windows 3.00 its something much earlier and the only way to view the files is with an MS-DOS program.

Glorious MS-DOS interface

I even tried it on OS/2 hoping it was a family api program (like so many of the era were) but no luck.  I was then hoping maybe I could just ‘print’ the files to a virtual printer, and spool the whole job.  BUT YOU CANT PRINT.

So I then wondered if I could put together a TSR that would scrape the screen, append it to a file, and just keep hitting page down.   A few hours of cobbling together some example programs, and remembering to compile with the LARGE memory model (FAR pointers! remember those?)  I could then finally unleash the TSR through the program and extract some of the texts.

For those wondering how to do this kind of thing from MS-DOS here is the source.  While I wanted to use Scott’s program, there was the one drawback that almost everything grabs printscreen now so doing a REAL printscreen that hits interrupt 5 seems like it’d actually require a physical PC in MS-DOS.  And my current ‘retro’ PC has no ethernet so I wasn’t going to go that route.

So there is a lot of hacks with this, you can’t even uninstall it, just reboot …. but this hooks the clock, gives you about a minute to go where you want to go, then it saves a portion of the screen to a file, waits a few seconds and hits pagedown, and repeats….

// Written by Scott Hall of the U. of Missouri - Columbia, USA.
// This program will redirect your print screen button so that
// it goes to a file.  The file name is at the beginning of the
// start() function.  It can easily be modified to print screens
// that are larger than 80x25.

#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <dos.h>

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

char far *scr=(char far*)0xb0008000L;
#define VIDMEM 0Xb0008000L
#define INTR 0x1c

int busy=0;                                     // mutual exclusion (MUTEX)
void interrupt (*oldhandler)(__CPPARGS);
char far *old_dta;
char fname[9];

void interrupt int_5();
void tsr(unsigned size);                        // standard tsr bios call
void write_char(int x, int y, char ch, int attrib);
void write_string(int x, int y, char *str, int attrib);

void start(void);
void interrupt handler(__CPPARGS);

int main(int argc, char*argv[])
{
   if(argc==2)
   sprintf(fname,argv[1]);
      else
   sprintf(fname,"log.txt");

   printf ("installing\n");
   disable();
   oldhandler=getvect(INTR);
   setvect(INTR,handler);
   setvect(32,oldhandler);
   enable();
   printf("done\n");
   tsr(1000);
return 0;
}

void tsr(unsigned size)                 // standard tsr bios call
{                                       // you can also use keep()
union REGS r;

r.h.ah = 49;                            // function 0x31
r.h.al = 0;
r.x.dx = size;
int86(0x21,&r, &r);                     // last line executed
}                                       // never get to this line

unsigned char j=0;
unsigned int tcount;
unsigned int dcount=0;

//void interrupt int_5()                  // print screen button starts here
void interrupt handler(__CPPARGS)
{

if(dcount>480)
   {
   if(!busy&&tcount>5)
      {
      char far *p;
      union REGS r;
      struct SREGS s;

      p=scr;
      *p+=6;
      *p++=j;
      *p++=0x4f;

      j++;

      busy = !busy;                   // mutex around tsr
      start();

      r.h.ah=0x5;
      r.h.ch=0x51;    //pagedown?
      r.h.cl=0x0;
      int86x(0x16,&r, &r, &s);

      busy = !busy;
      tcount=0;
      }
   tcount++;
   }
else
   dcount++;
}

void write_char(int x, int y, char ch, int attrib)
{                                       // displays 1 character at (x,y)
char far *v;

v = (char far *) VIDMEM;
v += y*160 + x*2;
*v++ = ch;
*v = attrib;
}

void write_string(int x, int y, char *str, int attrib)
{                                       // writes string str at (x,y)
for( ; *str; str++,x++)
   write_char(x, y, *str, attrib);
}

int firsttime=0;        //need to skip 3 lines after the first time we
//page down.

void start(void)
{
int fd,x,y;
char cr=0x0D, lf=0x0A;

old_dta=getdta();
setdta((char far *)MK_FP(_psp,0x80));

//if((fd =_open("c:\\temp\\log.txt",O_WRONLY))<0) // open the file
//        if((fd =_creat("c:\\temp\\log.txt",_A_NORMAL))<0) // try to make new
//                write_string(1,1,"OOPS--write error1",0x8F);

if((fd =_open(fname,O_WRONLY))<0) // open the file
   if((fd =_creat(fname,_A_NORMAL))<0) // try to make new
   write_string(1,1,"OOPS--write error1",0x8F);

lseek (fd,0,SEEK_END);                          // jump to end of file

//for(y=0;y<25;y++)                               // grab lines 0 to 24
for(y=2+firsttime;y<24;y++)
   {
   //for(x=0;x<80;x++)                       // grab rows 0 through 79
   for(x=1;x<79;x++)                       //cut the bars from msl

   if(_write(fd,(char far *)(VIDMEM+160*y+2*x),1)==-1)
      write_string(1,2,"OOPS--write error2",0x8F);

   if(_write (fd,&cr,1)==-1)               // put a cr and lf at end
      write_string(1,3,"OOPS--write error3",0x8F); // of line

   if(_write (fd,&lf,1)==-1)
      write_string(1,4,"OOPS--write error4",0x8F);
   }

_close(fd);                                     // close the file

setdta(old_dta);
if(firsttime==0)
firsttime=1;
}

Hopefully this will help someone in the distant future, maybe it’ll just serve as a warning on how not to build stuff … lol

Oh and I used Borland C++ 3.1, but compiled this as C for the LARGE memory model.