Source file: /~heha/basteln/PC/Programmiergeräte/PEPS-III/peps4win32.zip/src/resw.c

// String table and printout functions for WIN32
// tabsize = 8, lineends = LF, encoding = UTF-8
#include "peps.h"
#include <conio.h>
#include <shlwapi.h>

#ifdef UNICODE
#define MyLoadStringO(i,s,l) LoadString(0,i,s,l)
#else
// OEM-String laden
static int MyLoadStringO(UINT id, PSTR buf, int len) {
 HRSRC r=FindResource(0,MAKEINTRESOURCE((id>>4)+1),RT_STRING);
 PCWSTR p=(PCWSTR)LoadResource(0,r);
 if (!p) return 0;
 for (id&=15; id; id--) {
  p+=*p+1;
 }
 len=WideCharToMultiByte(CP_OEMCP,0,p+1,*p,buf,len-1,NULL,NULL);
 buf[len]=0;
 return len;
}
#endif

#if _MSC_VER > 1400
static _declspec(noinline)
#endif
// ANSI- oder Unicode-String auf Konsole ausgeben (v.a. für Rahmensymbole)
// bei Umleitung ANSI- oder UTF8-Datei schreiben
void outConsole(PCTSTR s, DWORD l) {
 if (_isatty(_fileno(stdout)))
   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),s,l,&l,NULL);	// Die Unicode-Funktion funktioniert für jede per <chcp> eingestellte Konsolen-Kodeseite
 else{
#ifdef UNICODE
  char u[4000];
  DWORD x=WideCharToMultiByte(CP_UTF8,0,s,l,u,sizeof u,NULL,NULL);
  fwrite(u,1,x,stdout);
#else
  fwrite(s,1,l,stdout);
#endif
 }
}

#if _MSC_VER > 1400
// Ohne "noinline" wirft der Linker vcprintf() in vrprintf() und benötigt __chkstk
static _declspec(noinline)
#endif
void vcprintf(PCTSTR t, va_list va) {
 TCHAR s[2000];
 outConsole(s,_vsntprintf(s,elemof(s),t,va));
}

void vrprintf(int id, va_list va) {
 TCHAR t[2000];
 MyLoadStringO(id,t,elemof(t));
 vcprintf(t,va);	// Stack aufteilen
}

void _cdecl rprintf(int id, ...) {
 va_list va;
 va_start(va,id);
 vrprintf(id,va);
 va_end(va);
}

extern int mygetch(bool noblock) {
 int i=-1;
 if (!noblock || _kbhit()) {
  i=_getch();	// ASCII-Zeichen
  if (!i || i==0xE0) i|=_getch()<<8;	// Scancode (Cursortasten, F-Tasten)
 }		// Scancodes: F1=0x3B .. F10=0x44, ← ↑ → ↓ - unter Linux ganz anders!
 return i;
}

// Je nach Argument wird
// - in einer Busy-Loop gewartet, bis die Zeit abgelaufen ist (< 2 ms)
// - Sleep() in einer Klammer aus timeBegin/EndPeriod() aufgerufen (<20 ms)
// - Sleep() aufgerufen, ohne in den Scheduler einzugreifen (sonst)
void usleep(DWORD us) {
 if (us>=2000) {
  if (us<20000) timeBeginPeriod(1);
  Sleep(us/1000);
  if (us<20000) timeEndPeriod(1);
 }else{
  LARGE_INTEGER freq, tic,toc;
  QueryPerformanceFrequency(&freq);
  freq.LowPart=MulDiv(freq.LowPart,us,1000000);
  QueryPerformanceCounter(&tic);
  do{
   QueryPerformanceCounter(&toc);
  }while (toc.LowPart-tic.LowPart < freq.LowPart);
 }
}

static BOOL CALLBACK HandlerRoutine(DWORD reason) {
 DoExit(45,reason);
 return TRUE;
}

void InitRes() {
 SetConsoleCtrlHandler(HandlerRoutine,TRUE);
}

void CALLBACK mainCRTStartup() {
 extern void _cdecl main(int,TCHAR**);
 int argc;
 TCHAR **argv;
#ifdef UNICODE
 argv = CommandLineToArgvW(GetCommandLine(),&argc);
#else	// es gibt keine ANSI-Version davon,
// daher die undokumentierte MSVCRT.DLL-Version aufrufen
// Die ebenfalls exportierten Variablen __argc, __argv und __envp
// sind erst /nach/ Aufruf jener Funktion richtig gesetzt!
 _CRTIMP void _cdecl __getmainargs(int*,char***,char***,void*,void*);
 char **envp;
 __getmainargs(&argc,&argv,&envp,NULL,&envp);
#endif
 main(argc, argv);
}

/* Port access driver installation */

#ifdef _M_IX86
/*──────────────────────────────────────────────────────────────────────┐
│ Install/Remove eingebautes DirectNT.sys				│
│ Die Datei DirectNT.sys ist in der Ressource (der Windows-Version)	│
│ enthalten und wird bei Bedarf ausgepackt und installiert.		│
│ Das klappt nicht:							│
│ - bei fehlenden Admin-Rechten						│
│ - bei aktiviertem Treiberzertifizierungszwang				│
│ - bei 64-bit-Windows (da ist die .SYS-Datei auch nicht enthalten)	│
├───────────────────────────────────────────────────────────────────────┤
│ Parameter:								│
│  remove = false: installieren						│
│  remove = true: alten Zustand wiederherstellen			│
│ Rückgabe:								│
└──────────────────────────────────────────────────────────────────────*/
extern bool InstallDirectNT(bool remove) {
 bool ret = false;
 static TCHAR SysFileName[MAX_PATH];	// static → zum Löschen der .SYS-Datei
 static bool was_started;		// static → beim Beenden anhalten oder auch nicht
 SC_HANDLE hMgr = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
 if (hMgr) {
  SC_HANDLE hSrv = OpenService(hMgr,T("DirectNT"),SERVICE_ALL_ACCESS);
  SERVICE_STATUS Status;
  if (remove) {
   if (hSrv) {
    ret = was_started			// nicht stoppen
          || ControlService(hSrv,SERVICE_CONTROL_STOP,&Status)
          && (!SysFileName[0] || DeleteFile(SysFileName) && DeleteService(hSrv));
    CloseServiceHandle(hSrv);
   }
  }else{
   if (!hSrv) {
    HRSRC hFR = FindResource(0,MAKEINTRESOURCE(1),RT_RCDATA);
    HGLOBAL hRes = LoadResource(0,hFR);
    if (hRes) {
     HANDLE hSys;
     DWORD bw;
     GetTempPath(elemof(SysFileName),SysFileName);
     PathAppend(SysFileName,T("DirectNT.sys"));
     hSys = CreateFile(SysFileName,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_TEMPORARY,0);
     if (hSys) {
      WriteFile(hSys,LockResource(hRes),SizeofResource(0,hFR),&bw,NULL);
      CloseHandle(hSys);
      hSrv = CreateService(hMgr,
	T("DirectNT"),		// name of service
	T("DirectNT"),		// name to display
	SERVICE_ALL_ACCESS,	// desired access
	SERVICE_KERNEL_DRIVER,	// service type
	SERVICE_DEMAND_START,	// start type
	SERVICE_ERROR_NORMAL,	// error control type
	SysFileName,		// service's binary
	NULL,			// no load ordering group
	NULL,			// no tag identifier
	NULL,			// no dependencies
	NULL,			// LocalSystem account
	NULL);			// no password
      if (!hSrv) {		// CreateService schlug fehl?
       DeleteFile(SysFileName);	// SYS-Datei löschen
       SysFileName[0] = 0;	// nicht noch einmal löschen
      }
     }
    }
   }
   if (hSrv) {
    ret = StartService (hSrv,0,NULL);
    if (!ret && GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) ret=was_started=true;
    CloseServiceHandle(hSrv);
   }
  }
  CloseServiceHandle(hMgr);
 }
 return ret;
}
#else
void __chkstk() {};
#endif

// Portadresse beschaffen
// Funktioniert ab NT4, Win98, aber (für die 32-Bit-Echse) nicht unter Windows 8/64!
// Windows 8/64 verbietet 32-Bit-Programmen den Aufruf von CM_Get_First_Log_Conf().
#include <setupapi.h>
#include <cfgmgr32.h>
#include <devguid.h>

WORD GetParportAddr(int n) {
 WORD start=0;
 TCHAR SucheNach[16];
 HDEVINFO Devs=SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,NULL,0,DIGCF_PRESENT);
 SP_DEVINFO_DATA devInfo;
 int j;
 devInfo.cbSize=sizeof(devInfo);
 _sntprintf(SucheNach,elemof(SucheNach),T("LPT%d"),n+1);
 for (j=0; SetupDiEnumDeviceInfo(Devs,j,&devInfo); j++) {
  HKEY hKey;
  TCHAR val[16];
  DWORD valsize=sizeof(val);
  LOG_CONF Config;
  RES_DES resDes;
  IO_RESOURCE ior;
  if (CM_Open_DevNode_Key(devInfo.DevInst,KEY_QUERY_VALUE,0,RegDisposition_OpenExisting,&hKey,CM_REGISTRY_HARDWARE)) continue;
  if (!RegQueryValueEx(hKey,T("PortName"),NULL,NULL,(LPBYTE)val,&valsize)
  && !lstrcmpi(val,SucheNach)
  && !CM_Get_First_Log_Conf(&Config,devInfo.DevInst,ALLOC_LOG_CONF)
  && !CM_Get_Next_Res_Des(&resDes,Config,ResType_IO,NULL,0)) {
   if (!CM_Get_Res_Des_Data(resDes,&ior,sizeof(ior),0))
     start = (WORD)ior.IO_Header.IOD_Alloc_Base;
   CM_Free_Res_Des_Handle(resDes);
  }
  RegCloseKey(hKey);
  if (start) break;
 }
 SetupDiDestroyDeviceInfoList(Devs);
 return start;
}
Detected encoding: UTF-80