#define WIN32_LEAN_AND_MEAN #include "wutils.h" #include #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; }