Newsgroup: it.comp.lang.c
Titolo: accesso LPT (spero non OT)

Salve a tutti.
Da qualche tempo smanetto con DJGPP. Riesco a fare di tutto in
ambiente WinXP salvo accedere alla LPT con outportb()/inportb():
questo perchè (mi risulta) "because the direct access of hardware
from user mode programms was denied by the operating system".
Naturalmente tutto funziona regolarmente spostandomi su di una
macchina Win98.
Ho trovato in rete dei programmi che dovrebbero (in ambiente XP)
risolvere il problema (uno di questi è Userport) ma la cosa non
ha funzionato.
Qualche idea o suggerimento in proposito?
Grazie a tutti per la disponibilita'
Sandro
-- 
Postato da Alice Newsgroup: lo usi da web ma con le funzioni del newsreader 
http://newsgroup.alice.it
Gerarchie it, italia, it-alt, tin, it.binari. Unico!

 Sandro
DAi un'occhiata qui
http://www.ennepisoft.it

   
Devi realizzare un piccolo driver, se hai il microsoft DDK
la cosa è abbastanza semplice.
Un esempio per W2K/NT (ma va bene anche con XP)
http://www.embeddedtronics.com/design&ideas.html
Cerca userport
Ho scritto un driver funzionante per accedere solo a IO,
se ti interessa te lo invio.
brix

brix99luftballons ha scritto:

già provato userport, non funziona. Cosa intendi per driver?
qualcosa che posso integrare con DJGPP o che scavalca da win i 
privilegi di accesso all' HW?
ciao - S


   
In questo caso è un software che gira a livello di kernel (.sys) e che 
accede
all' hardware mettendo a disposizione degli applicativi una interfaccia.
Il modello driver di Windows (K2K/XP) utilizza i WDM, che sono un
poco complessi, ma e' possibile usare anche dei driver (.SYS) tipo NT
a caricamento dinamico (ovvero quando serve), che e' il tuo caso.
Con DJGPP non so', io li faccio con il DDK di Microsoft.
L' argomento e' un po OT in questo newgroup, spostati su un ng di
programmazione windows ;-)
B.
OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT
Ti allego il source completo di un driver che uso per accedere
a porte di IO, compresa la porta parallela, compilabile con DDK
(Usa "build -c" con DDK)
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// file sources
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
TARGETNAME=pioacc
TARGETPATH=.
TARGETTYPE=DRIVER
INCLUDES=c:\winddk\2600\inc;..\; c:\ddk\inc
SOURCES=tioacc.c
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// end  sources
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// NT-LIKE DRIVER
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <ntddk.h>
#include <MYIOCTL.h>
#define    IOPM_SIZE               (0x2000)
typedef UCHAR IOPM[IOPM_SIZE];
IOPM* lv_IOPM = 0;
void Ke386SetIoAccessMap(int, IOPM *);
void Ke386QueryIoAccessMap(int, IOPM *);
void Ke386IoSetAccessProcess(PEPROCESS, int);
NTSTATUS     IOaccessDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN 
PIRP Irp);
NTSTATUS     PsLookupProcessByProcessId(IN ULONG ulProcId,OUT struct 
_EPROCESS ** pEProcess);
VOID         IOaccessUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS IOaccessCreateDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
)
{
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
)
{
    PDEVICE_OBJECT     deviceObject;
    NTSTATUS         status;
    WCHAR NameBuffer[]    = IOPORT_DEV_NAME;
    WCHAR DOSNameBuffer[] = IOPORT_DOSDEV_NAME ;
    UNICODE_STRING uniNameString, uniDOSString;
    KdPrint( ("IOaccess: V1.0 18/06/2004 has Loaded") );
    lv_IOPM = MmAllocateNonCachedMemory(sizeof(IOPM));
    if(lv_IOPM == 0)
    {
        return (STATUS_INSUFFICIENT_RESOURCES);
    }
    RtlFillMemory(lv_IOPM, sizeof(IOPM), 0xFF);
    KdPrint( ("IOaccess: Memory Allocated at %X\n",lv_IOPM) );
    RtlInitUnicodeString(&uniNameString, NameBuffer);
    RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
    status = IoCreateDevice(DriverObject,
                            0,
                            &uniNameString,
                            FILE_DEVICE_UNKNOWN,
                            0,
                            FALSE,
                            &deviceObject);
    if(!NT_SUCCESS(status))
    {
        return(status);
    }
    status = IoCreateSymbolicLink (&uniDOSString, &uniNameString);
    if (!NT_SUCCESS(status))
    {
        return(status);
    }
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IOaccessCreateDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 
IOaccessDeviceControl;
    DriverObject->DriverUnload = IOaccessUnload;
    return (STATUS_SUCCESS);
}
NTSTATUS
IOaccessDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp
    )
{
    PIO_STACK_LOCATION  irpSp;
    struct _EPROCESS*    Process;
    NTSTATUS            ntStatus;
    ULONG               bufInLen;   /* Input buffer length */
    ULONG               bufOutLen;  /* Output buffer length */
    ULONG               inBuf;      /* Pointer to Input and output buffer */
    ULONG                 ProcessID;
    union{
        PUCHAR              pBufchar;
        PUSHORT             pBufshort;
        PULONG              pBuflong;
        PVOID               pBufIo;
    }pIO;
    USHORT                 Offset;
    UCHAR                 Value;
    irpSp        = IoGetCurrentIrpStackLocation( pIrp );
    bufInLen     = irpSp->Parameters.DeviceIoControl.InputBufferLength;
    bufOutLen    = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
    pIO.pBufIo   = pIrp->AssociatedIrp.SystemBuffer;
     ntStatus = STATUS_SUCCESS;
    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
        case IOCTL_IOPM_LIMIT_ACCESS:
        {
            KdPrint( ("IOACCESS: IOCTL_IOPM_LIMIT_ACCESS - 
RTLFillMemory") );
            RtlFillMemory(lv_IOPM, sizeof(IOPM), 0xFF);
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */
        }break;
          case IOCTL_IOPM_ALLOW_ACCESS:
        {
            KdPrint( ("IOACCESS: IOCTL_IOPM_ALLOW_ACCESS - 
RTLZeroMemory") );
            RtlZeroMemory(lv_IOPM, sizeof(IOPM));
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */
        }break;
          case IOCTL_IOPM_SET:
        {
            KdPrint( ("IOACCESS: IOCTL_IOPM_SET - Set IO Permission 
Bitmap") );
            if (bufInLen >= 3)
            {
                Offset = pIO.pBufshort[0];
                if (Offset >= 0x2000)
                {
                      ntStatus = STATUS_ARRAY_BOUNDS_EXCEEDED;
                      break;
                }
                Value  = pIO.pBufchar[2];
                KdPrint( ("IOACCESS: Offset = %X, Value = 
%X\n",Offset,Value) );
                *(*lv_IOPM + Offset) = Value;
            }
            else
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */
        }break;
          case IOCTL_IOPM_ENABLE_PROCID:
        {
            KdPrint( ("IOACCESS: IOCTL_IOPM_ENABLE_PROCID") );
            if (bufInLen >= 4)
            {
                ProcessID = pIO.pBuflong[0];
                KdPrint( ("IOACCESS: ProcessID Received is 
%d\n",ProcessID) );
                PsLookupProcessByProcessId(ProcessID, &Process);
                KdPrint( ("IOACCESS: Pointer to Process is %X\n",Process) );
                KdPrint( ("IOACCESS: Address = %X\n",*(*lv_IOPM + 0x6F) ) );
                Ke386SetIoAccessMap(1, lv_IOPM);
                Ke386IoSetAccessProcess(Process, 1);
            }
            else
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */
        }break;
          case IOCTL_READ_PORT_BYTE:
        {
            if ((bufInLen >= 2) && (bufOutLen >= 1))
            {
                KdPrint( ("IOACCESS: IOCTL_READ_PORT_BYTE 
0x%X",pIO.pBufshort[0]) );
                (UCHAR)Value = READ_PORT_UCHAR((PUCHAR)pIO.pBufshort[0]);
                KdPrint( ("IOACCESS: Value Read %X",Value) );
                pIO.pBufchar[0] = Value;
            }
            else
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            pIrp->IoStatus.Information = 1; /* Output Buffer Size */
        }break;
          case IOCTL_WRITE_PORT_BYTE:
        {
            if (bufInLen >= 3)
            {
                KdPrint( ("IOACCESS: 
IOCTL_WRITE_PORT_BYTE(0x%X,0x%X)",pIO.pBufshort[0], pIO.pBufchar[2]) );
                WRITE_PORT_UCHAR((PUCHAR)pIO.pBufshort[0], pIO.pBufchar[2]);
            }
            else
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            pIrp->IoStatus.Information = 0; /* Output Buffer Size */
        }break;
          default:
        {
            KdPrint( ("IOACCESS: Unsupported IOCTL Call\n") );
            pIrp->IoStatus.Information = 0;
            ntStatus = STATUS_UNSUCCESSFUL;
        }break;
    }
    pIrp->IoStatus.Status = ntStatus;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    return (ntStatus);
}
VOID IOaccessUnload(IN PDRIVER_OBJECT DriverObject)
{
    WCHAR DOSNameBuffer[] = IOPORT_DOSDEV_NAME;
    UNICODE_STRING uniDOSString;
    KdPrint( ("IOACCESS: IOaccess is Unloading . .\n") );
    if(lv_IOPM)
    {
        MmFreeNonCachedMemory(lv_IOPM, sizeof(IOPM));
    }
    RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
    IoDeleteSymbolicLink (&uniDOSString);
    IoDeleteDevice(DriverObject->DeviceObject);
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// NT-LIKE DRIVER END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// IOCTRL HEADER
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#ifndef _MYIOCTRL_H
#define _MYIOCTRL_H
#define IOPORT_DEV_NAME     L"\\Device\\pioacc"
#define IOPORT_DOSDEV_NAME     L"\\DosDevices\\pioacc"
        /*[-------------------------------------------]
         *[ Device IOCTRL codes                       ]
         *[-------------------------------------------]
         */
#define FILE_MYDEVICE          (35000)       // Legacy definition
#define TIOACCESS_TYPE             (FILE_DEVICE_TECNINT)
#define IOCTL_MSG( code )        CTL_CODE(  \
                                        FILE_MYDEVICE,     \
                                        (code),                         \
                                        METHOD_BUFFERED,      \
                                        FILE_ANY_ACCESS       \
                                     )
#define IOCTL_ETN_DEVICE_INIT            IOCTL_MSG( (TSNIOCT_BASE+0) )
#define IOCTL_IOPM_LIMIT_ACCESS            IOCTL_MSG( (TSNIOCT_BASE+0))
#define IOCTL_IOPM_ALLOW_ACCESS           IOCTL_MSG( (TSNIOCT_BASE+1))
#define IOCTL_IOPM_SET                  IOCTL_MSG( (TSNIOCT_BASE+2))
#define IOCTL_IOPM_ENABLE_PROCID        IOCTL_MSG( (TSNIOCT_BASE+3))
#define IOCTL_READ_PORT_BYTE            IOCTL_MSG( (TSNIOCT_BASE+4))
#define IOCTL_WRITE_PORT_BYTE            IOCTL_MSG( (TSNIOCT_BASE+5))
#endif
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// IOCTRL HEADER END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//  USER DEMO
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int outportb(
    HANDLE            IoDrvHandle,
    unsigned short     PortAddress,
    unsigned char     byte
)
{
    DWORD             BytesReturned;
    unsigned int     err;
    unsigned char     Buffer[8];
    unsigned short* pBuffer;
    if(NULL==IoDrvHandle) { return(-1);  }
    pBuffer = (unsigned short *)&Buffer[0];
    *pBuffer = PortAddress;
    Buffer[2] = byte;
    err = DeviceIoControl(
            IoDrvHandle,
            IOCTL_WRITE_PORT_BYTE,
            &Buffer,
            3,
            NULL,
            0,
            &BytesReturned,
            NULL
    );
    if (!err){return(-1); }
    return(0);
}
int inportb(
    HANDLE           IoDrvHandle,
    unsigned short PortAddress
)
{
    DWORD             BytesReturned;
    unsigned int     err;
    unsigned short* pBuffer;
    unsigned char     Buffer[3];
    pBuffer = (unsigned short *)&Buffer;
    *pBuffer = PortAddress;
    if(NULL==IoDrvHandle) { return(-1);}
    err = DeviceIoControl(
                IoDrvHandle,
                IOCTL_READ_PORT_BYTE,
                 &Buffer,
                 2,
                 &Buffer,
                 1,
                 &BytesReturned,
                 NULL);
    if (!err){  return(-1); }
    return( (Buffer[0] & 0xFF) );
}
unsigned char LoadIOaccessDriver(void)
{
    SC_HANDLE  SchSCManager;
    SC_HANDLE  schService;
    BOOL       ret;
    DWORD      err;
    /*
     * Open Handle to Service Control Manager
     */
    SchSCManager = OpenSCManager (NULL,                        /* 
machine (NULL == local) */
                                  NULL,                        /* 
database (NULL == default) */
                                  SC_MANAGER_ALL_ACCESS);      /* access 
required */
    if (NULL== SchSCManager)
    {
        if (ERROR_ACCESS_DENIED == GetLastError() )
        {
             /*
             * We do not have enough rights to open the SCM, therefore 
we must
              * be a poor user with only user rights.
             */
             printf("\nI/O access: The I/O access driver is NOT 
installed or started!");
             printf("\n You must be an administrator to install the 
driver on your machine.");
             printf("\n Check if You have rights to access the Service 
Control Manager");
             return(0);
        }
    }
    do {
        /*
         * Open a Handle to the IOaccess Service Database
         */
        schService = OpenService(SchSCManager,         /* handle to 
service control manager database */
                                 IO_NT_SERVICE,        /* pointer to 
name of service to start */
                                 SERVICE_ALL_ACCESS);  /* type of access 
to service */
        if (NULL == schService)
        {
            switch (GetLastError())
            {
                case ERROR_ACCESS_DENIED:
                {
                    printf("I/O access: You do not have rights to the 
driver service database\n");
                    return(0);
                }break;
                case ERROR_INVALID_NAME:
                {
                    printf("I/O access: The specified service name is 
invalid.\n");
                    return(0);
                }break;
                case ERROR_SERVICE_DOES_NOT_EXIST:
                {
                    printf("\nI/O access: The driver does not exist.");
                    printf("\nInstalling driver and wait up to 40 
seconds before try again....");
                    InstallIOaccessDriver();
                }break;
            }
        };/*end_switch */
    } while (NULL== schService);
    /*
     * Start the IOaccess Driver.
     * Errors will occur here if IOaccess.SYS file doesn't exist
     */
    ret = StartService (schService,    /* service identifier */
                        0,             /* number of arguments */
                        NULL);         /* pointer to arguments */
    if (ret)
    {
        printf("IOaccess: The IOaccess driver has been successfully 
started.\n");
    }
    else
    {
        err = GetLastError();
        if (err == ERROR_SERVICE_ALREADY_RUNNING)
        {
          printf("IOaccess: The IOaccess driver is already running.\n");
        }
        else
        {
          printf("IOaccess: Unknown error while starting IOaccess driver 
service.\n");
          printf("Does the .SYS driver exist in your " IO_DRV_NAME " 
dir?\n");
          return(0);
        }
    }
    /* Close handle to Service Control Manager */
    CloseServiceHandle (schService);
    return(TRUE);
}
HANDLE io_access_open(void)
{
    /*
     * Open IOaccess Driver. If we cannot open it, try installing and 
starting it
     */
    HANDLE IoDrvHandle;
    IoDrvHandle = CreateFile(
                    IO_ACCESS_NAME,
                    GENERIC_READ,
                    0,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL
                );
    if(IoDrvHandle == INVALID_HANDLE_VALUE)
    {
        /*
         * Start or Install I/O access Driver
         */
        LoadIOaccessDriver();
        /*
         * Then try to open once more, before failing
         */
        IoDrvHandle = CreateFile(
                        IO_ACCESS_NAME,
                        GENERIC_READ,
                        0,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL
                    );
    }
    if(IoDrvHandle == INVALID_HANDLE_VALUE)
    {
        IoDrvHandle =NULL;
    }
    return(IoDrvHandle);
}
void io_access_close(HANDLE IoDrvHandle)
{
    CloseHandle(IoDrvHandle);
}
void InstallIOaccessDriver(void)
{
    SC_HANDLE    SchSCManager;
    SC_HANDLE      schService;
    DWORD          err;
    CHAR        DriverFileName[190];
    /*
     * Get Current Directory.
     *
     * Assumes IOaccess driver is in this directory.
     *
     * Doesn't detect if file exists, nor if file is on removable media -
     * if this is the case then when windows next boots, the driver will
     * fail to load and  a error entry is made in the event viewer to 
reflect
     * this Get System Directory.
     *
     * This should be something like:
     *      c:\windows\system32 or c:\winnt\system32
     * with a Maximum Character lenght of 20.
     */
    if (!GetSystemDirectory(DriverFileName, ((sizeof(DriverFileName))-25) ))
    {
        printf("IOaccess: Failed to get System Directory. Is System 
Directory Path > %u Characters?\n",                  
((sizeof(DriverFileName))-25) );
        printf("IOaccess: Please copy driver to your system32/driver 
directory.\n");
    }
    /*
     * Append our Driver Name
     */
    lstrcat(DriverFileName, IO_DRV_NAME );
    printf("IOaccess: Copying driver to %s\n",DriverFileName);
    /* Copy Driver to System32/drivers directory. This fails if the file 
doesn't exist. */
    if (!CopyFile( IO_DRIVER_NAME, DriverFileName, FALSE))
    {
         printf("IOaccess: Failed to copy driver to %s\n",DriverFileName);
         printf("IOaccess: Please manually copy driver to your 
system32/driver directory.\n");
    }
    /* Open Handle to Service Control Manager */
    SchSCManager = OpenSCManager (NULL,                   /* machine 
(NULL == local) */
                                  NULL,                   /* database 
(NULL == default) */
                                  SC_MANAGER_ALL_ACCESS); /* access 
required */
    /* Create Service/Driver - This adds the appropriate registry keys in */
    /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services - It doesn't  */
    /* care if the driver exists, or if the path is correct.              */
    schService = CreateService (SchSCManager,           /* SCManager 
database */
                                IO_NT_SERVICE,          /* name of 
service */
                                IO_NT_SERVICE,          /* name to 
display */
                                SERVICE_ALL_ACCESS,     /* desired access */
                                SERVICE_KERNEL_DRIVER,  /* service type */
                                SERVICE_DEMAND_START,   /* start type */
                                SERVICE_ERROR_NORMAL,   /* error control 
type       */
                                IO_NT_DRIVER_NAME,        /* service's 
binary       */
                                NULL,                   /* no load 
ordering group */
                                NULL,                   /* no tag 
identifier       */
                                NULL,                   /* no 
dependencies           */
                                NULL,                   /* LocalSystem 
account    */
                                NULL                    /* no password 
              */
                                );
    if (schService == NULL)
    {
        err = GetLastError();
        if (err == ERROR_SERVICE_EXISTS)
            printf("IOaccess: Driver already exists. No action taken.\n");
        else
             printf("IOaccess: Unknown error while creating Service.\n");
    }
    else printf("IOaccess: Driver successfully installed.\n");
    /* Close Handle to Service Control Manager */
    CloseServiceHandle (schService);
}
void removeIOaccessDriver(void)
{
    SC_HANDLE       SchSCManager;
    SC_HANDLE       schService;
    BOOL            ret;
    SERVICE_STATUS  serviceStatus;
    printf("\nIOaccess: Uninstall \n");
    /*
     * Open Handle to Service Control Manager
     */
    SchSCManager = OpenSCManager (
                        NULL,                    // machine (NULL == local)
                        NULL,                    // database (NULL == 
default)
                        SC_MANAGER_ALL_ACCESS ); // access required
    /*
     * Open Handle to IOaccess Service Database
     */
    schService = OpenService ( SchSCManager,
                               IO_NT_SERVICE,
                              SERVICE_ALL_ACCESS);
    if (NULL == schService )
    {
        printf("IOaccess: Error while opening service, check if IOaccess 
is installed.\n");
        return;
    }
    /*
     * Stop Service
     */
    ret = ControlService (schService,
                          SERVICE_CONTROL_STOP,
                          &serviceStatus);
    if (ret)
        printf("IOaccess: service has been successfully stopped.\n");
    else
        printf("IOaccess: Unknown error while stopping service.\n");
    /*
     * Delete Service
     */
    ret = DeleteService (schService);
    if (ret)
        printf("IOaccess: service has been successfully deleted.\n");
    else
        printf("IOaccess: Error removing service.\n");
    printf("You may now re-install a new IOaccess release\n");
    /* Close Handle to Porttalk Service Database */
    CloseServiceHandle (schService);
    /* Close Handle to Service Control Manager */
    CloseServiceHandle(SchSCManager);
}
int testLPT( HANDLE    IoDrvHandle,  int  data)
{
    int value;
    printf("\n Write data: 0x%02X ", (data&0xFF) );
    outportb(IoDrvHandle,0x378, (char)data);
     value = inportb(IoDrvHandle,   0x378);
    printf(" Read back: 0x%02X",value);
    if(value != data)
    {
        printf(" FAILURE!\n");
        return(-1);
    }
    printf(" OK!\n");
    return(0);
}
/////////////////////////////////////////////////
int __cdecl main(int argc, char **argv)
{
    DWORD                      BytesReturned;
    STARTUPINFO             si;    /* Startup Info Structure */
    PROCESS_INFORMATION     pi;    /* Process Info Structure */
    char*    pArg;
    int     value;
    int        err;
    int        port;
    int        data;
    char    mode;
    char    buf[80];
    printf("IoExample for IOaccess V1.0\n");
    mode = 0;
    if (argc > 1)
    {
        pArg= (argv[1]);
        if(*pArg == '-')
        {
            pArg++;
            switch( *pArg )
            {
                case 'S':
                case 's':
                {
                    printf("\nTry to stop the driver...\n");
                    removeIOaccessDriver();
                    return;
                }break;
                /*
                 * Execute a user test program and give it rigth to 
access I/O
                 *
                 * Option: -L <executable.exe> 0x300 0x310
                 *
                 */
                case 'L' :
                case 'l' :
                {
                    int        count;    /* Temp Variable to process 
Auguments */
                    int           value;
                    int        offset;
                    /*
                     * TRy to open the driver....
                     */
                    if(NULL == (lv_IoDrvHandle = io_access_open()))
                    {
                        printf("\n\nIOPort driver access failed!\n");
                        return(-1);
                    }
                    /* Now, we have the driver running, so we must 
restrict the access
                     * to the I/O port filling the driver's IOPM with 0xFF.
                     */
                    err= DeviceIoControl(
                            lv_IoDrvHandle,
                            IOCTL_IOPM_LIMIT_ACCESS,
                            NULL,
                            0,
                            NULL,
                            0,
                            &BytesReturned,
                            NULL);
                    if (!err)
                    {
                        printf("tioacc: error %d occured in 
IOCTL_IOPM_LIMIT_ACCESS\n",GetLastError());
                        io_access_close(lv_IoDrvHandle);
                        return(-2);
                    }
                    argc--;
                    buf[0]=0;    /* NO VALID FILE */
                    for (count = 2; count < argc; count++)
                    {
                        /* If argument starts with '0x' */
                        if ( (argv[count][0] == '0') && (argv[count][1] 
=='x'))
                        {
                            sscanf(argv[count],"%x", &value);
                            offset = value / 8;
                            err = DeviceIoControl(
                                        lv_IoDrvHandle,
                                        IOCTL_IOPM_SET,
                                        &offset,
                                        3,
                                        NULL,
                                        0,
                                        &BytesReturned,
                                        NULL);
                            if (!err)
                            {
                                 printf("FAIL:%d No access to Address 
0x%03X\n",GetLastError(),value);
                            }
                            else
                            {
                                 printf("OK, Address 0x%03X (IOPM Offset 
0x%02X) can be accessed.\n",value,offset);
                            }
                        }
                        else if ((argv[count][0] == '/') && 
(argv[count][1] =='a'))
                        {
                            /*  Set Entire IOPM */
                            printf("Granting exclusive access to all I/O 
Ports\n");
                            err = DeviceIoControl(
                                        lv_IoDrvHandle,
                                        IOCTL_IOPM_ALLOW_ACCESS,
                                        NULL,
                                        0,
                                        NULL,
                                        0,
                                        &BytesReturned,
                                        NULL);
                        }
                        else
                        {
                            /* Must be a Filename */
                            if (strlen(buf) + strlen(argv[count]) > 80)
                            {
                                 printf("Command line exceeds limits\n");
                                io_access_close(lv_IoDrvHandle);
                                return(-3);
                            }
                            strcat(buf,argv[count]);
                            strcat(buf," ");
                            mode = 1;        /* Run a user program to 
test access */
                        }
                    }
                }break;
                default:
                {
                    printf("\nIllegal option,");
                }
                case '?':
                {
                    printf("\nOptions: -S stop driver");
                }break;
            }
        }
        else
        {
            port=(strtol(pArg, NULL, 0));
        }
    }
    else
    {
        while(1)
        {
            printf("\nEnter the IO port : ");
            port=0;
            if(NULL != gets(buf))
            {
                port = strtol(buf,NULL,0);
            }
            if(0==port)
                port=0x300;        /* Use default */
            else
            {
                if((port< 0x100) || (port > 0x3FF))
                {
                     printf("\n0x%03X (%u) is NOT a valid port!", 
port,port);
                    continue;
                }
            }
            break;
        }
    }
    printf("\n\nDEMO test port: 0x%X \n", port);
    if(NULL == (lv_IoDrvHandle = io_access_open()))
    {
        printf("\n\nIOPort driver access failed!\n");
        return(-4);
    }
        /*
         * Test the access writing and reading from standard LPT1
         * pheriperal....
         */
        testLPT(lv_IoDrvHandle,0x55);
        testLPT(lv_IoDrvHandle,0xAA);
    io_access_close(lv_IoDrvHandle);
    return(0);
}
OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT-OT