unit UnitPortTalk; interface uses Windows, SysUtils, Dialogs,WinSvc; const PORTTALK_TYPE = 40000; { 32768-65535是保留给用户使用的} METHOD_BUFFERED = 0; FILE_ANY_ACCESS = 0; IOCTL_IOPM_RESTRICT_ALL_ACCESS = PORTTALK_TYPE shl 16 + $900 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS = PORTTALK_TYPE shl 16 + $901 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; IOCTL_SET_IOPM = PORTTALK_TYPE shl 16 + $902 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; IOCTL_ENABLE_IOPM_ON_PROCESSID = PORTTALK_TYPE shl 16 + $903 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; IOCTL_READ_PORT_UCHAR = PORTTALK_TYPE shl 16 + $904 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; IOCTL_WRITE_PORT_UCHAR = PORTTALK_TYPE shl 16 + $905 shl 2 + METHOD_BUFFERED + FILE_ANY_ACCESS shl 14; function OpenPortTalk:boolean; procedure ClosePortTalk; procedure outportb(PortAddress:word;byte1:byte); function inportb(PortAddress:word):byte; function StartPortTalkDriver:boolean; procedure InstallPortTalkDriver; var PortTalk_Handle:THANDLE; {PortTalk句柄} implementation procedure outportb(PortAddress:word;byte1:byte); var error:boolean; BytesReturned:DWORD; Buffer:array[0..2]of byte; pBuffer:pword; begin pBuffer := pword(@Buffer[0]); pBuffer^ := PortAddress; Buffer[2] := byte1; error := DeviceIoControl(PortTalk_Handle, Cardinal(IOCTL_WRITE_PORT_UCHAR), @Buffer, 3, nil, 0, BytesReturned, nil); if (not error) then showmessagefmt('从PortTalk输出端口数据时出错:%d',[GetLastError]); end; function inportb(PortAddress:word):byte; var error:boolean; BytesReturned:DWORD; Buffer:array[0..2]of byte; pBuffer:pword; begin pBuffer := pword(@Buffer[0]); pBuffer^ := PortAddress; error := DeviceIoControl(PortTalk_Handle, cardinal(IOCTL_READ_PORT_UCHAR), @Buffer, 2, @Buffer, 1, BytesReturned, nil); if (not error) then showmessagefmt('从PortTalk输入端口数据时出错:%d',[GetLastError]); result:=Buffer[0]; end; function OpenPortTalk:boolean; begin {打开PortTalk,如果不能打开,则安装它} PortTalk_Handle := CreateFile('\\.\PortTalk', GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(PortTalk_Handle = INVALID_HANDLE_VALUE) then begin {启动驱动程序} StartPortTalkDriver; {再次打开PortTalk} PortTalk_Handle := CreateFile('\\.\PortTalk', GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(PortTalk_Handle = INVALID_HANDLE_VALUE) then begin showmessage('PortTalk: 不能存取PortTalk,请确保驱动程序已安装。'); result:=false; exit; end; end; result:=true; end; procedure ClosePortTalk; begin CloseHandle(PortTalk_Handle); end; function StartPortTalkDriver:boolean; type TNewStartService=function (hService: SC_HANDLE; dwNumServiceArgs: DWORD; lpServiceArgVectors: PPChar): BOOL; stdcall; var SchSCManager:SC_HANDLE; schService:SC_HANDLE; ret:BOOL; err:DWORD; begin {打开Service Control Manager} SchSCManager := OpenSCManager (nil, { 机器 (nil = 本机) } nil, { 数据库 (nil = 默认 } SC_MANAGER_ALL_ACCESS); { 访问权 } if (SchSCManager = 0) then if (GetLastError = ERROR_ACCESS_DENIED) then begin { 没有权限打开SCM管理,必须是poor用户} showmessage('PortTalk: 没有权限访问Service Control Manager,'#$D#$A+ '不能安装和启动PortTalk,请使用超级用户来安装。'); result:=false; exit; end; repeat begin {打开PortTalk服务数据库} schService := OpenService(SchSCManager, {服务数据库句柄} 'PortTalk', {要启动的服务名} SERVICE_ALL_ACCESS); {存取的权限} if (schService = 0) then case (GetLastError) of ERROR_ACCESS_DENIED: begin showmessage('PortTalk: 没有权限访问PortTalk服务数据库'); result:=false; exit; end; ERROR_INVALID_NAME: begin showmessage('PortTalk: 指定的服务名无效'); result:=false; exit; end; ERROR_SERVICE_DOES_NOT_EXIST: begin showmessage('PortTalk: PortTalk驱动程序不存在'); InstallPortTalkDriver; end; end; end until (schService <> 0); {启动PortTalk驱动程序,如果发生错误,一般是由于PortTalk.SYS不存在。} ret := TNewStartService(@StartService) (schService, {服务标识} 0, {参数个数} nil); {参数} if (ret) then //showmessage('PortTalk: PortTalk安装成功!') else begin err := GetLastError; if (err = ERROR_SERVICE_ALREADY_RUNNING) then showmessage('PortTalk: PortTalk已经安装') else begin showmessage('PortTalk: 启动PortTalk时发生未知错误。'+#$D#$A+ 'PortTalk.SYS没有放入\System32\Drivers目录吗?'); result:=false; exit; end; end; {关闭Service Control Manager} CloseServiceHandle (schService); result:=TRUE; end; procedure InstallPortTalkDriver; var SchSCManager:SC_HANDLE; schService:SC_HANDLE; err:DWORD; DriverFileName:array[0..79]of CHAR; begin if (GetSystemDirectory(DriverFileName, 55)=0) then begin showmessage('PortTalk: 取System目录出错'); exit; end; {加入驱动程序文件名} lstrcat(DriverFileName,'\Drivers\PortTalk.sys'); showmessagefmt('PortTalk: 拷贝驱动程序到%s',[DriverFileName]); {拷贝驱动程序到System32/drivers目录,如果出错,一般是因为文件不存在。} if (not CopyFile('PortTalk.sys', DriverFileName, FALSE)) then begin showmessagefmt('PortTalk: 拷贝驱动程序到以下位置出错:%s'+#$D#$A+ '请手工拷贝到system32/driver目录', [DriverFileName]); exit; end; {打开Service Control Manager} SchSCManager := OpenSCManager (nil, { 机器 (nil = 本机) } nil, { 数据库 (nil = 默认 } SC_MANAGER_ALL_ACCESS); { 访问权 } schService := CreateService (SchSCManager, { SCManager数据库 } 'PortTalk', { 服务个数 } 'PortTalk', { 显示名 } SERVICE_ALL_ACCESS, { 权限 } SERVICE_KERNEL_DRIVER, { 服务类别 } SERVICE_DEMAND_START, { 启动类别 } SERVICE_ERROR_NORMAL, { 出错控件类别 } 'System32\Drivers\PortTalk.sys', { 服务二进制文件 } nil, { 加入的组 } nil, { 标识 } nil, { 隶属 } nil, { 本地帐户 } nil { 密码 } ); if (schService = 0) then begin err := GetLastError; if (err = ERROR_SERVICE_EXISTS) then showmessage('PortTalk: 驱动程序不存在。') else showmessage('PortTalk:建立服务时发生未知的错误。'); end else showmessage('PortTalk: 成功安装!'); { 关闭Service Control Manager } CloseServiceHandle (schService); end; end.