ref: 662ad8cbcdc389b41693fbe2fcf567275d3408e7
dir: /opl/ioperm_sys.c/
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 2002, 2003 Marcel Telka
// Copyright(C) 2009 Simon Howard
//
// 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-1307, USA.
//
// DESCRIPTION:
// Interface to the ioperm.sys driver, based on code from the
// Cygwin ioperm library.
//
//-----------------------------------------------------------------------------
#ifdef _WIN32
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winioctl.h>
#include <errno.h>
#include "ioperm_sys.h"
#define IOPERM_FILE L"\\\\.\\ioperm"
#define IOCTL_IOPERM \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0xA00, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct ioperm_data
{
unsigned long from;
unsigned long num;
int turn_on;
};
static SC_HANDLE scm = NULL;
static SC_HANDLE svc = NULL;
static int service_was_created = 0;
static int service_was_started = 0;
int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on)
{
HANDLE h;
struct ioperm_data ioperm_data;
DWORD BytesReturned;
BOOL r;
h = CreateFileW(IOPERM_FILE, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
errno = ENODEV;
return -1;
}
ioperm_data.from = from;
ioperm_data.num = num;
ioperm_data.turn_on = turn_on;
r = DeviceIoControl(h, IOCTL_IOPERM,
&ioperm_data, sizeof ioperm_data,
NULL, 0,
&BytesReturned, NULL);
if (!r)
{
errno = EPERM;
}
CloseHandle(h);
return r != 0;
}
// Load ioperm.sys driver.
// Returns 1 for success, 0 for failure.
// Remember to call IOperm_UninstallDriver to uninstall the driver later.
int IOperm_InstallDriver(void)
{
wchar_t driver_path[MAX_PATH];
int error;
int result = 1;
scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (scm == NULL)
{
error = GetLastError();
fprintf(stderr, "IOperm_InstallDriver: OpenSCManager failed (%i).\n",
error);
return 0;
}
// Get the full path to the driver file.
GetFullPathNameW(L"ioperm.sys", MAX_PATH, driver_path, NULL);
// Create the service.
svc = CreateServiceW(scm,
L"ioperm",
L"ioperm support for Cygwin driver",
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
driver_path,
NULL,
NULL,
NULL,
NULL,
NULL);
if (svc == NULL)
{
error = GetLastError();
if (error != ERROR_SERVICE_EXISTS)
{
fprintf(stderr,
"IOperm_InstallDriver: Failed to create service (%i).\n",
error);
}
else
{
svc = OpenServiceW(scm, L"ioperm", SERVICE_ALL_ACCESS);
if (svc == NULL)
{
error = GetLastError();
fprintf(stderr,
"IOperm_InstallDriver: Failed to open service (%i).\n",
error);
}
}
if (svc == NULL)
{
CloseServiceHandle(scm);
return 0;
}
}
else
{
service_was_created = 1;
}
// Start the service. If the service already existed, it might have
// already been running as well.
if (!StartServiceW(svc, 0, NULL))
{
error = GetLastError();
if (error != ERROR_SERVICE_ALREADY_RUNNING)
{
fprintf(stderr, "IOperm_InstallDriver: Failed to start service (%i).\n",
error);
result = 0;
}
else
{
printf("IOperm_InstallDriver: ioperm driver already running.\n");
}
}
else
{
printf("IOperm_InstallDriver: ioperm driver installed.\n");
service_was_started = 1;
}
// If we failed to start the driver running, we need to clean up
// before finishing.
if (result == 0)
{
IOperm_UninstallDriver();
}
return result;
}
int IOperm_UninstallDriver(void)
{
SERVICE_STATUS stat;
int result = 1;
int error;
// If we started the service, stop it.
if (service_was_started)
{
if (!ControlService(svc, SERVICE_CONTROL_STOP, &stat))
{
error = GetLastError();
if (error == ERROR_SERVICE_NOT_ACTIVE)
{
fprintf(stderr,
"IOperm_UninstallDriver: Service not active? (%i)\n",
error);
}
else
{
fprintf(stderr,
"IOperm_UninstallDriver: Failed to stop service (%i).\n",
error);
result = 0;
}
}
}
// If we created the service, delete it.
if (service_was_created)
{
if (!DeleteService(svc))
{
error = GetLastError();
fprintf(stderr,
"IOperm_UninstallDriver: DeleteService failed (%i).\n",
error);
result = 0;
}
else if (service_was_started)
{
printf("IOperm_UnInstallDriver: ioperm driver uninstalled.\n");
}
}
// Close handles.
if (svc != NULL)
{
CloseServiceHandle(svc);
svc = NULL;
}
if (scm != NULL)
{
CloseServiceHandle(scm);
scm = NULL;
}
service_was_created = 0;
service_was_started = 0;
return result;
}
#endif /* #ifndef _WIN32 */