驱动写好后,要在应用程序中调用驱动还需要自己写一个驱动加载器,
以下代码能够实现在Windows中加载驱动到系统中,并能调用驱动的I/O例程。
编译成功后,把驱动sys文件与此代码编译好的exe放同一个目录。
cpp源文件:
#include "libmio.h"
using namespace std;
CLibmio::CLibmio(void) throw (CLibmioException) :
m_hDriver(INVALID_HANDLE_VALUE)
{
OSVERSIONINFO
osv;
// check the os whether support this driver.
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(&osv);
if ( osv.dwPlatformId != VER_PLATFORM_WIN32_NT )
throw new CLibmioException(ERR_OS_NOT_SUPPORT);
const char
* pChar = NULL;
// get the file path of driver.
::GetModuleFileName(NULL, szDriverPath, MAX_PATH);
pChar = ::strrchr(szDriverPath, '\\');
if ( !pChar )
throw new CLibmioException(ERR_DRIVER_NOT_FOUND);
::strcpy(const_cast<char*>(++pChar), DRIVER_FILE);
WIN32_FIND_DATA
finddata;
HANDLE
hFindDriver = ::FindFirstFile(szDriverPath, &finddata);
// confirm the file path is exist.
if ( hFindDriver == INVALID_HANDLE_VALUE )
throw new CLibmioException(ERR_DRIVER_NOT_FOUND);
::FindClose(hFindDriver);
// open the driver
if ( !OpenDriver() )
{
// stop and uninstall the driver.
StopDriver();
UninstallDriver();
// install the driver.
if ( !InstalDriver() )
throw new CLibmioException(ERR_DRIVER_INSTALL_FAIL);
// startup the driver.
if ( !StartDriver() )
throw new CLibmioException(ERR_DRIVER_START_FAIL);
// open the driver.
if ( !OpenDriver() )
throw new CLibmioException(ERR_DRIVER_OPEN_FAIL);
}
}
CLibmio::~CLibmio(void)
{
bool
bUns = CanUninstall();
CloseDriver();
if ( bUns )
{
StopDriver();
UninstallDriver();
}
}
bool CLibmio::InstalDriver(void)
{
SC_HANDLE
hSCManager,
hService;
hSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( hSCManager == NULL )
return false;
hService = ::CreateService(
hSCManager,
DRIVER_NAME,
DRIVER_NAME,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
szDriverPath,
NULL, NULL, NULL, NULL, NULL);
::CloseServiceHandle(hSCManager);
if ( hService == NULL )
return false;
::CloseServiceHandle(hService);
return true;
}
bool CLibmio::StartDriver(void)
{
SC_HANDLE
hSCManager,
hService;
bool
bResult = false;
hSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( hSCManager == NULL )
return bResult;
hService = ::OpenService(hSCManager, DRIVER_NAME, SERVICE_ALL_ACCESS);
::CloseServiceHandle(hSCManager);
if ( hService == NULL )
return bResult;
#pragma warning(disable:4800)
bResult = ::StartService(hService, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
::CloseServiceHandle(hService);
return bResult;
}
bool CLibmio::OpenDriver(void)
{
m_hDriver = ::CreateFile(
DEVICE_PATH, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (m_hDriver != INVALID_HANDLE_VALUE);
}
bool CLibmio::CanUninstall(void)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return true;
DWORD
dwBytes = 0,
dwRef = 0;
if ( !::DeviceIoControl(
m_hDriver,
IOCTL_GET_REFCOUNT,
NULL,
0,
&dwRef,
sizeof(DWORD),
&dwBytes,
NULL) )
return false;
return (dwRef < 2);
}
void CLibmio::CloseDriver(void)
{
if ( m_hDriver != INVALID_HANDLE_VALUE )
::CloseHandle(m_hDriver);
m_hDriver = INVALID_HANDLE_VALUE;
}
bool CLibmio::UninstallDriver(void)
{
SC_HANDLE
hSCManager,
hService;
bool
bResult = false;
hSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( hSCManager == NULL )
return bResult;
hService = ::OpenService(hSCManager, DRIVER_NAME, SERVICE_ALL_ACCESS);
::CloseServiceHandle(hSCManager);
if ( hService == NULL )
return bResult;
#pragma warning(disable:4800)
bResult = ::DeleteService(hService);
::CloseServiceHandle(hService);
return bResult;
}
bool CLibmio::StopDriver(void)
{
SERVICE_STATUS
ServiceStatus;
SC_HANDLE
hSCManager,
hService;
bool
bResult = false;
hSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( hSCManager == NULL )
return bResult;
hService = ::OpenService(hSCManager, DRIVER_NAME, SERVICE_ALL_ACCESS);
::CloseServiceHandle(hSCManager);
if ( hService == NULL )
return bResult;
#pragma warning(disable:4800)
bResult = ::ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus);
::CloseServiceHandle(hService);
return bResult;
}
bool CLibmio::GetVersion(
DWORD &dwVersion)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_GET_VERSION,
NULL, 0,
&dwVersion,
sizeof(DWORD),
&dwBytes,
NULL);
}
bool CLibmio::GetVersionString(
char *outString,
int length)
{
DWORD
dwVersion = 0;
if ( !outString )
return false;
if ( !GetVersion(dwVersion) )
return false;
BYTE
vers[4];
char
szStr[18];
::memcpy(vers, &dwVersion, sizeof(DWORD));
::sprintf(szStr, "%d.%d.%d.%d", vers[3], vers[2], vers[1], vers[0]);
if ( length > strlen(szStr) )
length = strlen(szStr);
::strncpy(outString, szStr, length);
return true;
}
bool CLibmio::Rdmsr(
DWORD index,
ULARGE_INTEGER& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_MSR,
&index,
sizeof(index),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::Wrmsr(
DWORD index,
ULARGE_INTEGER value)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
buff[3];
buff[0] = index;
::memcpy(&buff[1], &value, sizeof(value));
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_MSR,
buff,
sizeof(buff),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::Rdpmc(
DWORD index,
ULARGE_INTEGER& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PMC,
&index,
sizeof(index),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::Inp(
WORD port,
BYTE& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::Inp(
WORD port,
WORD& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::Inp(
WORD port,
DWORD& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::Outp(
WORD port,
BYTE data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
WORD
buff[2];
DWORD
dwBytes = 0;
buff[0] = port;
buff[1] = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT,
buff,
sizeof(port) + sizeof(data),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::Outp(
WORD port,
WORD data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
WORD
buff[2];
DWORD
dwBytes = 0;
buff[0] = port;
buff[1] = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT,
buff,
sizeof(port) + sizeof(data),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::Outp(
WORD port,
DWORD data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
WORD
buff[3];
DWORD
dwBytes = 0;
buff[0] = port;
*((DWORD*)&buff[1]) = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT,
buff,
sizeof(port) + sizeof(data),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::ReadPort(
WORD port,
BYTE& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT_BYTE,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::ReadPort(
WORD port,
WORD& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT_WORD,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::ReadPort(
WORD port,
DWORD& out)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0;
out = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PORT_DWORD,
&port,
sizeof(port),
&out,
sizeof(out),
&dwBytes,
NULL);
}
bool CLibmio::WritePort(
WORD port,
BYTE data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
buff[2];
buff[0] = port;
buff[1] = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT_BYTE,
buff,
sizeof(buff),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::WritePort(
WORD port,
WORD data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
buff[2];
buff[0] = port;
buff[1] = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT_WORD,
buff,
sizeof(buff),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::WritePort(
WORD port,
DWORD data)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
buff[2];
buff[0] = port;
buff[1] = data;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PORT_DWORD,
buff,
sizeof(buff),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::PciReadConfig(
DWORD addr,
DWORD offset,
LPVOID out,
DWORD cbSize)
{
return PciReadConfig((addr >> 8) & 0xff, (addr >> 3) & 0x1f, addr & 0x7, offset, out, cbSize);
}
bool CLibmio::PciReadConfig(
WORD bus,
WORD dev,
WORD fun,
DWORD offset,
LPVOID out,
DWORD cbSize)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
buff[3];
buff[0] = bus;
buff[1] = (fun << 5) | (dev & 0x1f);
buff[2] = offset;
::RtlZeroMemory(out, cbSize);
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_PCI_READ_CONFIG,
buff,
sizeof(buff),
out,
cbSize,
&dwBytes,
NULL);
}
bool CLibmio::PciWriteConfig(
DWORD addr,
DWORD offset,
LPVOID out,
DWORD cbSize)
{
return PciWriteConfig((addr >> 8) & 0xff, (addr >> 3) & 0x1f, addr & 0x7, offset, out, cbSize);
}
bool CLibmio::PciWriteConfig(
WORD bus,
WORD dev,
WORD fun,
DWORD offset,
LPVOID out,
DWORD cbSize)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
DWORD
dwBytes = 0,
dwSize = 0,
* pBuff;
bool
result = false;
dwSize = cbSize + 0x10;
pBuff = reinterpret_cast<DWORD*>(new BYTE[dwSize]);
pBuff[0] = bus;
pBuff[1] = (fun << 5) | (dev & 0x1f);
pBuff[2] = offset;
pBuff[3] = cbSize;
::RtlMoveMemory(&pBuff[4], out, cbSize);
result = 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_PCI_WRITE_CONFIG,
pBuff,
dwSize,
NULL,
0,
&dwBytes,
NULL);
delete []pBuff;
return result;
}
LPVOID CLibmio::MapPhyMemory(
LPVOID addr,
DWORD cbSize)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return NULL;
if ( !cbSize )
return false;
DWORD
dwBytes = 0,
buff[2];
LPVOID
out = NULL;
buff[0] = reinterpret_cast<DWORD>(addr);
buff[1] = cbSize;
if ( !::DeviceIoControl(
m_hDriver,
IOCTL_MAP_PHY_MEMORY,
buff,
sizeof(buff),
&out,
sizeof(out),
&dwBytes,
NULL) )
return NULL;
return out;
}
bool CLibmio::UnmapPhyMemory(
LPVOID addr)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
if ( !addr )
return false;
DWORD
dwBytes = 0;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_UNMAP_PHY_MEMORY,
&addr,
sizeof(LPVOID),
NULL,
0,
&dwBytes,
NULL);
}
bool CLibmio::ReadPhyMemory(
LPVOID addr,
LPVOID buffer,
DWORD cbSize)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
if ( !buffer )
return false;
if ( !cbSize )
return false;
DWORD
dwBytes = 0,
buff[2];
buff[0] = reinterpret_cast<DWORD>(addr);
buff[1] = cbSize;
return 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_READ_PHY_MEMORY,
buff,
sizeof(buff),
buffer,
cbSize,
&dwBytes,
NULL);
}
bool CLibmio::WritePhyMemory(
LPVOID addr,
LPVOID buffer,
DWORD cbSize)
{
if ( m_hDriver == INVALID_HANDLE_VALUE )
return false;
if ( !buffer )
return false;
if ( !cbSize )
return false;
bool
result = false;
DWORD
dwBytes = 0,
dwSize = cbSize + 2 * sizeof(DWORD),
* pBuff;
pBuff = reinterpret_cast<DWORD*>(new BYTE[dwSize]);
pBuff[0] = reinterpret_cast<DWORD>(addr);
pBuff[1] = cbSize;
::RtlMoveMemory(&pBuff[2], buffer, cbSize);
result = 0 != ::DeviceIoControl(
m_hDriver,
IOCTL_WRITE_PHY_MEMORY,
pBuff,
dwSize,
NULL,
0,
&dwBytes,
NULL);
delete []pBuff;
return result;
}
libmio.h中的部分内容:
class CLibmioException;
class CLibmio
{
public:
CLibmio(void) throw (CLibmioException);
virtual ~CLibmio(void);
bool GetVersion(DWORD &);
bool GetVersionString(char *, int);
bool Rdmsr(DWORD, ULARGE_INTEGER&);
bool Wrmsr(DWORD, ULARGE_INTEGER);
bool Rdpmc(DWORD, ULARGE_INTEGER&);
bool Inp(WORD, BYTE&);
bool Inp(WORD, WORD&);
bool Inp(WORD, DWORD&);
bool Outp(WORD, BYTE);
bool Outp(WORD, WORD);
bool Outp(WORD, DWORD);
bool ReadPort(WORD, BYTE&);
bool ReadPort(WORD, WORD&);
bool ReadPort(WORD, DWORD&);
bool WritePort(WORD, BYTE);
bool WritePort(WORD, WORD);
bool WritePort(WORD, DWORD);
bool PciReadConfig(DWORD, DWORD, LPVOID, DWORD);
bool PciReadConfig(WORD, WORD, WORD, DWORD, LPVOID, DWORD);
bool PciWriteConfig(DWORD, DWORD, LPVOID, DWORD);
bool PciWriteConfig(WORD, WORD, WORD, DWORD, LPVOID, DWORD);
LPVOID MapPhyMemory(LPVOID, DWORD);
bool UnmapPhyMemory(LPVOID);
bool ReadPhyMemory(LPVOID, LPVOID, DWORD);
bool WritePhyMemory(LPVOID, LPVOID, DWORD);
private:
bool StartDriver(void);
bool StopDriver(void);
bool InstalDriver(void);
bool UninstallDriver(void);
bool CanUninstall(void);
bool OpenDriver(void);
void CloseDriver(void);
protected:
HANDLE m_hDriver;
char szDriverPath[MAX_PATH];
};