#define WIN32_LEAN_AND_MEAN
#include "wutils.h"
#include <winioctl.h>
#define PORTTALK_TYPE 40000 /* 32768-65535 are reserved for customers */
// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
#define IOCTL_IOPM_RESTRICT_ALL_ACCESS \
CTL_CODE(PORTTALK_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS \
CTL_CODE(PORTTALK_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SET_IOPM \
CTL_CODE(PORTTALK_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_ENABLE_IOPM_ON_PROCESSID \
CTL_CODE(PORTTALK_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_READ_PORT_UCHAR \
CTL_CODE(PORTTALK_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_PORT_UCHAR \
CTL_CODE(PORTTALK_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS)
bool InstallPortTalkDriver(HWND w, SC_HANDLE hSCManager) {
// Installation des Treibers ins System (erfordert Admin-Rechte)
SC_HANDLE hService;
TCHAR DriverFileName[MAX_PATH],RootDir[4];
/* Get Current Directory. Assumes PortTalk.SYS driver is in this directory. */
/* Doesn't detect if file exists, nor if file is on removable media - if this */
/* is the case then when windows next boots, the driver will fail to load and */
/* a error entry is made in the event viewer to reflect this */
/* Get System Directory. This should be something like c:\windows\system32 or */
/* c:\winnt\system32 with a Maximum Character lenght of 20. As we have a */
/* buffer of 80 bytes and a string of 24 bytes to append, we can go for a max */
/* of 55 bytes */
// Es muss nur kopiert werden, wenn das aktuelle Medium wechselbar ist!
// NT-Bug? Bei gesubsteten Laufwerken funktioniert es nicht.
// Der Treiber »porttalk.sys« muss neben der .EXE liegen
GetModuleFileName(0,DriverFileName,MAX_PATH);
lstrcpyn(RootDir,DriverFileName,4); // 3 Zeichen kopieren
lstrcpy(GetFileNamePtr(DriverFileName),T("PortTalk.sys"));
/*if (GetDriveType(RootDir)!=DRIVE_FIXED)*/ {
TCHAR LocalFileName[MAX_PATH];
lstrcpy(LocalFileName,DriverFileName);
GetWindowsDirectory(DriverFileName,MAX_PATH-21);
lstrcat(DriverFileName,T("\\System32\\Drivers\\"));
lstrcat(DriverFileName,T("PortTalk.sys"));
if (!CopyFile(LocalFileName,DriverFileName,FALSE)) {
MBox(w,303,MB_OK|MB_ICONSTOP,GetLastError(),LocalFileName,DriverFileName);
return false;
}
}
hService=CreateService(hSCManager,/* SCManager database */
T("PortTalk"), /* name of service */
T("PortTalk"), /* name to display */
SERVICE_START|SERVICE_STOP, /* desired access */
SERVICE_KERNEL_DRIVER, /* service type */
SERVICE_DEMAND_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
DriverFileName, /* service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no dependencies */
NULL, /* LocalSystem account */
NULL); /* no password */
if (!hService) {
if (GetLastError()==ERROR_SERVICE_EXISTS) return true;
MBox(w,304,MB_OK|MB_ICONSTOP,T("PortTalk"));
}
CloseServiceHandle (hService);
return true;
}
static bool StartPortTalkDriver(HWND w) {
// Starten des Treibers (erfordert eigentlich KEINE Admin-Rechte)
// Bei Rückgabe von FALSE meckert die Funktion selber per MessageBox
SC_HANDLE hSCManager;
SC_HANDLE hService;
bool ret=false;
/* Open Handle to Service Control Manager */
hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (!hSCManager) {
MBox(w,302,MB_OK|MB_ICONSTOP);
return ret;
}
for(;;){ /* Open a Handle to the PortTalk Service Database */
hService=OpenService(hSCManager,
T("PortTalk"),
SERVICE_ALL_ACCESS); /* type of access to service */
if (hService) break;
if (!InstallPortTalkDriver(w,hSCManager)) goto close;
}
ret=(bool)StartService(hService,0,NULL);
if (!ret) {
if (GetLastError()==ERROR_SERVICE_ALREADY_RUNNING) ret=true;
else{
DWORD BytesNeeded;
union {
QUERY_SERVICE_CONFIG qsc;
BYTE buffer[1024];
}u;
QueryServiceConfig(hService,&u.qsc,sizeof(u),&BytesNeeded);
MBox(w,305,MB_OK,u.qsc.lpDisplayName,u.qsc.lpBinaryPathName);
DeleteService(hService);
}
}
CloseServiceHandle(hService);
close:
CloseServiceHandle(hSCManager);
return ret;
}
static HANDLE openPortTalkDriver(void) {
return CreateFile(T("\\\\.\\PortTalk"),
GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
}
bool EnablePorts(HANDLE fh, UINT base, UINT count) {
// Bei count=0 erfolgt Rücksetzen auf "keine Portfreigabe"
DWORD BytesRet;
if (fh==INVALID_HANDLE_VALUE) return true; // Win95
if (!count) DeviceIoControl(fh,IOCTL_IOPM_RESTRICT_ALL_ACCESS,NULL,0,NULL,0,&BytesRet,NULL);
else{
struct {
WORD offset;
BYTE byte;
}o;
BYTE mask;
o.offset=(WORD)(base>>3); // Byte-Adresse (Start)
o.byte=0xFF;
mask=(BYTE)(1<<(base&7)); // Bit-Maske
do{
count--;
o.byte&=(BYTE)~mask; // Ein Bit löschen
mask<<=1; // nächstes Bit
if (!count) mask=0; // IOCTL erzwingen in letzter Runde
if (!mask) {
if (!DeviceIoControl(fh,IOCTL_SET_IOPM,&o,3,NULL,0,&BytesRet,NULL)) return false;
// if (!DeviceIoControl(fh,IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS,NULL,0,NULL,0,&BytesRet,NULL)) return false;
o.offset++; // Nächstes Byte
o.byte=0xFF; // wieder neu anfangen (alle Bits setzen oder löschen)
mask=1;
}
}while (count);
}
BytesRet=GetCurrentProcessId();
return DeviceIoControl(fh,IOCTL_ENABLE_IOPM_ON_PROCESSID,&BytesRet,4,NULL,0,&BytesRet,NULL);
}
HANDLE OpenPortTalkDriver(HWND w) {
HANDLE r=openPortTalkDriver();
if (r==INVALID_HANDLE_VALUE && StartPortTalkDriver(w)) {
r=openPortTalkDriver();
if (r==INVALID_HANDLE_VALUE) MBox(w,301,MB_OK,T("PortTalk"));
}
EnablePorts(r,0,0);
return r;
}
Vorgefundene Kodierung: UTF-8 | 0
|