Source file: /~heha/hsn/glpntdrv.zip/h#s/glpntdrv.cpp

#include "glpntdrv.h"

#pragma intrinsic(memset)
/*
void KrnlInterfaceHdw::Disable() {
 if (!DisableCallCount++) KeRaiseIrql(HIGH_LEVEL,&OldIrql);
}

void KrnlInterfaceHdw::Enable() {
 if (!--DisableCallCount) KeLowerIrql(OldIrql);
}
*/
long GALEP::FreePort(long) {
 if (PortAllocFlag) {
  freefunc(context);
  PortAllocFlag=false;
 }
 return 0;
}


NTSTATUS GALEP::FindAndAllocParallelPort(ULONG addr) {
 FreePort(0);
 PCONFIGURATION_INFORMATION ci=IoGetConfigurationInformation();
 int numPar=ci->ParallelCount;
 WCHAR space[32];
 UNICODE_STRING strSpace={0,sizeof space,space};
 WCHAR numBuf[10];
 UNICODE_STRING strNumber={0,sizeof numBuf,numBuf};
 UNICODE_STRING strDevPar;
 RtlInitUnicodeString(&strDevPar,L"\\Device\\ParallelPort");	// 20 Zeichen
 RtlCopyUnicodeString(&strSpace,&strDevPar);
 for (int idx=0; idx<numPar; idx++) {
  RtlCopyUnicodeString(&strSpace,&strDevPar);
  NTSTATUS ret=RtlIntegerToUnicodeString(idx,10,&strNumber);
  if (!NT_SUCCESS(ret)) return ret;
  ret=RtlAppendUnicodeStringToString(&strSpace,&strNumber);
  if (!NT_SUCCESS(ret)) return ret;
  PFILE_OBJECT fileObj;
  PDEVICE_OBJECT parObj;
  ret=IoGetDeviceObjectPointer(&strSpace,FILE_READ_ATTRIBUTES,&fileObj,&parObj);
  if (!NT_SUCCESS(ret)) return ret;
  ObDereferenceObject(fileObj);
  pDevObj->StackSize=parObj->StackSize+1;		// Huh! Was ist denn das??
  KEVENT event;
  KeInitializeEvent(&event,NotificationEvent,false);
  PARALLEL_PORT_INFORMATION ppi;
  IO_STATUS_BLOCK ioStatus;
  IRP *irp=IoBuildDeviceIoControlRequest(
    IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO,parObj,	// 0x160030
    NULL,0,
    &ppi,sizeof ppi,
    true,						// internal IOCTL
    &event,&ioStatus);
  if (!irp) return STATUS_INSUFFICIENT_RESOURCES;
  ret=IoCallDriver(parObj,irp);
  if (!NT_SUCCESS(ret)) return ret;
  ret=KeWaitForSingleObject(&event,Executive,KernelMode,false,NULL);
  if (!NT_SUCCESS(ret)) return ret;
  KeClearEvent(&event);
  allocfunc=ppi.TryAllocatePort;
  freefunc=ppi.FreePort;
  context=ppi.Context;
  if (ppi.OriginalController.LowPart==addr) {
   if (allocfunc(context)) {
    PortAllocFlag=true;
    PortExternBusy=false;
    break;
   }else{
    PortExternBusy=true; 
    return STATUS_ADAPTER_HARDWARE_ERROR;
   }
  }
 }
 return STATUS_SUCCESS;
}


long GALEP::SetLPTAddress(long addr) {
 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)) {
   pCmdBuf->errorcode=1002;
   return 0;
  }
  lptport=got_address.LowPart;
#else
  lptport=addr;
#endif
  if (NT_SUCCESS(FindAndAllocParallelPort(addr))
  && PortExternBusy) pCmdBuf->errorcode=1000;
 }
 return 0;
}

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;
 GALEP*p=(GALEP*)irpStack->FileObject->FsContext;
 p->doio(devObj,(CMDBUF*)irpStack->Parameters.DeviceIoControl.Type3InputBuffer);
 I->IoStatus.Information=sizeof(CMDBUF);
 return STATUS_SUCCESS;
}

static NTSTATUS DispatchCreate(DEVICE_OBJECT*, IRP*I) {
 GALEP*p=(GALEP*)ExAllocatePool(PagedPool,sizeof(GALEP));
 if (!p) return STATUS_NO_MEMORY;
 IoGetCurrentIrpStackLocation(I)->FileObject->FsContext=p;
 return STATUS_SUCCESS;
}

static NTSTATUS DispatchClose(DEVICE_OBJECT*, IRP*I) {
 GALEP*p=(GALEP*)IoGetCurrentIrpStackLocation(I)->FileObject->FsContext;
 p->FreePort(0);
 ExFreePool(p);
 return STATUS_SUCCESS;
}

static NTSTATUS DispatchDeviceControl(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;
 PDEVICE_OBJECT devObj;
 RtlInitUnicodeString(&ntName,L"\\Device\\glpntdrv");
 NTSTATUS ret=IoCreateDevice(drvObj,0,&ntName,FILE_DEVICE_UNKNOWN,0,FALSE,&devObj);
 if (!ret) {
  devObj->Flags|=DO_DIRECT_IO;
  UNICODE_STRING dosName;
  RtlInitUnicodeString(&dosName,L"\\DosDevices\\glpntdrv");
  ret=IoCreateSymbolicLink(&dosName,&ntName);
  if (ret) IoDeleteDevice(devObj);
 }
 return ret;
}

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

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT drvObj, IN PUNICODE_STRING /*regPath*/) {
 drvObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
 drvObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
 drvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
 drvObj->DriverUnload = DriverUnload;
 return CreateDevice(drvObj);
}
Detected encoding: ASCII (7 bit)2