开发dos虚拟机程序(续)

     dos虚拟机本来是老玩意儿了,没想到一直有朋友关心,现在就把开发dos虚拟机的文章写完,介绍一下开发串口通信程序。先用一条短接线把PC机串口的收发短接,这样就能实现自发自收了,再来一段C程序:

 

#include "stdio.h"

 

void main(void)
{
 unsigned char byteID;
 
 __asm
 {

//初始化串口,9600,无校验,1位停止位
  mov al,80H
  mov dx,03FBH
  out dx,al
  mov al,0CH
  mov dx,03F8H
  out dx,al
  mov al,00H
  mov dx,03F9H
  out dx,al
  mov al,03H
  mov dx,03FBH
  out dx,al
  mov al,00H
  mov dx,03F9H
  out dx,al

 

//发送字节01h

  mov dx,03FDH
COM_OUT1:
  in al,dx
  test al,20H
  je COM_OUT1
  mov al,01H        //在这里可以修改发送字节
  mov dx,03F8H
  out dx,al

 

//接收字节

  MOV DX,03FDH
COM_IN1:
  in al,dx
                TEST al,01H
  JE COM_IN1
  MOV DX,03F8H
  in al,dx
  MOV byteID,al
 }

 

//显示接收的字节

  printf ("SampleService0 returned = %x/n", byteID);

} // main

 

    用16位的编译器编译后成一个exe文件,在dos操作系统下运行就能看到显示结果了。因为windows操作系统禁止直接操作硬件设备,这样的程序在windows下是不能跑的。

 

    下面我们就来虚拟一个串口设备,让它在windows下跑起来。先来一段C程序:

 

#include "stdio.h"

#define PORT_IDENTIFY   0x300
#define PORT_READ       0x301
#define PORT_WRITE      0x302


void main(void)
{
 unsigned char byteIDi;

 _asm  mov  dx, PORT_IDENTIFY
 _asm  in   al, dx
 _asm  mov  byteID, al

 

   printf("Port I/O: ID %d read from port 0x%x/n",
      byteID, PORT_IDENTIFY);

   _asm  mov  dx, PORT_WRITE
   _asm  mov  al, 01H
   _asm  out  dx, al

 
   _asm  mov  dx, PORT_READ
    _asm  in   al, dx
    _asm  mov  byteID, al

  printf ("SampleService0 returned = %x/n", byteID);
} // main

 

    这段程序虚拟的串口定义了三个端口:0x300,0x301,0x302,通过读0x300端口判断虚拟串口设备是否存在,然后往0x302端口写了一个01h,再读0x301端口的字节。

 

    只有这样一个文件是没法跑的,还需要有一个vdd来截取这些操作,要整一个vdd出来需要以下五个源文件:

1,iovdd.c

 

// IOVDD.C - Demonstate port and memory-mapped I/O

#include <windows.h>
#include <vddsvc.h>
#include <winioctl.h>
#include "iovdd.h"

typedef struct  _GENPORT_WRITE_INPUT {
    ULONG   PortNumber;     // Port # to write to
    union   {               // Data to be output to port
        ULONG   LongData;
        USHORT  ShortData;
        UCHAR   CharData;
    };
}   GENPORT_WRITE_INPUT;

// Function Prototypes
BOOL VDDLibMain(HINSTANCE, ULONG, LPVOID);
VOID IoVDD_ReadByte(WORD wPort, PBYTE byteData);
VOID IoVDD_WriteByte(WORD wPort, BYTE byteData);
VOID IoVDD_Memory(ULONG ulAddress, ULONG RWFlags);
VOID Debug(LPSTR szDebug);

// Globals
HANDLE hVDD = NULL;
VDD_IO_PORTRANGE portRange;
ULONG ulAddr;
PBYTE pMem;
BYTE byteStatus = 0;
BYTE byteCount = 0;
BOOL bIoHooked = FALSE;
BOOL bMemHooked= FALSE;
BOOL bMemAllocated = FALSE;
BOOL bDebug = TRUE;

HANDLE hDevice=NULL;
/**---------------------------------------------**/
BOOL VDDLibMain(HINSTANCE hInst, ULONG ulReason,
   LPVOID lpRsrv)
{
   VDD_IO_HANDLERS ioHandlers;
   hVDD = hInst;
  
   switch(ulReason)
   {
      case DLL_PROCESS_ATTACH:
/*   hDevice = CreateFile((LPTSTR)".//simpldrv",
            GENERIC_READ | GENERIC_WRITE, 0, NULL,
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
*/
         Debug("IOVDD: VDDLibMain - Attach/n");

         portRange.First = IOVDD_PORT_START;
         portRange.Last  = IOVDD_PORT_END;

         ioHandlers.inb_handler   = IoVDD_ReadByte;
         ioHandlers.inw_handler   = NULL;
         ioHandlers.insb_handler  = NULL;
         ioHandlers.insw_handler  = NULL;
         ioHandlers.outb_handler  = IoVDD_WriteByte;
         ioHandlers.outw_handler  = NULL;
         ioHandlers.outsb_handler = NULL;
         ioHandlers.outsw_handler = NULL;

         if (!(bIoHooked = VDDInstallIOHook(hVDD,
            1, &portRange, &ioHandlers)))
         {
            Debug("IOVDD: Port hook failed");
            return FALSE;
         }
/*
         ulAddr = (ULONG)MAKELONG(0, 0xCC00);
         pMem = (PBYTE)GetVDMPointer(ulAddr,
            IOVDD_MIO_RANGE, 0);
         if (!(bMemHooked = VDDInstallMemoryHook(
            hVDD, pMem, IOVDD_MIO_RANGE,
            (PVDD_MEMORY_HANDLER)IoVDD_Memory)))
         {
            Debug("IOVDD: Memory hook failed");
            return FALSE;
         }*/
         break;

      case DLL_PROCESS_DETACH:
         Debug("IOVDD: VDDLibMain - Detach/n");
         if (bIoHooked)
            VDDDeInstallIOHook(hVDD, 1, &portRange);

   CloseHandle(hDevice);
/*         if (bMemHooked)
            VDDDeInstallMemoryHook(hVDD, pMem,
               IOVDD_MIO_RANGE);
         if (bMemAllocated)
            VDDFreeMem(hVDD, (PVOID)pMem,
               IOVDD_MIO_RANGE);
         if (pMem)
            FreeVDMPointer(ulAddr, IOVDD_MIO_RANGE,
               pMem, FALSE);*/
         break;

      default: break;
   }

   return TRUE;
} // VDDLibMain

/**---------------------------------------------**/
VOID IoVDD_ReadByte(WORD wPort, PBYTE byteData)
{
//   HANDLE hDevice=NULL;
   DWORD dwCount=0L;
  
   ULONG PortNumber = wPort;
   HANDLE hComm;

   // handle ports that apps reads from
   switch(wPort)
   {
      case IOVDD_PORT_IDENTIFY:
         Debug("IOVDD: IOVDD_PORT_IDENTIFY/n");
        
         hComm = CreateFile("com1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);  
     if(INVALID_HANDLE_VALUE==hComm)
        {
//      int err=GetLastError();
      Debug("Error in open COM port: com1./n");  
//      return FALSE;
     }
         hDevice = CreateFile((LPTSTR)".//simpldrv",
            GENERIC_READ | GENERIC_WRITE, 0, NULL,
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//         DeviceIoControl(hDevice, (DWORD)IOCTL_SIMPLDRV_HELLO,
//            NULL, 0, byteData, 1, &dwCount, NULL);

      DeviceIoControl(
                            hDevice,            // Handle to device
                            (DWORD)IOCTL_SIMPLDRV_HELLO,          // IO Control code for Read
                            &PortNumber,        // Buffer to driver.
                            sizeof(PortNumber), // Length of buffer in bytes.
                            byteData,        // Buffer from driver.
                            1,         // Length of buffer in bytes.
                            &dwCount,    // Bytes placed in DataBuffer.
                            NULL                // NULL means wait till op. completes.
                            );
//         CloseHandle(hDevice);
         break;

//      case IOVDD_PORT_STATUS:
      case 0x301:
         Debug("IOVDD: IOVDD_PORT_STATUS/n");
//         *byteData = byteStatus;

      DeviceIoControl(
                            hDevice,            // Handle to device
                            (DWORD)IOCTL_SIMPLDRV_HELLO,          // IO Control code for Read
                            &PortNumber,        // Buffer to driver.
                            sizeof(PortNumber), // Length of buffer in bytes.
                            byteData,        // Buffer from driver.
                            1,         // Length of buffer in bytes.
                            &dwCount,    // Bytes placed in DataBuffer.
                            NULL                // NULL means wait till op. completes.
                            );
         break;
/*
      case IOVDD_PORT_COUNT:
         Debug("IOVDD: IOVDD_PORT_COUNT/n");
         *byteData = byteCount;
         break;
*/
      default:
         Debug("IOVDD: Unsupported port read/n");
         break;
   }

   return;
} // IoVDD_ReadByte

/**---------------------------------------------**/
VOID IoVDD_WriteByte(WORD wPort, BYTE byteData)
{
//   HANDLE hDevice=NULL;
/*   DWORD dwCount=0L;

   // handle ports that apps write to
   switch(wPort)
   {
      case IOVDD_PORT_READ:
         Debug("IOVDD: IOVDD_PORT_READ/n");
         byteStatus = FALSE;
         // request kernel-mode driver to read,
         // when read completes, set status
         if (byteCount > 35) byteCount = 35;
         memcpy(pMem,
            "This would be data read from device",
            byteCount);
         byteStatus = TRUE;
         break;
                 
      case IOVDD_PORT_WRITE:
         Debug("IOVDD: IOVDD_PORT_WRITE/n");
         byteStatus = FALSE;
         // request kernel-mode driver to write,
         // when write request completes, set status
         byteStatus = TRUE;
         break;

      case IOVDD_PORT_COUNT:
         Debug("IOVDD: IOVDD_PORT_COUNT/n");
         // this is how many bytes to write
         byteCount = byteData;
         if (byteCount > IOVDD_MIO_RANGE)
            byteCount = IOVDD_MIO_RANGE;
         break;
        
      case IOVDD_PORT_READ:
     
      default:
         Debug("IOVDD: Unsupported port write/n");
         break;
   }*/
  
 GENPORT_WRITE_INPUT InputBuffer;
 DWORD   ReturnedLength;
 InputBuffer.PortNumber = wPort;
 InputBuffer.CharData = byteData;
 DeviceIoControl(
       hDevice,                // Handle to device
       (DWORD)IOCTL_GPD_WRITE_PORT_UCHAR,              // IO Control code for Write
       &InputBuffer,           // Buffer to driver.  Holds port & data.
       5,             // Length of buffer in bytes.
       NULL,                   // Buffer from driver.   Not used.
       0,                      // Length of buffer in bytes.
       &ReturnedLength,        // Bytes placed in outbuf.  Should be 0.
       NULL                    // NULL means wait till I/O completes.
       );
// byteData = InputBuffer.CharData;
 byteStatus = TRUE;

   return;
} // IoVDD_WriteByte

/**---------------------------------------------
VOID IoVDD_Memory(ULONG ulAddress, ULONG RWFlags)
{
   Debug("IOVDD: IoVDD_Memory/n");
   bMemAllocated = VDDAllocMem(hVDD, pMem,
      IOVDD_MIO_RANGE);
   return;
} // IoVDD_Memory

/**---------------------------------------------**/
VOID Debug(LPSTR szDebug)
{
   if (bDebug) OutputDebugString(szDebug);
} // Debug

// end of file

2,iovdd.h

 

// IOVDD.H - Include file for SIMPLVDD.C

#define IOVDD_PORT_START      0x300
#define IOVDD_PORT_END        0x304

#define IOVDD_PORT_IDENTIFY   0x300
//#define IOVDD_PORT_READ       0x301
//#define IOVDD_PORT_WRITE      0x302
//#define IOVDD_PORT_COUNT      0x303
#define IOVDD_PORT_STATUS     0x304

#define IOVDD_MIO_SEG   0xCC00
#define IOVDD_MIO_ADDR  (((ULONG)IOVDD_MIO_SEG) << 16)
#define IOVDD_MIO_RANGE 128+1

// SimplDrv information
#define FILE_DEVICE_SIMPLDRV     0x00008300
#define SIMPLDRV_IOCTL_INDEX     0x830
#define IOCTL_SIMPLDRV_HELLO    CTL_CODE(FILE_DEVICE_SIMPLDRV, /
   SIMPLDRV_IOCTL_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_GPD_WRITE_PORT_UCHAR /
    CTL_CODE(FILE_DEVICE_SIMPLDRV, SIMPLDRV_IOCTL_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
   
// end of file

3,iovdd.def

 

; IOVDD.DEF - Module definition file for IOVDD.DLL
LIBRARY IOVDD
;DESCRIPTION 'VDD to demonstrate port I/O trapping

EXPORTS
   VDDLibMain

; end of file

4,SOURCES

 

TARGETNAME=iovdd
TARGETPATH=obj
TARGETTYPE=DYNLINK

TARGETLIBS=$(BASEDIR)/lib/*/$(DDKBUILDENV)/kernel32.lib  /
       $(BASEDIR)/lib/*/$(DDKBUILDENV)/user32.lib /
       $(BASEDIR)/lib/*/$(DDKBUILDENV)/advapi32.lib /
    $(BASEDIR)/lib/*/$(DDKBUILDENV)/ntvdm.lib

DLLENTRY=VDDLibMain
DLLBASE=0x2000000

SOURCES=iovdd.c

INDENTED_DIRECTIVES=1

C_DEFINES=-DWIN_32 -DDEBUG

5,MAKEFILE

 

# Sample VDD makefile
#
# Copyright (c) 1991, Microsoft Corporation
#
# History:
#   Created 16-Dec-1991 Sudeep Bharati (sudeepb)
#


# DO NOT EDIT THIS FILE!!!  Edit ./sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the components of NT OS/2
#
!INCLUDE $(NTMAKEENV)/makefile.def

    有了这五个源文件,就能用DDK build生成一个iovdd.dll文件了。要让这个vdd起作用,需要把这个dll文件拷到windows/system32目录下,重命名为iovdd1.dll。还需要修改注册表,为了方便广大人民群众,我有整了一个修改注册表的文件iovdd.reg:

 

Windows Registry Editor Version 5.00 

[HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Control/VirtualDeviceDrivers] 
"VDD"=hex(7):69,00,6F,00,76,00,64,00,64,00,31,00,2E,00,64,00,6C,00,6C,00

 

    什么乱七八糟的?双击后运行就知道了。为什么要把iovdd.dll改名为iovdd1.dll,因为我发现vdd好像必须要有六个字符才能起作用。再要问为什么需要六个字符?只有微软的人能回答了。

 

    现在截取操作的vdd有了,再把它们发送到相应的内核模式驱动程序就大功告成了。现在来写内核驱动程序。编译内核驱动程序需要以下四个文件:

1,simpldrv.c

 

/*++

Copyright (c) 1993  Microsoft Corporation

Module Name:

    simpldrv.c

Abstract:

    A simple kernel-mode driver sample.

Environment:

    kernel mode only

Notes:

    See readme.txt

Revision History:

    06-25-93 : created

--*/

#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
#include "simpldrv.h"

//
// The following is the debug print macro- when we are building checked
// drivers "DBG" will be defined (by the /ddk/setenv.cmd script), and we
// will see debug messages appearing on the KD screen on the host debug
// machine. When we build free drivers "DBG" is not defined, and calls
// to SimplDrvKdPrint are removed.
//

typedef struct  _GENPORT_WRITE_INPUT {
    ULONG   PortNumber;     // Port # to write to
    union   {               // Data to be output to port
        ULONG   LongData;
        USHORT  ShortData;
        UCHAR   CharData;
    };
}   GENPORT_WRITE_INPUT;

#ifdef DBG
#define SimplDrvKdPrint(arg) DbgPrint arg
#else
#define SimplDrvKdPrint(arg)
#endif

 

NTSTATUS
SimplDrvDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

VOID
SimplDrvUnload(
    IN PDRIVER_OBJECT DriverObject
    );

 

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path
                   to driver-specific key in the registry

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/
{

    PDEVICE_OBJECT         deviceObject        = NULL;
    NTSTATUS               ntStatus;
    WCHAR                  deviceNameBuffer[]  = L"//Device//SimplDrv";
    UNICODE_STRING         deviceNameUnicodeString;
    PDEVICE_EXTENSION      deviceExtension;
    WCHAR                  deviceLinkBuffer[]  = L"//DosDevices//SIMPLDRV";
    UNICODE_STRING         deviceLinkUnicodeString;


    SimplDrvKdPrint (("SIMPLDRV.SYS: entering DriverEntry/n"));

 

    //
    // A real driver would:
    //
    //     1. Report it's resources (IoReportResourceUsage)
    //
    //     2. Attempt to locate the device(s) it supports

 

    //
    // OK, we've claimed our resources & found our h/w, so create
    // a device and initialize stuff...
    //

    RtlInitUnicodeString (&deviceNameUnicodeString,
                          deviceNameBuffer
                          );

 

    //
    // Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
    // i/o requests.
    //

    ntStatus = IoCreateDevice (DriverObject,
                               sizeof (DEVICE_EXTENSION),
                               &deviceNameUnicodeString,
                               FILE_DEVICE_SIMPLDRV,
                               0,
                               TRUE,
                               &deviceObject
                               );

    if (NT_SUCCESS(ntStatus))
    {
        deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;

 

        //
        // Set up synchronization objects, state info,, etc.
        //

 

        //
        // Create a symbolic link that Win32 apps can specify to gain access
        // to this driver/device
        //

        RtlInitUnicodeString (&deviceLinkUnicodeString,
                              deviceLinkBuffer
                              );

        ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                         &deviceNameUnicodeString
                                         );


        if (!NT_SUCCESS(ntStatus))
        {
            SimplDrvKdPrint (("SIMPLDRV.SYS: IoCreateSymbolicLink failed/n"));
        }

 

        //
        // Create dispatch points for device control, create, close.
        //

        DriverObject->MajorFunction[IRP_MJ_CREATE]         =
        DriverObject->MajorFunction[IRP_MJ_CLOSE]          =
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SimplDrvDispatch;
        DriverObject->DriverUnload                         = SimplDrvUnload;
    }


//done_DriverEntry:

    if (!NT_SUCCESS(ntStatus))
    {
        //
        // Something went wrong, so clean up (free resources, etc.)
        //

        if (deviceObject)

            IoDeleteDevice (deviceObject);
    }

    return ntStatus;
}

 

NTSTATUS
SimplDrvDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

    Process the IRPs sent to this device.

Arguments:

    DeviceObject - pointer to a device object

    Irp          - pointer to an I/O Request Packet

Return Value:


--*/
{

    PIO_STACK_LOCATION  irpStack;
    PDEVICE_EXTENSION   deviceExtension;
    PVOID               ioBuffer;       //PVOID
    ULONG               inputBufferLength;
    ULONG               outputBufferLength;
    ULONG               ioControlCode;
    NTSTATUS            ntStatus;

    // added by PLT
    unsigned char ucValue = 13;
    GENPORT_WRITE_INPUT ucValue1;
    ULONG ucValue2;
   
    Irp->IoStatus.Status      = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;


    //
    // Get a pointer to the current location in the Irp. This is where
    //     the function codes and parameters are located.
    //

    irpStack = IoGetCurrentIrpStackLocation (Irp);

 

    //
    // Get a pointer to the device extension
    //

    deviceExtension = DeviceObject->DeviceExtension;

 

    //
    // Get the pointer to the input/output buffer and it's length
    //

    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

 

    switch (irpStack->MajorFunction)
    {
  case IRP_MJ_CREATE:

   SimplDrvKdPrint (("SIMPLDRV.SYS: IRP_MJ_CREATE/n"));

   break;

  case IRP_MJ_CLOSE:

   SimplDrvKdPrint (("SIMPLDRV.SYS: IRP_MJ_CLOSE/n"));

   break;

  case IRP_MJ_DEVICE_CONTROL:

//   SimplDrvKdPrint (("SIMPLDRV.SYS: IRP_MJ_DEVICE_CONTROL/n"));

   ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

   switch (ioControlCode)
   {

    case IOCTL_SIMPLDRV_HELLO:
    {
     //
     // Some app is saying hello
     //

     RtlMoveMemory(&ucValue2,ioBuffer,sizeof(ucValue2));
     
     switch (ucValue2)
     {
      case 0x300:
       {
        __asm
        {
         mov al,80H
         mov dx,03FBH
         out dx,al
         mov al,0CH
         mov dx,03F8H
         out dx,al
         mov al,00H
         mov dx,03F9H
         out dx,al
         mov al,03H
         mov dx,03FBH
         out dx,al
       //  mov dx,03fch  
       //  out dx,al
         mov al,00H
         mov dx,03F9H
         out dx,al
        }
           // added by PLT
        RtlMoveMemory(ioBuffer, &ucValue, sizeof(ucValue));
        Irp->IoStatus.Information = sizeof(ucValue);
        break;
        }
      case 0x301:
       {
         __asm
         {
          MOV DX,03FDH
        COM_IN1:
          in al,dx
        //  _emit 0xEC
          TEST al,01
          JE COM_IN1
          MOV DX,03F8H
          in al,dx
        //  _emit 0xEC
          MOV ucValue,al
         }

//        _asm mov dx,3F8H
//        _asm in al,dx
//        _asm mov ucValue,al
        RtlMoveMemory(ioBuffer, &ucValue, sizeof(ucValue));
        Irp->IoStatus.Information = sizeof(ucValue);
        break;
        }
/*      case 0x304:
       {
        _asm mov dx,3FDH
        _asm in al,dx
        _asm mov ucValue,al
        RtlMoveMemory(ioBuffer, &ucValue, sizeof(ucValue));
        Irp->IoStatus.Information = sizeof(ucValue);
        break;
        }*/
       }       

     break;
    }

    case IOCTL_GPD_WRITE_PORT_UCHAR:
    {
//     SimplDrvKdPrint (("SIMPLDRV.SYS: zouyu_ok/n"));
     
     RtlMoveMemory(&ucValue1,ioBuffer,5);

     switch (ucValue1.PortNumber)
     {
/*      case 0x301:
       {
           _asm mov dx,3FBH
           _asm mov al,ucValue1.CharData
           _asm out dx,al
           SimplDrvKdPrint (("SIMPLDRV.SYS: 3FBH/n"));
        break;
        }*/
      case 0x302:
       {
        __asm
        {
         mov dx,03FDH
       COM_OUT1:
         in al,dx
         test al,20H
         je COM_OUT1
         mov al,ucValue1.CharData
         mov dx,03F8H
         out dx,al
        }
/*
//           _asm mov dx,3F8H
//           _asm mov al,ucValue1.CharData
//           _asm out dx,al
       if (ucValue1.CharData==0xfe)
       {
            SimplDrvKdPrint (("SIMPLDRV.SYS: 0xfe/n"));
       }
       else
       {
        SimplDrvKdPrint (("SIMPLDRV.SYS: other/n"));
       }*/
        break;
        }
/*      case 0x303:
       {
           _asm mov dx,3F9H
           _asm mov al,ucValue1.CharData
           _asm out dx,al
           SimplDrvKdPrint (("SIMPLDRV.SYS: 3F9H/n"));
        break;
        }*/
       }
     
     break;
    }
    default:

     Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

     SimplDrvKdPrint (("SIMPLDRV.SYS: unknown IRP_MJ_DEVICE_CONTROL/n"));

     break;

   }

   break;
    }


    //
    // DON'T get cute and try to use the status field of
    // the irp in the return status.  That IRP IS GONE as
    // soon as you call IoCompleteRequest.
    //

    ntStatus = Irp->IoStatus.Status;

    IoCompleteRequest (Irp,
                       IO_NO_INCREMENT
                       );


    //
    // We never have pending operation so always return the status code.
    //

    return ntStatus;
}

 

VOID
SimplDrvUnload(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:

    Free all the allocated resources, etc.

Arguments:

    DriverObject - pointer to a driver object

Return Value:


--*/
{
    WCHAR                  deviceLinkBuffer[]  = L"//DosDevices//SIMPLDRV";
    UNICODE_STRING         deviceLinkUnicodeString;

 

    //
    // Free any resources
    //

 

    //
    // Delete the symbolic link
    //

    RtlInitUnicodeString (&deviceLinkUnicodeString,
                          deviceLinkBuffer
                          );

    IoDeleteSymbolicLink (&deviceLinkUnicodeString);

 

    //
    // Delete the device object
    //

    IoDeleteDevice (DriverObject->DeviceObject);

    SimplDrvKdPrint (("SIMPLDRV.SYS: unloading/n"));
}

2,simpldrv.h

 

/*++

Copyright (c) 1993  Microsoft Corporation

Module Name:

    simpldrv.h

Abstract:

    This module contains the PRIVATE (driver-only) definitions for the
    code that implements the mono device driver.

Environment:

    Kernel & user mode

Revision History:

    06-25-93 : created

--*/

 

//
// A structure representing the instance information associated with
// a particular device
//

typedef struct _DEVICE_EXTENSION
{
    ULONG  StateVariable;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

 

//
// Define the various device type values.  Note that values used by Microsoft
// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
// by customers.
//

#define FILE_DEVICE_SIMPLDRV  0x00008300

 

//
// Macro definition for defining IOCTL and FSCTL function control codes.  Note
// that function codes 0-2047 are reserved for Microsoft Corporation, and
// 2048-4095 are reserved for customers.
//

#define SIMPLDRV_IOCTL_INDEX  0x830

 

//
// The MONO device driver IOCTLs
//

#define IOCTL_SIMPLDRV_HELLO          CTL_CODE(FILE_DEVICE_SIMPLDRV,  /
                                               SIMPLDRV_IOCTL_INDEX,  /
                                               METHOD_BUFFERED,       /
                                               FILE_ANY_ACCESS)
                                              
#define IOCTL_GPD_WRITE_PORT_UCHAR /
    CTL_CODE(FILE_DEVICE_SIMPLDRV, SIMPLDRV_IOCTL_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)

3,SOURCES

 

TARGETNAME=simpldrv
TARGETPATH=obj
TARGETTYPE=DRIVER

SOURCES=simpldrv.c

4,MAKEFILE

 

#
# DO NOT EDIT THIS FILE!!!  Edit ./sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#

!INCLUDE $(NTMAKEENV)/makefile.def

 

    编译成功后会生成一个simpldrv.sys,怎样加载这个sys文件,搞过windows设备驱动程序的人都知道,应该不用我多说了。

 

    最后补充说一句,因为这些代码都是97年写的了,很多源程序没有多加注解,看帖的朋友只有自己多体会了。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您可以通过以下步骤安装VMware虚拟机程序: 1. 首先,您需要下载VMware Workstation软件。您可以从官方网站\[3\]或百度网盘分享链接中获取下载链接。 2. 点击下载链接,选择合适的版本并下载软件安装包。 3. 下载完成后,双击安装包并按照提示进行安装。在安装过程中,您可以选择安装位置和其他选项。 4. 完成安装后,打开VMware Workstation软件。 5. 在软件界面中,您可以创建新的虚拟机或导入现有的虚拟机。如果您是第一次使用,可以选择创建新的虚拟机。 6. 在创建虚拟机的过程中,您需要选择操作系统类型和版本,并设置虚拟机的硬件配置,如内存大小、硬盘容量等。 7. 完成虚拟机的配置后,您可以启动虚拟机并安装操作系统。您可以使用光盘镜像文件或操作系统安装文件进行安装。 8. 安装完成后,您可以在VMware Workstation中同时运行多个虚拟机,并在它们之间进行切换和操作。 请注意,以上步骤仅为一般安装过程的概述,具体步骤可能会因软件版本和个人需求而有所不同。建议您在安装过程中参考官方文档或相关教程以获取更详细的指导。 #### 引用[.reference_title] - *1* *2* *3* [vmware 详细安装教程](https://blog.csdn.net/SoulNone/article/details/126681722)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值