The PortIO95 Parallel Port Interface

Sample Source: porttest.c

/* ****************************************************************************
 * porttest.c - This file provides code that will test the portio95 vxd.
 *              It also serves as a useful example of how to use the
 *              windows 95 DeviceIoControl function to access VxD's. This code
 *              compiles up into a Win95 32 bit console application. The 32
 *              bitness is required. The DeviceIoControl() function is not 
 *              available to 16 bit Windows or DOS programs.
 *
 *              As written, this program compiles cleanly under Visual C++ 4.0 
 *              using the command line compiler. It is designed to work only
 *              with the PortIO95 parallel port handler VxD. 
 *              
 * Note: This file is best viewed with tab stops of 4
 *
 * DISCLAIMER !!!
 * There is no warranty - you use PortIO95 entirely at your own risk.  Net 2000 Ltd. does
 * not warrant PortIO95's suitability for any purpose, does not guarantee PortIO95's
 * uninterrupted functionality, or even its functionality. Net 2000 Ltd. is not liable
 * for any damage or loss that may occur to you, your computer or the things that your
 * computer is controlling.
 *
 * NOTE: This program uses LPT1 by default. See the variable cPortInUse below to change this.
 *
 * See the PortIO95 documentation and FAQ at http://ds.dial.pipex.com/town/close/ec63 for
 * more information.
 *
 * Copyright (c) 1997 Net 2000 Ltd.
 */
    
#include 
#include 
#include 
#include 
#include "portio95.h"

/* function prototypes */
void Handle_Error(char *);

/* global variables */
HANDLE        hDevice;

char cLPT1;        
char cLPT2;        
char cLPT3;
char cPortInUse;
char szVersionStr[MAX_PORTIO_VERSION_STR_LEN+1];

void main(int ac, char* av[])
    {
    BOOL    retval;
    DWORD    err;

    /* Load the name of the vxd in here where we can pass it as a pointer
     * Note that the format is really "\\.\VXDNAME.VXD" but we have to
     * escape the back slashes with more back slashes because of the
     * special significance the backslash has in C */
    const PCHAR VxDName = "\\\\.\\PORTIO95.VXD";
    printf("\n");
    printf("Preparing to Dynamically Load VxD ->%s\n",VxDName);

    /* the VxD opens just like a regular file. Windows will look for it as follows:
     *   * if it has an .VXD extension
     *     - current directory
     *     - windows directory
     *     - on the path (the autoexec.bat one that win95 sees when it starts)
     *   * if there is no .VXD extension
     *     - in the registry under the KnownVxD's Key
     * see [HAZZAH 227]. The FILE_FLAG_DELETE_ON_CLOSE will cause the VxD to
     * be dynamically removed when the program ends. */
    hDevice = CreateFile(VxDName, 0,0,0,CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);

    /* By now the PortIO95 VxD should be loaded - lets check */
    if (hDevice == INVALID_HANDLE_VALUE)
        {
        /* Get the Last Error Value see also [PortIO95.doc, Appendix A] */
        err = GetLastError();
           printf("Could Not Load VxD, error=%08lx\n", err );

        /* There is one error we have to handle carefully. It implies that
         * the PortIO95 VxD was found ok but didn't handle the dyamic
         * loading properly. This error shouldn't happen. But if it
         * does we cope with it here. We dynamically unload the vxd
         * before we exit. NOTE there is no .VXD extension on this call
         * otherwise you really do delete the VXD file rather than just
         * forcing an unload. */
        if (err == ERROR_NOT_SUPPORTED) DeleteFile("\\\\.\\PORTIO95");
         exit(1);
        }
    printf("VxD ->%s Now loaded\n",VxDName);

    /* now we will make our first call to the PortIO95 vxd to get the version.
     * This is not required but does serve as a nice example of how to accept
     * returning information. The the DeviceIoControl call is documented in 
     * the Win32 sdk, in the VC4.0 help and also in Appendix A of the 
     * PortIO95.docfile. In summary, the DeviceIoControl prototype is:
     *
     *   BOOL DeviceIoControl(
     *            HANDLE  hDevice,            // handle to device of interest 
     *            DWORD   dwIoControlCode,      // control code of operation to perform
     *            LPVOID  lpInBuffer,         // pointer to buffer to supply input data
     *            DWORD   nInBufferSize,      // size of input buffer
     *            LPVOID  lpOutBuffer,        // pointer to buffer to receive output data
     *            DWORD   nOutBufferSize,     // size of output buffer
     *            LPDWORD lpBytesReturned,    // pointer to var to receive output byte count
     *            LPOVERLAPPED  lpOverlapped  // pointer to overlapped structure for asynch op
     *            );    
     *
     * Note: that the lpInBuffer and lpOutBuffer fields pass a pointer to a variable. The
     *       nInBufferSize and nOutBufferSize fields contain the size of the variable in bytes.
     *       The number and type of fields used vary depending on the call. In the case below
     *       in the next call (ie the PORTIO_GETVERSION call) we are not sending any 
     *       information to the Portio95 VxD so the lpInBuffer is NULL and the size is 0. 
     *       We expect a string back so we pass in the address of a string variable and give
     *       its size in the size field. The returning string will be null terminated. The
     *       PortIO95 VxD never uses the lpBytesReturned or lpOverlapped so we just set these
     *       to NULL. See the PortIO95.doc file for a further discussion of this call.
     */

    retval=DeviceIoControl(hDevice, PORTIO_GETVERSION, NULL, 0, &szVersionStr, MAX_PORTIO_VERSION_STR_LEN, NULL, NULL);
    if (!retval) Handle_Error("PORTIO_GETVERSION");
    printf("Version is %s\n",szVersionStr);

    /* now lets find out what LPT ports are available on this PC */
    retval=DeviceIoControl(hDevice, PORTIO_FINDLPT1, NULL, 0, &cLPT1, sizeof(cLPT1), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_FINDLPT1");
    retval=DeviceIoControl(hDevice, PORTIO_FINDLPT2, NULL, 0, &cLPT2, sizeof(cLPT2), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_FINDLPT2");
     retval=DeviceIoControl(hDevice, PORTIO_FINDLPT3, NULL, 0, &cLPT3, sizeof(cLPT3), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_FINDLPT3");

    /* print out what we found */
    if(cLPT1 == '1') printf("LPT1 found\n");
      else printf ("LPT1 not found\n");
    if(cLPT2 == '2') printf("LPT2 found\n");
      else printf ("LPT2 not found\n");
    if(cLPT3 == '1') printf("LPT3 found\n");
      else printf ("LPT3 not found\n");

    /* now lets set the PortIO95 Vxd to use an LPT for its Input and output */
    cPortInUse='1';      /* set it for '1'=LPT1, '2'=LPT2, '3'=LPT3 */
    retval=DeviceIoControl(hDevice, PORTIO_SETPORT, &cPortInUse, sizeof(cPortInUse), NULL, 0, NULL, NULL);
    if (!retval) Handle_Error("PORTIO_SETPORT");
    printf("PortIO95 set to use LPT%c\n",cPortInUse);

    /* we could do lots more in here - but we have done enough
     * for this example. See the other sample source for more
     * information */

    /* unset our port before leaving, this is desireable as it resets things */
    retval=DeviceIoControl(hDevice, PORTIO_UNSETPORT, NULL, 0, NULL, 0, NULL, NULL);

    CloseHandle( hDevice );
    }

/* ********************************************************************
 * Handle_Error - a simple function to print out errors for us
 *               Saves having to put this code after every call
 *
 */
void Handle_Error(char * szErrStr)
        {
        printf("%s DeviceIoControl failed, error=%d\n", szErrStr, GetLastError() );
        exit (1);
        }
    

[Previous] [PortIO95 Home][PortIO95 Source Home] [Next]