📄 tdlportio.cpp
字号:
//*** TDLPortIO: DriverLINX Port IO Driver wrapper component *****************
//** **
//** File: TDLPortIO.cpp **
//** **
//** Copyright (c) 1999 John Pappas (DiskDude). All rights reserved. **
//** This software is FreeWare. **
//** **
//** Please notify me if you make any changes to this file. **
//** Email: diskdude@poboxes.com **
//** **
//** **
//** The following resources helped in developing the install, start, stop **
//** and remove code for dynamically opening/closing the DriverLINX WinNT **
//** kernel mode driver. **
//** **
//** "Dynamically Loading Drivers in Windows NT" by Paula Tomlinson **
//** from "Windows Developer's Journal", Volume 6, Issue 5. (C code) **
//** ftp://ftp.mfi.com/pub/windev/1995/may95.zip **
//** **
//** "Hardware I/O Port Programming with Delphi and NT" by Graham Wideman **
//** http://www.wideman-one.com/tech/Delphi/IOPM/index.htm **
//** **
//** **
//** Special thanks to Peter Holm <comtext3@post4.tele.dk> for his **
//** algorithm and code for detecting the number and addresses of the **
//** installed printer ports, on which the detection code below is based. **
//** **
//*** http://diskdude.cjb.net/ ***********************************************
#include <vcl.h>
#include <cstring>
#include <stdlib.h>
#include <string.h>
#pragma hdrstop
#pragma package(smart_init)
#include "TDLPortIO.h"
//---------------------------------------------------------------------------
// Constants
//---------------------------------------------------------------------------
// DriverLINX DLL filename
const AnsiString LIBRARY_FILENAME = "DLPortIO.dll";
// WinNT DriverLINX Information
const AnsiString DRIVER_NAME = "DLPortIO";
const AnsiString DISPLAY_NAME = "DriverLINX Port I/O Driver";
const AnsiString DRIVER_GROUP = "SST miniport drivers";
// Define to do a little less error checking
#define FAST
//*************************************************************************//
// TDLPortIO class implementation
//*************************************************************************//
//---------------------------------------------------------------------------
// TDLPortIO()
//---------------------------------------------------------------------------
__fastcall TDLPortIO::TDLPortIO(TComponent *Owner) : TComponent(Owner)
{
// Are we running Windows NT?
OSVERSIONINFO os;
memset(&os, NULL, sizeof(OSVERSIONINFO));
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
FRunningWinNT=(os.dwPlatformId==VER_PLATFORM_WIN32_NT);
// Set default WinNT driver path
char Buffer[MAX_PATH];
GetSystemDirectory(Buffer, MAX_PATH);
FDriverPath = AnsiString(Buffer)+"\\DRIVERS";
// Set the default DLL path
FDLLPath="";
FActiveHW=false; // DLL/Driver not loaded
FHardAccess=true; // Not used, default true
FLastError=""; // No errors yet
}
//---------------------------------------------------------------------------
// ~TDLPortIO()
//---------------------------------------------------------------------------
__fastcall TDLPortIO::~TDLPortIO()
{
// Make sure we close the DLL
if (IsLoaded()) CloseDriver();
}
//---------------------------------------------------------------------------
// ConnectSCM()
// Connects to the WinNT Service Control Manager
//---------------------------------------------------------------------------
bool TDLPortIO::ConnectSCM()
{
DWORD dwStatus = 0; // Assume success, until we prove otherwise
DWORD scAccess; // Access mode when connecting to SCM
// Try and connect as administrator
scAccess = SC_MANAGER_CONNECT |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_CREATE_SERVICE; // Admin only
// Connect to the SCM
hSCMan = OpenSCManager(NULL, NULL, scAccess);
// If we're not in administrator mode, try and reconnect
if (hSCMan==NULL && GetLastError()==ERROR_ACCESS_DENIED)
{
scAccess = SC_MANAGER_CONNECT |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_ENUMERATE_SERVICE;
// Connect to the SCM
hSCMan = OpenSCManager(NULL, NULL, scAccess);
}
// Did it succeed?
if (hSCMan==NULL)
{
// Failed, save error information
dwStatus=GetLastError();
FLastError="ConnectSCM: Error #"+IntToStr(dwStatus);
}
return dwStatus==0; // Success == 0
}
//---------------------------------------------------------------------------
// DisconnectSCM()
// Disconnects from the WinNT Service Control Manager
//---------------------------------------------------------------------------
void TDLPortIO::DisconnectSCM()
{
if (hSCMan != NULL)
{
// Disconnect from our local Service Control Manager
CloseServiceHandle(hSCMan);
hSCMan=NULL;
}
}
//---------------------------------------------------------------------------
// DriverInstall()
// Installs the DriverLINX driver into Windows NT's registry
//---------------------------------------------------------------------------
bool TDLPortIO::DriverInstall()
{
SC_HANDLE hService; // Handle to the new service
DWORD dwStatus = 0; // Assume success, until we prove otherwise
FDrvPrevInst=false; // Assume the driver wasn't installed previously
// Path including filename
AnsiString DriverPath = FDriverPath+"\\"+DRIVER_NAME+".SYS";
// Is the DriverLINX driver already in the SCM? If so,
// indicate success and set FDrvPrevInst to true.
hService=OpenService(hSCMan, DRIVER_NAME.c_str(), SERVICE_QUERY_STATUS);
if (hService!=NULL)
{
FDrvPrevInst=true; // Driver previously installed, don't remove
CloseServiceHandle(hService); // Close the service
return true; // Success
}
// Add to our Service Control Manager's database
hService=CreateService(
hSCMan,
DRIVER_NAME.c_str(),
DISPLAY_NAME.c_str(),
SERVICE_START | SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
DriverPath.c_str(),
DRIVER_GROUP.c_str(),
NULL, NULL, NULL, NULL);
if (hService==NULL)
dwStatus=GetLastError();
else
// Close the service for now...
CloseServiceHandle(hService);
if (dwStatus!=0)
FLastError="DriverInstall: Error #"+IntToStr(dwStatus);
return dwStatus==0; // Success == 0
}
//---------------------------------------------------------------------------
// DriverStart()
// Starts the Windows NT DriverLINX driver for use
//---------------------------------------------------------------------------
bool TDLPortIO::DriverStart()
{
SC_HANDLE hService; // Handle to the service to start
DWORD dwStatus = 0; // Assume success, until we prove otherwise
SERVICE_STATUS sStatus;
FDrvPrevStart=false; // Assume the driver was not already running
hService = OpenService(hSCMan, DRIVER_NAME.c_str(), SERVICE_QUERY_STATUS);
if (hService!=NULL && QueryServiceStatus(hService, &sStatus))
{
// Got the service status, now check it
if (sStatus.dwCurrentState==SERVICE_RUNNING)
{
FDrvPrevStart=true; // Driver was previously started
CloseServiceHandle(hService); // Close service
return true; // Success
}
else if (sStatus.dwCurrentState==SERVICE_STOPPED)
{
// Driver was stopped. Start the driver.
CloseServiceHandle(hService);
hService = OpenService(hSCMan, DRIVER_NAME.c_str(), SERVICE_START);
if (!StartService(hService, 0, NULL))
dwStatus=GetLastError();
CloseServiceHandle(hService); // Close service
}
else dwStatus=-1; // Can't run the service
}
else
dwStatus=GetLastError();
if (dwStatus!=0)
FLastError="DriverStart: Error #"+IntToStr(dwStatus);
return dwStatus==0; // Success == 0
}
//---------------------------------------------------------------------------
// DriverStop()
// Stops a Windows NT driver from use
//---------------------------------------------------------------------------
bool TDLPortIO::DriverStop()
{
SC_HANDLE hService; // Handle to the service to start
DWORD dwStatus = 0; // Assume success, until we prove otherwise
// If we didn't start the driver, then don't stop it.
// Pretend we stopped it, by indicating success.
if (FDrvPrevStart) return true;
// Get a handle to the service to stop
hService = OpenService(
hSCMan,
DRIVER_NAME.c_str(),
SERVICE_STOP | SERVICE_QUERY_STATUS);
if (hService!=NULL)
{
// Stop the driver, then close the service
SERVICE_STATUS sStatus;
if (!ControlService(hService, SERVICE_CONTROL_STOP, &sStatus))
dwStatus = GetLastError();
// Close the service
CloseServiceHandle(hService);
}
else
dwStatus = GetLastError();
if (dwStatus!=0)
FLastError="DriverStop: Error #"+IntToStr(dwStatus);
return dwStatus==0; // Success == 0
}
//---------------------------------------------------------------------------
// DriverRemove()
// Removes a driver from the Windows NT system (service manager)
//---------------------------------------------------------------------------
bool TDLPortIO::DriverRemove()
{
SC_HANDLE hService; // Handle to the service to start
DWORD dwStatus = 0; // Assume success, until we prove otherwise
// If we didn't install the driver, then don't remove it.
// Pretend we removed it, by indicating success.
if (FDrvPrevInst) return true;
// Get a handle to the service to remove
hService = OpenService(
hSCMan,
DRIVER_NAME.c_str(),
DELETE);
if (hService!=NULL)
{
// Remove the driver then close the service again
if (!DeleteService(hService))
dwStatus = GetLastError();
// Close the service
CloseServiceHandle(hService);
}
else
dwStatus = GetLastError();
if (dwStatus!=0)
FLastError="DriverRemove: Error #"+IntToStr(dwStatus);
return dwStatus==0; // Success == 0
}
//---------------------------------------------------------------------------
// OpenDriver()
// Opens the DLL dynamically
//---------------------------------------------------------------------------
void __fastcall TDLPortIO::OpenDriver()
{
// If the DLL/driver is already open, then forget it!
if (IsLoaded()) return;
// If we're running Windows NT, install the driver then start it
if (FRunningWinNT)
{
// Connect to the Service Control Manager
if (!ConnectSCM()) return;
// Install the driver
if (!DriverInstall())
{
// Driver install failed, so disconnect from the SCM
DisconnectSCM();
return;
}
// Start the driver
if (!DriverStart())
{
// Driver start failed, so remove it then disconnect from SCM
DriverRemove();
DisconnectSCM();
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -