home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advos2 / ch18 / snap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-12  |  12.5 KB  |  339 lines

  1. /*
  2.         SNAP.C  
  3.  
  4.         A sample OS/2 device monitor that captures the current 
  5.         display into the file SNAPxx.IMG, where xx is the 
  6.         session number.  SNAP works in character mode only and
  7.         and may not be used in a PM window.  The following keys
  8.         are defined as defaults:
  9.  
  10.     Alt-F10   hot key to capture a screen
  11.     Ctrl-F10  hot key to deinstall SNAP.EXE
  12.  
  13.         Compile with:  C> cl /F 2000 snap.c
  14.  
  15.         Usage is:  C> snap
  16.  
  17.         Copyright (C) 1988 Ray Duncan
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22.  
  23.                     /* hot key definitions */
  24. #define SNAPKEY  0x71                   /* Alt-F10 to capture screen */
  25. #define EXITKEY  0x67                   /* Ctrl-F10 to exit */
  26.  
  27. #define STKSIZE  2048                   /* stack size for threads */
  28.  
  29. #define WAIT     0                      /* parameters for DosMonRead */
  30. #define NOWAIT   1                      /* and DosMonWrite */
  31.  
  32. #define API unsigned extern far pascal  /* API function prototypes */
  33.  
  34. API DosBeep(unsigned, unsigned);
  35. API DosBufReset(unsigned);
  36. API DosClose(unsigned); 
  37. API DosCloseSem(unsigned long far *);
  38. API DosCreateThread(void (far *)(), unsigned far *, void far *);
  39. API DosCreateSem(unsigned, unsigned long far *, char far *);
  40. API DosExecPgm(char far *, int, int, char far *, char far *, 
  41.                int far *, char far *);
  42. API DosExit(unsigned, unsigned);
  43. API DosGetInfoSeg(unsigned far *, unsigned far *);
  44. API DosMonClose(unsigned);
  45. API DosMonOpen(char far *, unsigned far *);
  46. API DosMonRead(void far *, unsigned, char far *, int far *);
  47. API DosMonReg(unsigned, void far *, void far *, int, unsigned);
  48. API DosMonWrite(void far *, char far *, int);
  49. API DosOpen(char far *, unsigned far *, unsigned far *, unsigned long,
  50.             unsigned, unsigned, unsigned, unsigned long);           
  51. API DosOpenSem(unsigned long far *, char far *);
  52. API DosSemClear(unsigned long far *);
  53. API DosSemSet(unsigned long far *);
  54. API DosSemWait(unsigned long far *, unsigned long);
  55. API DosSetPrty(int, int, int, int);
  56. API DosSleep(unsigned long);
  57. API DosSuspendThread(unsigned);
  58. API DosWrite(unsigned, void far *, int, unsigned far *);
  59. API VioEndPopUp(unsigned);
  60. API VioGetMode(void far *, unsigned);
  61. API VioPopUp(unsigned far *, unsigned);
  62. API VioReadCharStr(char far *, int far *, int, int, unsigned);
  63. API VioWrtCharStr(char far *, int, int, int, unsigned);
  64.  
  65. void signon(void);                      /* local function prototypes */
  66. void signoff(void);
  67. void popup(unsigned);
  68. void unpop(void);
  69. void far snap(void);
  70. void far watch(void);
  71. void errexit(char *);
  72.  
  73.                                         /* RAM semaphores */
  74. unsigned long exitsem = 0;        /* exit hot key semaphore */
  75. unsigned long snapsem = 0;              /* screen snapshot semaphore */
  76.  
  77. char sname[20];                         /* system semaphore name */
  78. unsigned long shandle = 0;              /* system semaphore handle */
  79.  
  80. char fname[20];             /* snapshot filename */
  81. unsigned fhandle = 0;                   /* snapshot file handle */
  82.  
  83. char kname[] = "KBD$";                  /* keyboard device name */
  84. unsigned khandle = 0;                   /* keyboard monitor handle */
  85.  
  86. struct _monbuf {                        /* monitor input and */
  87.     int len;                            /* output buffers */
  88.     char buf[128];
  89.     } kbdin  = { sizeof(kbdin.buf)  } , 
  90.       kbdout = { sizeof(kbdout.buf) } ;
  91.  
  92. struct _vioinfo {                       /* display mode info */
  93.     int len;
  94.     char type;
  95.     char colors;
  96.     int cols;
  97.     int rows;
  98.     } vioinfo;
  99.  
  100. char msg1[] = "SNAP utility installed!";
  101. char msg2[] = "Alt-F10 to capture screen image into file SNAP.IMG,";
  102. char msg3[] = "Ctrl-F10 to shut down SNAP.";
  103. char msg4[] = "SNAP utility deactivated.";
  104. char msg5[] = "Error detected during SNAP installation:";
  105.  
  106. main()
  107. {
  108.     char obuff[80];                     /* object name buffer */
  109.     int retcode[2];                     /* receives child info */
  110.  
  111.     unsigned gseg, lseg;                /* receives selectors */
  112.     char far *ginfo;            /* global info segment pointer */
  113.  
  114.     unsigned snapID, watchID;           /* receives thread IDs */
  115.     char snapstk[STKSIZE];              /* snapshot thread stack */
  116.     char watchstk[STKSIZE];             /* keyboard thread stack */
  117.  
  118.     DosGetInfoSeg(&gseg, &lseg);    /* get info segment selectors */
  119.     (long) ginfo = (long) gseg << 16;   /* make far pointer */
  120.  
  121.                     /* build semaphore and file names */
  122.     sprintf(sname, "\\SEM\\SNAP%02d.LCK", ginfo[0x18]);
  123.     sprintf(fname, "\\SNAP%02d.IMG",      ginfo[0x18]);
  124.  
  125.     if(DosOpenSem(&shandle, sname))     /* does \SEM\SNAPxx.LCK exist? */
  126.     {
  127.                                         /* no, we're parent SNAP */
  128.                                         /* create system semaphore */
  129.         if(DosCreateSem(1, &shandle, sname))
  130.             errexit("Can't create SNAP system semaphore.");
  131.         DosSemSet((unsigned long far *) shandle);
  132.  
  133.                                         /* start detached child SNAP */
  134.         if(DosExecPgm(obuff, sizeof(obuff), 4, NULL, NULL, retcode, "snap.exe"))
  135.             errexit("Can't start child copy of SNAP.");
  136.  
  137.                                         /* wait for child to load */
  138.         DosSemWait((unsigned long far *) shandle, -1L);
  139.         DosCloseSem((unsigned long far *) shandle);
  140.     }
  141.     else                                /* if SNAPxx.LCK exists, */
  142.     {                                   /* we're the child SNAP */
  143.  
  144.                                         /* abort if already resident */
  145.         if(! DosSemWait((unsigned long far *) shandle, 0L))
  146.             errexit("SNAP is already loaded.");
  147.  
  148.         DosSemSet(&exitsem);            /* initialize exit and */
  149.         DosSemSet(&snapsem);            /* snapshot semaphores */
  150.     
  151.         if(DosMonOpen(kname, &khandle)) /* open monitor connection */
  152.             errexit("Can't open KBD$ monitor connection.");
  153.  
  154.                                         /* register at head of chain */
  155.         if(DosMonReg(khandle, &kbdin, &kbdout, 1, ginfo[0x18]))
  156.             errexit("Can't register as KBD$ monitor.");
  157.  
  158.                                         /* create keyboard thread */
  159.         if(DosCreateThread(watch, &watchID, watchstk+STKSIZE))
  160.             errexit("Can't create keyboard thread.");
  161.  
  162.         DosSetPrty(2, 3, 0, watchID);   /* promote keyboard thread */
  163.  
  164.                                         /* create snapshot thread */
  165.         if(DosCreateThread(snap, &snapID, snapstk+STKSIZE))
  166.             errexit("Can't create snapshot thread.");
  167.  
  168.         signon();                       /* announce installation */
  169.  
  170.                                         /* tell parent we're running */
  171.         DosSemClear((unsigned long far *) shandle);
  172.  
  173.     DosSemWait(&exitsem, -1L);    /* wait for exit hot key */
  174.  
  175.         DosSuspendThread(snapID);       /* suspend snapshot thread */
  176.         DosSuspendThread(watchID);      /* suspend keyboard thread */
  177.         DosMonClose(khandle);           /* close monitor connection */
  178.                                         /* close system semaphore */
  179.         DosCloseSem((unsigned long far *) shandle);
  180.         DosClose(fhandle);              /* close snapshot file */
  181.  
  182.     signoff();            /* announce deinstallation */
  183.     }
  184.  
  185.     DosExit(1, 0);                      /* final exit */
  186. }
  187.  
  188. /*
  189.     The 'watch' thread is responsible for monitoring the keyboard
  190.     data stream.  It clears the 'snapsem' semaphore when the 
  191.     screen capture hot key is detected and clears the 'exitsem'
  192.     semaphore when the deinstall hot key is detected.
  193. */
  194. void far watch(void)
  195. {
  196.     char kbdpkt[128];                   /* monitor data packet */
  197.     int kbdpktlen;                      /* data packet length */
  198.  
  199.     while(1)
  200.     {
  201.         kbdpktlen = sizeof(kbdpkt);     /* set buffer length */
  202.  
  203.                                         /* read monitor data */
  204.         DosMonRead(&kbdin, WAIT, kbdpkt, &kbdpktlen);
  205.  
  206.                     /* check for hot keys */
  207.                                         /* ignore key breaks */
  208.         if((kbdpkt[2] == 0) && (kbdpkt[3] == EXITKEY))
  209.     {                /* exit hot key detected */
  210.             if(kbdpkt[12] == 0) DosSemClear(&exitsem);
  211.         }
  212.         else if((kbdpkt[2] == 0) && (kbdpkt[3] == SNAPKEY))
  213.     {                /* snapshot hot key detected */
  214.             if(kbdpkt[12] == 0) DosSemClear(&snapsem);
  215.     }                /* not hot key, pass it through */
  216.         else DosMonWrite(&kbdout, kbdpkt, kbdpktlen);
  217.     }
  218. }
  219.  
  220. /*
  221.     The 'snap' thread blocks on the 'snapsem' semaphore until it
  222.     is cleared by the 'watch' thread, then captures the current
  223.     screen contents into the snapshot file.
  224. */
  225. void far snap(void)
  226. {
  227.     int i;                              /* scratch variable */
  228.     unsigned action;                    /* receives DosOpen action */
  229.     unsigned wlen;                      /* receives DosWrite length */
  230.     char divider[81];                   /* snapshot divider line */
  231.     char scrbuf[80];                    /* receives screen data */
  232.     int slen;                           /* contains buffer size */
  233.  
  234.     memset(divider, '-', 79);           /* initialize divider line */
  235.     divider[79] = 0x0d;
  236.     divider[80] = 0x0a;
  237.  
  238.                                         /* create/replace snapshot file */
  239.     if(DosOpen(fname, &fhandle, &action, 0L, 0, 0x12, 0x21, 0L))
  240.         errexit("Can't create snapshot file.");
  241.  
  242.     while(1)
  243.     {                                   /* write divider line */
  244.         DosWrite(fhandle, divider, sizeof(divider), &wlen);
  245.         DosBufReset(fhandle);           /* force file update */
  246.  
  247.     DosSemWait(&snapsem, -1L);    /* wait for hot key */
  248.  
  249.     popup(3);            /* pop-up in transparent mode */
  250.         vioinfo.len = sizeof(vioinfo);  /* get screen dimensions */
  251.         VioGetMode(&vioinfo, 0);
  252.  
  253.         for(i = 0; i < vioinfo.rows; i++)
  254.         {
  255.             slen = vioinfo.cols;        /* read line from screen */
  256.             VioReadCharStr(scrbuf, &slen, i, 0, 0);
  257.  
  258.                                         /* discard trailing spaces */
  259.             while((slen > 0) && (scrbuf[slen-1] == 0x20)) slen--;
  260.  
  261.                                         /* write line to file */
  262.             DosWrite(fhandle, scrbuf, slen, &wlen); 
  263.             DosWrite(fhandle, "\x0d\x0a", 2, &wlen);
  264.         }
  265.  
  266.         DosBeep(440, 200);              /* reward the user */
  267.         unpop();                        /* release screen */
  268.         DosSemSet(&snapsem);            /* reset snapshot semaphore */
  269.     }
  270. }
  271.  
  272. /*
  273.     Display the installation and help messages in popup window.
  274. */
  275. void signon(void)
  276. {
  277.     popup(1);                           /* acquire popup screen */
  278.     VioWrtCharStr(msg1, sizeof(msg1), 10, ((80-sizeof(msg1))/2), 0);
  279.     VioWrtCharStr(msg2, sizeof(msg2), 13, ((80-sizeof(msg2))/2), 0);
  280.     VioWrtCharStr(msg3, sizeof(msg3), 15, ((80-sizeof(msg3))/2), 0);
  281.     DosSleep(4000L);            /* pause for 4 seconds */
  282.     unpop();                            /* release popup screen */
  283. }
  284.  
  285. /*
  286.     Display exit message in popup window.
  287. */
  288. void signoff(void)                      
  289. {
  290.     popup(1);                           /* acquire popup screen */
  291.     VioWrtCharStr(msg4, sizeof(msg4), 12, ((80-sizeof(msg4))/2), 0);
  292.     DosSleep(2000L);            /* pause for 2 seconds */
  293.     unpop();                            /* release popup screen */
  294. }
  295.  
  296. /*
  297.     Get popup screen, using wait/no-wait and
  298.     transparent/nontransparent flags supplied by caller.
  299. */
  300. void popup(unsigned pflags)
  301. {
  302.     VioPopUp(&pflags, 0);   
  303. }
  304.  
  305. /*
  306.     Take down popup screen.
  307. */
  308. void unpop(void)
  309. {
  310.     VioEndPopUp(0);
  311. }
  312.  
  313. /*
  314.     Common error exit routine.  Display error message on popup
  315.     screen and terminate process.
  316. */
  317. void errexit(char *errmsg)
  318. {
  319.     if(khandle != 0)                    /* close monitor handle */
  320.         DosMonClose(khandle);           /* if monitor active */
  321.  
  322.     if(shandle != 0)                    /* clear and close the */
  323.     {                                   /* SNAPxx.LCK semaphore */
  324.         DosSemClear((unsigned long far *) shandle);
  325.         DosCloseSem((unsigned long far *) shandle);
  326.     }
  327.  
  328.     popup(1);                           /* get popup screen and */
  329.                                         /* display error message */
  330.     VioWrtCharStr(msg5, sizeof(msg5), 10, ((80-sizeof(msg5))/2), 0);
  331.     VioWrtCharStr(errmsg, strlen(errmsg), 12, ((80-strlen(errmsg))/2), 0);
  332.     DosSleep(3000L);            /* let user read message */
  333.     unpop();                            /* release popup screen */
  334.     DosExit(1, 1);            /* terminate, exitcode = 1 */
  335. }                                       
  336.  
  337.  
  338. 
  339.