GetVersionEx(&os);
// If we're running on Windows NT, load the driver this way.
if(os.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
return CreateFile("\\\\.\\MSJDrvr",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
}
// Otherwise, running under Windows 9x, dynamically load the VxD
else
{
return CreateFile("\\\\.\\MSJDrvr.VXD", 0,0,0,
CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE |
FILE_FLAG_OVERLAPPED, 0);
}
Figure B MSJDrvr.VxD
/*
main.c - 1998 James M. Finnegan - Microsoft Systems Journal
This module is for DeviceIoControl() dispatching on the VxD...
*/
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <vxdwraps.h>
#include <vwin32.h>
#include <winerror.h>
#define CVXD_VERSION 0x400
typedef DIOCPARAMETERS *LPDIOC;
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
// Define the method codes for how buffers are passed for I/O and FS controls
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
// Define the access check value for any access
//
//
// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
// constants *MUST* always be in sync.
#define FILE_ANY_ACCESS 0
#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
#define FILE_DEVICE_UNKNOWN 0x00000022
#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
#define IOCTL_MSJDRVR_GET_STRING CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800,
METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG
// define wrappers for VWIN32_DIOCCompletionRoutine and Set_Thread_Time_Out
MAKE_HEADER(VOID, _stdcall, VWIN32_DIOCCompletionRoutine, (DWORD hEvent))
#define VWIN32_DIOCCompletionRoutine PREPEND(VWIN32_DIOCCompletionRoutine)
DWORD _stdcall CVXD_W32_DeviceIOControl(DWORD dwService,
DWORD dwDDB,
DWORD hDevice,
LPDIOC lpDIOCParms)
{
DWORD dwRetVal;
switch(dwService)
{
case DIOC_OPEN:
// Must return 0 to tell WIN32 that this VxD supports DEVIOCTL
dwRetVal = 0;
break;
case DIOC_CLOSEHANDLE:
dwRetVal = VXD_SUCCESS;
break;
case IOCTL_MSJDRVR_GET_STRING:
{
char szString[] = "Hello from VxD-land!";
char *szOutput = (char *)lpDIOCParms->lpvOutBuffer;
int i;
// Copy the string to the caller's buffer...
for(i = 0; szString[i] != NULL; i++)
szOutput[i] = szString[i];
// Set the event handle to indicate to the Win32 caller that we're
// done...
VWIN32_DIOCCompletionRoutine((DWORD)((OVERLAPPED *)lpDIOCParms->
lpoOverlapped)->O_Internal);
dwRetVal = VXD_SUCCESS;
}
break;
default:
dwRetVal = ERROR_NOT_SUPPORTED;
break;
}
return dwRetVal;
}