[Uha-devel] CVS: uha/super/windows MAKEFILE, NONE, 1.1 SOURCES, NONE, 1.1 dhahelper.c, NONE, 1.1 dhahelper.h, NONE, 1.1 dhasetup.c, NONE, 1.1
Update of /cvsroot/uha/uha/super/windows In directory mail:/home/alex/uha/uha/super/windows Added Files: MAKEFILE SOURCES dhahelper.c dhahelper.h dhasetup.c Log Message: initial commit --- NEW FILE: MAKEFILE --- # # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source # file to this component. This file merely indirects to the real make file # that is shared by all the driver components of the Windows NT DDK # !INCLUDE $(NTMAKEENV)\makefile.def --- NEW FILE: SOURCES --- TARGETNAME=dhahelper TARGETPATH=. TARGETTYPE=DRIVER NTDEBUG=ntsd SOURCES= dhahelper.c --- NEW FILE: dhahelper.c --- /****************************************************************************** * dhahelper.c: direct hardware access under Windows NT/2000/XP * Copyright (c) 2004 Sascha Sommer <saschasommer@freenet.de>. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * *****************************************************************************/ #include <ntddk.h> #include "dhahelper.h" #define OutputDebugString DbgPrint #define IOPM_SIZE 0x2000 typedef char IOPM[IOPM_SIZE]; static IOPM *pIOPM = NULL; typedef struct { PMDL Mdl; PVOID SystemVirtualAddress; PVOID UserVirtualAddress; ULONG PhysMemSizeInBytes; }alloc_priv; static alloc_priv* alloclist; static unsigned int alloccount=0; static NTSTATUS dhahelperdispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); static void dhahelperunload(IN PDRIVER_OBJECT DriverObject); static NTSTATUS UnmapPhysicalMemory(PVOID UserVirtualAddress); static NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,ULONG PhysMemSizeInBytes,PVOID *PhysMemLin); void Ke386SetIoAccessMap(int, IOPM *); void Ke386QueryIoAccessMap(int, IOPM *); void Ke386IoSetAccessProcess(PEPROCESS, int); //entry point NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath){ UNICODE_STRING DeviceNameUnicodeString; UNICODE_STRING DeviceLinkUnicodeString; NTSTATUS ntStatus; PDEVICE_OBJECT DeviceObject = NULL; OutputDebugString ("dhahelper: entering DriverEntry"); RtlInitUnicodeString (&DeviceNameUnicodeString, L"\\Device\\DHAHELPER"); // Create an EXCLUSIVE device object (only 1 thread at a time // can make requests to this device). ntStatus = IoCreateDevice(DriverObject,0,&DeviceNameUnicodeString,FILE_DEVICE_DHAHELPER,0,TRUE,&DeviceObject); if (NT_SUCCESS(ntStatus)){ // Create dispatch points for device control, create, close. DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = dhahelperdispatch; DriverObject->DriverUnload = dhahelperunload; // Create a symbolic link, e.g. a name that a Win32 app can specify // to open the device. RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\\DosDevices\\DHAHELPER"); ntStatus = IoCreateSymbolicLink(&DeviceLinkUnicodeString,&DeviceNameUnicodeString); if (!NT_SUCCESS(ntStatus)){ // Symbolic link creation failed- note this & then delete the // device object (it's useless if a Win32 app can't get at it). OutputDebugString ("dhahelper: IoCreateSymbolicLink failed"); IoDeleteDevice (DeviceObject); } } else{ OutputDebugString ("dhahelper: IoCreateDevice failed"); } OutputDebugString ("dhahelper: leaving DriverEntry"); return ntStatus; } // Process the IRPs sent to this device static NTSTATUS dhahelperdispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp){ PIO_STACK_LOCATION IrpStack; ULONG dwInputBufferLength; ULONG dwOutputBufferLength; ULONG dwIoControlCode; PVOID pvIOBuffer; NTSTATUS ntStatus; dhahelper_t dhahelper_priv; OutputDebugString ("dhahelper: entering dhahelperdispatch"); // Init to default settings Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IrpStack = IoGetCurrentIrpStackLocation(Irp); // Get the pointer to the input/output buffer and it's length pvIOBuffer = Irp->AssociatedIrp.SystemBuffer; dwInputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; dwOutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (IrpStack->MajorFunction){ case IRP_MJ_CREATE: OutputDebugString("dhahelper: IRP_MJ_CREATE"); break; case IRP_MJ_CLOSE: OutputDebugString("dhahelper: IRP_MJ_CLOSE"); break; case IRP_MJ_DEVICE_CONTROL: OutputDebugString("dhahelper: IRP_MJ_DEVICE_CONTROL"); dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; switch (dwIoControlCode){ case IOCTL_DHAHELPER_ENABLEDIRECTIO: OutputDebugString("dhahelper: IOCTL_DHAHELPER_ENABLEDIRECTIO"); pIOPM = MmAllocateNonCachedMemory(sizeof(IOPM)); if (pIOPM){ RtlZeroMemory(pIOPM, sizeof(IOPM)); Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1); Ke386SetIoAccessMap(1, pIOPM); } else Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; break; case IOCTL_DHAHELPER_DISABLEDIRECTIO: OutputDebugString("dhahelper: IOCTL_DHAHELPER_DISABLEDIRECTIO"); if (pIOPM){ Ke386IoSetAccessProcess(PsGetCurrentProcess(), 0); Ke386SetIoAccessMap(1, pIOPM); MmFreeNonCachedMemory(pIOPM, sizeof(IOPM)); pIOPM = NULL; } break; case IOCTL_DHAHELPER_MAPPHYSTOLIN: OutputDebugString("dhahelper: IOCTL_DHAHELPER_MAPPHYSTOLIN"); if (dwInputBufferLength){ memcpy (&dhahelper_priv, pvIOBuffer, dwInputBufferLength); ntStatus = MapPhysicalMemoryToLinearSpace(dhahelper_priv.base,dhahelper_priv.size,&dhahelper_priv.ptr); if (NT_SUCCESS(ntStatus)){ memcpy (pvIOBuffer, &dhahelper_priv, dwInputBufferLength); Irp->IoStatus.Information = dwInputBufferLength; } Irp->IoStatus.Status = ntStatus; } else Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; case IOCTL_DHAHELPER_UNMAPPHYSADDR: OutputDebugString("dhahelper: IOCTL_DHAHELPER_UNMAPPHYSADDR"); if (dwInputBufferLength){ memcpy (&dhahelper_priv, pvIOBuffer, dwInputBufferLength); ntStatus = UnmapPhysicalMemory(dhahelper_priv.ptr); Irp->IoStatus.Status = ntStatus; } else Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; default: OutputDebugString("dhahelper: unknown IRP_MJ_DEVICE_CONTROL"); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; } break; } // DON'T get cute and try to use the status field of the irp in the // return status. That IRP IS GONE as soon as you call IoCompleteRequest. ntStatus = Irp->IoStatus.Status; IoCompleteRequest (Irp, IO_NO_INCREMENT); // We never have pending operation so always return the status code. OutputDebugString("dhahelper: leaving dhahelperdispatch"); return ntStatus; } // Delete the associated device and return static void dhahelperunload(IN PDRIVER_OBJECT DriverObject){ UNICODE_STRING DeviceLinkUnicodeString; NTSTATUS ntStatus=STATUS_SUCCESS; OutputDebugString ("dhahelper: entering dhahelperunload"); OutputDebugString ("dhahelper: unmapping remaining memory"); while(alloccount && (ntStatus==STATUS_SUCCESS))ntStatus = UnmapPhysicalMemory(alloclist[alloccount-1].UserVirtualAddress); RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\\DosDevices\\DHAHELPER"); ntStatus = IoDeleteSymbolicLink (&DeviceLinkUnicodeString); if (NT_SUCCESS(ntStatus)){ IoDeleteDevice (DriverObject->DeviceObject); } else { OutputDebugString ("dhahelper: IoDeleteSymbolicLink failed"); } OutputDebugString ("dhahelper: leaving dhahelperunload"); } /************************* memory mapping functions ******************************/ //unlike the functions of other io helpers these functions allow to map adapter memory on windows xp //even if it has alread been mapped by the original driver //the technique used is described in //http://support.microsoft.com/default.aspx?scid=kb;en-us;q189327 //furthermore it keeps a list of mapped areas to free them when the driver gets unloaded //I'm not sure what the limitations of ZwMapViewOfSection are but mapping 128MB videoram (that is probably already mapped by the gfxcard driver) //won't work so it is generally a good idea to map only the memory you really need static NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,ULONG PhysMemSizeInBytes,PVOID *PhysMemLin){ alloc_priv* alloclisttmp; PMDL Mdl=NULL; PVOID SystemVirtualAddress=NULL; PVOID UserVirtualAddress=NULL; PHYSICAL_ADDRESS pStartPhysAddress; OutputDebugString ("dhahelper: entering MapPhysicalMemoryToLinearSpace"); pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress; __try { SystemVirtualAddress=MmMapIoSpace(pStartPhysAddress,PhysMemSizeInBytes, /*MmWriteCombined*/MmNonCached); if(!SystemVirtualAddress){ OutputDebugString("dhahelper: MmMapIoSpace failed"); return STATUS_INVALID_PARAMETER; } OutputDebugString("dhahelper: SystemVirtualAddress 0x%x",SystemVirtualAddress); Mdl=IoAllocateMdl(SystemVirtualAddress, PhysMemSizeInBytes, FALSE, FALSE,NULL); if(!Mdl){ OutputDebugString("dhahelper: IoAllocateMdl failed"); return STATUS_INSUFFICIENT_RESOURCES; } OutputDebugString("dhahelper: Mdl 0x%x",Mdl); MmBuildMdlForNonPagedPool(Mdl); UserVirtualAddress = (PVOID)(((ULONG)PAGE_ALIGN(MmMapLockedPages(Mdl,UserMode))) + MmGetMdlByteOffset(Mdl)); if(!UserVirtualAddress){ OutputDebugString("dhahelper: MmMapLockedPages failed"); return STATUS_INSUFFICIENT_RESOURCES; } OutputDebugString("dhahelper: UserVirtualAddress 0x%x",UserVirtualAddress); }__except(EXCEPTION_EXECUTE_HANDLER){ NTSTATUS ntStatus; ntStatus = GetExceptionCode(); OutputDebugString("dhahelper: MapPhysicalMemoryToLinearSpace failed due to exception 0x%0x\n", ntStatus); return ntStatus; } OutputDebugString("dhahelper: adding data to internal allocation list"); alloclisttmp=MmAllocateNonCachedMemory((alloccount+1)*sizeof(alloc_priv)); if(!alloclisttmp){ OutputDebugString("dhahelper: not enough memory to create temporary allocation list"); MmUnmapLockedPages(UserVirtualAddress, Mdl); IoFreeMdl(Mdl); return STATUS_INSUFFICIENT_RESOURCES; } if(alloccount){ memcpy(alloclisttmp,alloclist,alloccount * sizeof(alloc_priv)); MmFreeNonCachedMemory(alloclist,alloccount*sizeof(alloc_priv)); } alloclist=alloclisttmp; alloclist[alloccount].Mdl=Mdl; alloclist[alloccount].SystemVirtualAddress=SystemVirtualAddress; alloclist[alloccount].UserVirtualAddress=UserVirtualAddress; alloclist[alloccount].PhysMemSizeInBytes=PhysMemSizeInBytes; ++alloccount; *PhysMemLin=UserVirtualAddress; OutputDebugString("dhahelper: leaving MapPhysicalMemoryToLinearSpace"); return STATUS_SUCCESS; } static NTSTATUS UnmapPhysicalMemory(PVOID UserVirtualAddress){ unsigned int i; unsigned int x=0; unsigned int alloccounttmp=alloccount; OutputDebugString("dhahelper: entering UnmapPhysicalMemory to unmapp 0x%x",UserVirtualAddress); if(!alloccount){ OutputDebugString("dhahelper: UnmapPhysicalMemory: nothing todo -> leaving..."); return STATUS_SUCCESS; } for(i=0;i<alloccount;i++){ if(alloclist[i].UserVirtualAddress!=UserVirtualAddress){ if(x!=i){ alloclist[x].Mdl=alloclist[i].Mdl; alloclist[x].SystemVirtualAddress=alloclist[i].SystemVirtualAddress; alloclist[x].UserVirtualAddress=alloclist[i].UserVirtualAddress; alloclist[x].PhysMemSizeInBytes=alloclist[i].PhysMemSizeInBytes; } x++; } else if(alloclist[i].UserVirtualAddress==UserVirtualAddress){ if(x==i){ __try { MmUnmapLockedPages(alloclist[x].UserVirtualAddress, alloclist[x].Mdl); IoFreeMdl(alloclist[x].Mdl); MmUnmapIoSpace(alloclist[x].SystemVirtualAddress,alloclist[x].PhysMemSizeInBytes); }__except(EXCEPTION_EXECUTE_HANDLER){ NTSTATUS ntStatus; ntStatus = GetExceptionCode(); OutputDebugString("dhahelper: UnmapPhysicalMemory failed due to exception 0x%0x (Mdl 0x%x)\n", ntStatus,alloclist[x].Mdl); return ntStatus; } } alloccounttmp--; } } if(alloccounttmp){ alloc_priv* alloclisttmp; alloclisttmp=MmAllocateNonCachedMemory(alloccounttmp*sizeof(alloc_priv)); if(!alloclisttmp){ OutputDebugString("dhahelper: not enough memory to create temporary allocation list"); return STATUS_INSUFFICIENT_RESOURCES; } memcpy(alloclisttmp,alloclist,alloccounttmp * sizeof(alloc_priv)); MmFreeNonCachedMemory(alloclist,alloccount*sizeof(alloc_priv)); alloclist=alloclisttmp; } alloccount=alloccounttmp; OutputDebugString("dhahelper: leaving UnmapPhysicalMemory"); return STATUS_SUCCESS; } --- NEW FILE: dhahelper.h --- #ifndef _DHAHELPER_H #define _DHAHELPER_H 1 // Define the various device type values. Note that values used by Microsoft // Corporation are in the range 0-32767, and 32768-65535 are reserved for use // by customers. #define FILE_DEVICE_DHAHELPER 0x00008011 // Macro definition for defining IOCTL and FSCTL function control codes. // Note that function codes 0-2047 are reserved for Microsoft Corporation, // and 2048-4095 are reserved for customers. #define DHAHELPER_IOCTL_INDEX 0x810 #define IOCTL_DHAHELPER_MAPPHYSTOLIN CTL_CODE(FILE_DEVICE_DHAHELPER, \ DHAHELPER_IOCTL_INDEX, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #define IOCTL_DHAHELPER_UNMAPPHYSADDR CTL_CODE(FILE_DEVICE_DHAHELPER, \ DHAHELPER_IOCTL_INDEX + 1, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #define IOCTL_DHAHELPER_ENABLEDIRECTIO CTL_CODE(FILE_DEVICE_DHAHELPER, \ DHAHELPER_IOCTL_INDEX + 2, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #define IOCTL_DHAHELPER_DISABLEDIRECTIO CTL_CODE(FILE_DEVICE_DHAHELPER, \ DHAHELPER_IOCTL_INDEX + 3, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #if !defined(__MINGW32__) && !defined(__CYGWIN__) #pragma pack(1) typedef struct dhahelper_t { #else struct __attribute__((__packed__)) dhahelper_t { #endif unsigned int size; void* base; void* ptr; }; typedef struct dhahelper_t dhahelper_t; #endif --- NEW FILE: dhasetup.c --- /* dhahelper setup program (c) 2004 Sascha Sommer */ /* compile with gcc -o dhasetup.exe dhasetup.c */ /* LICENSE: GPL */ #include <windows.h> #include <stdio.h> int main(int argc,char* argv[]){ SC_HANDLE hSCManager; SC_HANDLE hService; char path[MAX_PATH]; printf("dhasetup (c) 2004 Sascha Sommer\n"); GetWindowsDirectory(path,MAX_PATH); strcpy(path+strlen(path),"\\system32\\drivers\\dhahelper.sys"); if(argc==1){ printf("Usage:\n"); printf("dhasetup install - Copies dhahelper.sys from the current directory to\n%s and configures it to start at boot.\n", path); printf("dhasetup remove - Removes the dhahelper utility.\n"); return 0; } hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!strcmp(argv[1],"install")){ printf("Installing dhahelper...\n"); if(!CopyFile("dhahelper.sys",path,FALSE)){ printf("Copying dhahelper.sys failed.\nEither dhahelper.sys is not in the current directory or you lack sufficient\nprivileges to write to %s.", path); return 1; } // Install the driver hService = CreateService(hSCManager, "DHAHELPER", "DHAHELPER", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL); if(!hService){ printf("Unable to register DHAHELPER Service (0x%x).\n",GetLastError()); } } else if(!strcmp(argv[1],"remove")){ SERVICE_STATUS ServiceStatus; printf("Removing dhahelper...\n"); hService = OpenService(hSCManager, "DHAHELPER", SERVICE_ALL_ACCESS); ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus); DeleteService(hService); DeleteFile(path); } else { printf("unknown parameter: %s\n",argv[1]); } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); printf("Please reboot to let the changes take effect.\n"); return 0; }
participants (1)
-
alex@mplayerhq.hu