You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
7.8 KiB
294 lines
7.8 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Module Name:
|
|
|
|
IOCTL.C
|
|
|
|
Abstract:
|
|
|
|
This modules contains functions to register/deregsiter a control-
|
|
deviceobject for ioctl purposes and dispatch routine for handling
|
|
ioctl requests from usermode.
|
|
|
|
Revision History:
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#if defined(IOCTL_INTERFACE)
|
|
|
|
|
|
#include "miniport.h"
|
|
#include "public.h"
|
|
|
|
//
|
|
// Simple Mutual Exclusion constructs used in preference to
|
|
// using KeXXX calls since we don't have Mutex calls in NDIS.
|
|
// These can only be called at passive IRQL.
|
|
//
|
|
|
|
typedef struct _NIC_MUTEX
|
|
{
|
|
ULONG Counter;
|
|
ULONG ModuleAndLine; // useful for debugging
|
|
|
|
} NIC_MUTEX, *PNIC_MUTEX;
|
|
|
|
#define NIC_INIT_MUTEX(_pMutex) \
|
|
{ \
|
|
(_pMutex)->Counter = 0; \
|
|
(_pMutex)->ModuleAndLine = 0; \
|
|
}
|
|
|
|
#define NIC_ACQUIRE_MUTEX(_pMutex) \
|
|
{ \
|
|
while (NdisInterlockedIncrement((PLONG)&((_pMutex)->Counter)) != 1)\
|
|
{ \
|
|
NdisInterlockedDecrement((PLONG)&((_pMutex)->Counter)); \
|
|
NdisMSleep(10000); \
|
|
} \
|
|
(_pMutex)->ModuleAndLine = ('I' << 16) | __LINE__;\
|
|
}
|
|
|
|
#define NIC_RELEASE_MUTEX(_pMutex) \
|
|
{ \
|
|
(_pMutex)->ModuleAndLine = 0; \
|
|
NdisInterlockedDecrement((PLONG)&(_pMutex)->Counter); \
|
|
}
|
|
|
|
#define LINKNAME_STRING L"\\DosDevices\\NETVMINI"
|
|
#define NTDEVICE_STRING L"\\Device\\NETVMINI"
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
|
|
NDIS_HANDLE NdisDeviceHandle = NULL; // From NdisMRegisterDevice
|
|
LONG MiniportCount = 0; // Total number of miniports in existance
|
|
PDEVICE_OBJECT ControlDeviceObject = NULL; // Device for IOCTLs
|
|
NIC_MUTEX ControlDeviceMutex;
|
|
extern NDIS_HANDLE NdisWrapperHandle;
|
|
|
|
#pragma NDIS_PAGEABLE_FUNCTION(NICRegisterDevice)
|
|
#pragma NDIS_PAGEABLE_FUNCTION(NICDeregisterDevice)
|
|
#pragma NDIS_PAGEABLE_FUNCTION(NICDispatch)
|
|
|
|
|
|
NDIS_STATUS
|
|
NICRegisterDevice(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Register an ioctl interface - a device object to be used for this
|
|
purpose is created by NDIS when we call NdisMRegisterDevice.
|
|
|
|
This routine is called whenever a new miniport instance is
|
|
initialized. However, we only create one global device object,
|
|
when the first miniport instance is initialized. This routine
|
|
handles potential race conditions with NICDeregisterDevice via
|
|
the ControlDeviceMutex.
|
|
|
|
NOTE: do not call this from DriverEntry; it will prevent the driver
|
|
from being unloaded (e.g. on uninstall).
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if we successfully register a device object.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
UNICODE_STRING DeviceName;
|
|
UNICODE_STRING DeviceLinkUnicodeString;
|
|
PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
|
|
|
|
DEBUGP(MP_TRACE, ("==>NICRegisterDevice\n"));
|
|
|
|
NIC_ACQUIRE_MUTEX(&ControlDeviceMutex);
|
|
|
|
++MiniportCount;
|
|
|
|
if (1 == MiniportCount)
|
|
{
|
|
NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
|
|
|
|
DispatchTable[IRP_MJ_CREATE] = NICDispatch;
|
|
DispatchTable[IRP_MJ_CLEANUP] = NICDispatch;
|
|
DispatchTable[IRP_MJ_CLOSE] = NICDispatch;
|
|
DispatchTable[IRP_MJ_DEVICE_CONTROL] = NICDispatch;
|
|
|
|
|
|
NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
|
|
NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
|
|
|
|
//
|
|
// Create a device object and register our dispatch handlers
|
|
//
|
|
Status = NdisMRegisterDevice(
|
|
NdisWrapperHandle,
|
|
&DeviceName,
|
|
&DeviceLinkUnicodeString,
|
|
&DispatchTable[0],
|
|
&ControlDeviceObject,
|
|
&NdisDeviceHandle
|
|
);
|
|
}
|
|
|
|
NIC_RELEASE_MUTEX(&ControlDeviceMutex);
|
|
|
|
DEBUGP(MP_TRACE, ("<==NICRegisterDevice: %x\n", Status));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NICDispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Process IRPs sent to this device.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object
|
|
Irp - pointer to an I/O Request Packet
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - STATUS_SUCCESS always - change this when adding
|
|
real code to handle ioctls.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG inlen;
|
|
PVOID buffer;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DEBUGP(MP_TRACE, ("==>NICDispatch %d\n", irpStack->MajorFunction));
|
|
|
|
switch (irpStack->MajorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
break;
|
|
|
|
case IRP_MJ_CLEANUP:
|
|
break;
|
|
|
|
case IRP_MJ_CLOSE:
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
{
|
|
|
|
buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
|
|
|
|
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
|
|
//
|
|
// Add code here to handle ioctl commands.
|
|
//
|
|
case IOCTL_NETVMINI_READ_DATA:
|
|
DEBUGP(MP_TRACE, ("Received Read IOCTL\n"));
|
|
break;
|
|
case IOCTL_NETVMINI_WRITE_DATA:
|
|
DEBUGP(MP_TRACE, ("Received Write IOCTL\n"));
|
|
break;
|
|
default:
|
|
status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
DEBUGP(MP_TRACE, ("<== NIC Dispatch\n"));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NICDeregisterDevice(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deregister the ioctl interface. This is called whenever a miniport
|
|
instance is halted. When the last miniport instance is halted, we
|
|
request NDIS to delete the device object
|
|
|
|
Arguments:
|
|
|
|
NdisDeviceHandle - Handle returned by NdisMRegisterDevice
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if everything worked ok
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
DEBUGP(MP_TRACE, ("==>NICDeregisterDevice\n"));
|
|
|
|
NIC_ACQUIRE_MUTEX(&ControlDeviceMutex);
|
|
|
|
ASSERT(MiniportCount > 0);
|
|
|
|
--MiniportCount;
|
|
|
|
if (0 == MiniportCount)
|
|
{
|
|
//
|
|
// All miniport instances have been halted.
|
|
// Deregister the control device.
|
|
//
|
|
|
|
if (NdisDeviceHandle != NULL)
|
|
{
|
|
Status = NdisMDeregisterDevice(NdisDeviceHandle);
|
|
NdisDeviceHandle = NULL;
|
|
}
|
|
}
|
|
|
|
NIC_RELEASE_MUTEX(&ControlDeviceMutex);
|
|
|
|
DEBUGP(MP_TRACE, ("<== NICDeregisterDevice: %x\n", Status));
|
|
return Status;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|