Source file: /~heha/basteln/PC/oszi/oszi.zip/unused/allowio.c

#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;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded