Source file: /~heha/hs/glpntdrv.zip/glpntdrv.cpp

#include "glpntdrv.h"
#include <parallel.h>

#pragma intrinsic(memset)

struct DEVEXT{		// Device Extension
 ULONG xxx;
 PDEVICE_OBJECT parObj;
 ULONG unused[4];
 PHYSICAL_ADDRESS OriginalController;
 PUCHAR Controller;
 ULONG SpanOfController;
 PPARALLEL_TRY_ALLOCATE_ROUTINE allocfunc;
 PPARALLEL_FREE_ROUTINE freefunc;
 PVOID context;
 ULONG unused2[3];
};

// Variablen, einige hatten C-, einige C++-Linkage
// Diese gehören eigentlich allesamt nach DEVEXT, sonst kracht's beim Betrieb zweier GALEPs
CMDBUF *pCmdBuf;
NTSTATUS doio_error;
ULONG i;
KrnlInterfaceHdw io;
ULONG IsIrplHigh;
ULONG DisableCallCount;

extern "C"{
static UCHAR OldIrql;
static bool PortExternBusy;
static PDEVICE_OBJECT pDevObj;
static bool PortAllocFlag;
static ULONG lptport;

// Prototypen
static void FreePort(PDEVICE_OBJECT);
static NTSTATUS FindAndAllocParallelPort(ULONG arg);

// Funktionen exakt in der Reihenfolge wie Conitecs glpntdrv.sys
// Auch in den beiden anderen Dateien, entsprechend alphabetisch angeordnet
void WRITE(UCHAR offset, UCHAR data) {
 WRITE_PORT_UCHAR(PUCHAR(lptport+offset),data);
}

UCHAR READ(UCHAR offset) {
 return READ_PORT_UCHAR(PUCHAR(lptport+offset));
}

void SetIrqlHigh() {
 KeRaiseIrql(HIGH_LEVEL,&OldIrql);
}

void ResetIrql() {
 KeLowerIrql(OldIrql);
}

void SetLPTAddress(CMDBUF*cmdbuf) {
 static ULONG OldAddr;
 ULONG addr=cmdbuf->address;
 if (PortExternBusy
 || OldAddr!=addr
 || !PortAllocFlag) {
  PortExternBusy=false;
#ifdef _M_IX86
  OldAddr=addr;
  PHYSICAL_ADDRESS got_address;
  ULONG addrSpace=1;
  LARGE_INTEGER a={addr};
  if (!HalTranslateBusAddress(Isa,0,a,&addrSpace,&got_address)) {
   doio_error=1002;
   return;
  }
  lptport=got_address.LowPart;
#else
  lptport=addr;
#endif
  if (!NT_SUCCESS(FindAndAllocParallelPort(addr))
  && PortExternBusy) doio_error=1000;
 }
}

void ExternFreePort() {
 FreePort(pDevObj);
}

static NTSTATUS FindAndAllocParallelPort(ULONG addr) {
 FreePort(pDevObj);
 PCONFIGURATION_INFORMATION ci=IoGetConfigurationInformation();
 int numPar=ci->ParallelCount;
 UNICODE_STRING strSpaces;
 static WCHAR spaces[]=L"                                       ";	// 39 spaces
 RtlInitUnicodeString(&strSpaces,spaces);			// (hier NICHT im CONST-Segment!! Problem ab Vista(?))
 WCHAR numBuf[10];
 UNICODE_STRING strNumber={0,sizeof numBuf,numBuf};
 UNICODE_STRING strDevPar;
 RtlInitUnicodeString(&strDevPar,L"\\Device\\ParallelPort");	// 20 Zeichen
 RtlCopyUnicodeString(&strSpaces,&strDevPar);
 if (numPar>0) {
  for(int idx=0;idx<numPar;idx++) {
   RtlCopyUnicodeString(&strSpaces,&strDevPar);		// überschreibt die Leerzeichen
   NTSTATUS ret=RtlIntegerToUnicodeString(idx,10,&strNumber);
   if (!NT_SUCCESS(ret)) return ret;
   ret=RtlAppendUnicodeStringToString(&strSpaces,&strNumber);
   if (!NT_SUCCESS(ret)) return ret;
   DEVEXT *X=(DEVEXT*)pDevObj->DeviceExtension;
   RtlZeroMemory(X,sizeof(DEVEXT));
   PFILE_OBJECT fileObj;
   ret=IoGetDeviceObjectPointer(&strSpaces,FILE_READ_ATTRIBUTES,&fileObj,&X->parObj);
   if (!NT_SUCCESS(ret)) return ret;
   ObDereferenceObject(fileObj);
   pDevObj->StackSize=X->parObj->StackSize+1;		// Huh! Was ist denn das??
   KEVENT event;
   X->unused[2]=0;					// Keine Ahnung!
   KeInitializeEvent(&event,NotificationEvent,false);
   PARALLEL_PORT_INFORMATION ppi;
   IO_STATUS_BLOCK ioStatus;
   IRP *irp=IoBuildDeviceIoControlRequest(
     IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO,X->parObj,	// 0x160030
     NULL,0,
     &ppi,sizeof ppi,
     true,						// internal IOCTL
     &event,&ioStatus);
   if (!irp) return STATUS_INSUFFICIENT_RESOURCES;
   ret=IoCallDriver(X->parObj,irp);
   if (!NT_SUCCESS(ret)) return ret;
   ret=KeWaitForSingleObject(&event,Executive,KernelMode,false,NULL);
   if (!NT_SUCCESS(ret)) return ret;
   KeClearEvent(&event);
   X->OriginalController=ppi.OriginalController;
   X->Controller=ppi.Controller;			// unbenutzt
   X->SpanOfController=ppi.SpanOfController;		// unbenutzt
   X->allocfunc=ppi.TryAllocatePort;
   X->freefunc=ppi.FreePort;
   X->context=ppi.Context;
   if (X->OriginalController.LowPart==addr) {
    if (X->allocfunc(X->context)) {
     PortAllocFlag=true;
     PortExternBusy=false;
     break;
    }else{
     PortExternBusy=true; 
     return STATUS_ADAPTER_HARDWARE_ERROR;
    }
   }
  }
 }
 return STATUS_SUCCESS;
}

static void FreePort(PDEVICE_OBJECT devObj) {
 if (PortAllocFlag) {
  DEVEXT *X=(DEVEXT*)devObj->DeviceExtension;
  X->freefunc(X->context);
  PortAllocFlag=false;
 }
}

void ExternalDelay(ULONG us) {
 KeStallExecutionProcessor(us);
}

static NTSTATUS DoIrpDeviceControl(IN PDEVICE_OBJECT devObj, IN PIRP I, IN PIO_STACK_LOCATION irpStack) {
 if (irpStack->Parameters.DeviceIoControl.IoControlCode!=IOCTL_GALEP) return STATUS_NOT_IMPLEMENTED;
 doio_error=0;
 pDevObj=devObj;
 CMDBUF *cmdbuf=(CMDBUF*)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
 if (!doio(cmdbuf)) cmdbuf->errorcode=doio_error;
 I->IoStatus.Information=sizeof(CMDBUF);
 return STATUS_SUCCESS;
}

static NTSTATUS DoIrpClose(IN PDEVICE_OBJECT, IN PIRP) {
 return STATUS_SUCCESS;
}

static NTSTATUS DispatchFunction(IN PDEVICE_OBJECT devObj, IN PIRP I) {
 I->IoStatus.Information=0;
 PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(I);
 I->IoStatus.Status=irpStack->MajorFunction==IRP_MJ_DEVICE_CONTROL
   ?DoIrpDeviceControl(devObj,I,irpStack)
   :STATUS_NOT_IMPLEMENTED;
 IoCompleteRequest(I,0);
 return STATUS_SUCCESS;
}

static NTSTATUS CreateDevice(PDRIVER_OBJECT drvObj) {
 UNICODE_STRING ntName,dosName;
 PDEVICE_OBJECT devObj;
 RtlInitUnicodeString(&ntName,L"\\Device\\glpntdrv");
 RtlInitUnicodeString(&dosName,L"\\DosDevices\\glpntdrv");
 NTSTATUS ret=IoCreateDevice(drvObj,sizeof(DEVEXT),&ntName,FILE_DEVICE_UNKNOWN,0,TRUE,&devObj);
 if (!ret) {
  devObj->Flags|=DO_DIRECT_IO;
  ret=IoCreateSymbolicLink(&dosName,&ntName);
  if (ret) IoDeleteDevice(devObj);
 }
 return ret;
}

static NTSTATUS DeleteDevice(PDRIVER_OBJECT drvObj) {
 IoDeleteDevice(drvObj->DeviceObject);
 return STATUS_SUCCESS;
}

static void UnloadDriver(IN PDRIVER_OBJECT drvObj) {
 UNICODE_STRING dosName;
 RtlInitUnicodeString(&dosName,L"\\DosDevices\\glpntdrv");
 IoDeleteSymbolicLink(&dosName);
 FreePort(drvObj->DeviceObject);
 DeleteDevice(drvObj);
}

static NTSTATUS InitDriver(PDRIVER_OBJECT drvObj) {
 return CreateDevice(drvObj);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING /*regPath*/) {
 drvObj->MajorFunction[IRP_MJ_CREATE] = DoIrpClose;
 drvObj->MajorFunction[IRP_MJ_CLOSE] = DoIrpClose;
 drvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFunction;
 drvObj->DriverUnload = UnloadDriver;
 return InitDriver(drvObj);
}

}//extern "C"
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded