446 lines
10 KiB
C
446 lines
10 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 FORE Systems, Inc.
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ntentry.c
|
|
|
|
Abstract:
|
|
|
|
NT entry points for ATMLANE driver.
|
|
|
|
Author:
|
|
|
|
Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Due to problems with including zwapi.h:
|
|
//
|
|
NTSYSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
ZwLoadDriver(
|
|
IN PUNICODE_STRING DriverServiceName
|
|
);
|
|
|
|
|
|
EXTERN
|
|
NTSTATUS
|
|
AtmLaneIoctlRequest(
|
|
IN PIRP pIrp
|
|
);
|
|
|
|
NTSTATUS
|
|
AtmLaneDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP pIrp
|
|
);
|
|
|
|
VOID
|
|
AtmLaneUnload(
|
|
IN PDRIVER_OBJECT pDriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT pDriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Entry point for the driver.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the system allocated DRIVER_OBJECT.
|
|
RegistryPath - Pointer to the UNICODE string defining the registry
|
|
path for the driver's information.
|
|
|
|
Return Value:
|
|
|
|
Appropriate NDIS_STATUS value.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
UNICODE_STRING DeviceName;
|
|
UNICODE_STRING DeviceLinkUnicodeString;
|
|
NDIS_STATUS NdisStatus;
|
|
NDIS_HANDLE NdisWrapperHandle = NULL;
|
|
NDIS_HANDLE MiniportDriverHandle;
|
|
NDIS_HANDLE NdisProtocolHandle;
|
|
NDIS50_PROTOCOL_CHARACTERISTICS AtmLaneProtChars;
|
|
NDIS_MINIPORT_CHARACTERISTICS AtmLaneMiniChars;
|
|
PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION];
|
|
ULONG i;
|
|
UNICODE_STRING AtmUniKeyName =
|
|
NDIS_STRING_CONST("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Atmuni");
|
|
|
|
#if DBG
|
|
volatile ULONG DontRun = 0;
|
|
#endif
|
|
|
|
TRACEIN(DriverEntry);
|
|
|
|
#if DBG
|
|
DbgPrint("ATMLANE built %s %s\n", __DATE__, __TIME__);
|
|
DbgPrint("ATMLANE: DbgVerbosity is at %p, currently set to %d\n",
|
|
&DbgVerbosity, DbgVerbosity);
|
|
|
|
if (DontRun > 0)
|
|
{
|
|
TRACEOUT(DriverEntry);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Initialize our globals.
|
|
//
|
|
AtmLaneInitGlobals();
|
|
|
|
//
|
|
// Save the pointer to the Driver Object
|
|
//
|
|
|
|
pAtmLaneGlobalInfo->pDriverObject = pDriverObject;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Initialize the wrapper.
|
|
//
|
|
NdisInitializeWrapper(
|
|
&NdisWrapperHandle,
|
|
pDriverObject,
|
|
RegistryPath,
|
|
NULL);
|
|
if (NULL == NdisWrapperHandle)
|
|
{
|
|
DBGP((0, "DriverEntry: NdisMInitializeWrapper failed!\n"));
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
DBGP((3, "DriverEntry: NdisWrapperhandle %x\n", NdisWrapperHandle));
|
|
//
|
|
// Save the handle to the wrapper.
|
|
//
|
|
pAtmLaneGlobalInfo->NdisWrapperHandle = NdisWrapperHandle;
|
|
}
|
|
|
|
//
|
|
// Attempt to load the standard UNI 3.1 Call Manager
|
|
//
|
|
NtStatus = ZwLoadDriver(&AtmUniKeyName);
|
|
DBGP((1, "ATMLANE: attempt to load ATMUNI returned %x\n", NtStatus));
|
|
|
|
//
|
|
// We don't care whether we successfully loaded the call manager or not.
|
|
//
|
|
NtStatus = STATUS_SUCCESS;
|
|
|
|
//
|
|
// Initialize the miniport characteristics.
|
|
//
|
|
NdisZeroMemory(&AtmLaneMiniChars, sizeof(AtmLaneMiniChars));
|
|
AtmLaneMiniChars.MajorNdisVersion = 4;
|
|
AtmLaneMiniChars.MinorNdisVersion = 0;
|
|
// CheckForHangHandler
|
|
// DisableInterruptHandler
|
|
// EnableInterruptHandler
|
|
AtmLaneMiniChars.HaltHandler = AtmLaneMHalt;
|
|
// HandleInterruptHandler
|
|
AtmLaneMiniChars.InitializeHandler = AtmLaneMInitialize;
|
|
// ISRHandler
|
|
AtmLaneMiniChars.QueryInformationHandler = AtmLaneMQueryInformation;
|
|
// ReconfigureHandler
|
|
AtmLaneMiniChars.ResetHandler = AtmLaneMReset;
|
|
// SendHandler
|
|
AtmLaneMiniChars.SetInformationHandler = AtmLaneMSetInformation;
|
|
// TransferDataHandler
|
|
AtmLaneMiniChars.ReturnPacketHandler = AtmLaneMReturnPacket;
|
|
AtmLaneMiniChars.SendPacketsHandler = AtmLaneMSendPackets;
|
|
// AllocateCompleteHandler
|
|
|
|
//
|
|
// Register the Layered Miniport with NDIS.
|
|
//
|
|
NdisStatus = NdisIMRegisterLayeredMiniport(
|
|
NdisWrapperHandle,
|
|
&AtmLaneMiniChars,
|
|
sizeof(AtmLaneMiniChars),
|
|
&MiniportDriverHandle);
|
|
if (NDIS_STATUS_SUCCESS == NdisStatus)
|
|
{
|
|
DBGP((3, "DriverEntry: NdisIMRegisterLayeredMiniport succeeded.\n"));
|
|
//
|
|
// Save the handle to the driver.
|
|
//
|
|
pAtmLaneGlobalInfo->MiniportDriverHandle = MiniportDriverHandle;
|
|
}
|
|
else
|
|
{
|
|
DBGP((0, "DriverEntry: NdisIMRegisterLayeredMiniport failed! Status: %x\n",
|
|
NdisStatus));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize the protocol characteristics.
|
|
//
|
|
NdisZeroMemory(&AtmLaneProtChars, sizeof(AtmLaneProtChars));
|
|
AtmLaneProtChars.MajorNdisVersion = 5;
|
|
AtmLaneProtChars.MinorNdisVersion = 0;
|
|
AtmLaneProtChars.OpenAdapterCompleteHandler = AtmLaneOpenAdapterCompleteHandler;
|
|
AtmLaneProtChars.CloseAdapterCompleteHandler = AtmLaneCloseAdapterCompleteHandler;
|
|
AtmLaneProtChars.SendCompleteHandler = AtmLaneSendCompleteHandler;
|
|
AtmLaneProtChars.TransferDataCompleteHandler = AtmLaneTransferDataCompleteHandler;
|
|
AtmLaneProtChars.ResetCompleteHandler = AtmLaneResetCompleteHandler;
|
|
AtmLaneProtChars.RequestCompleteHandler = AtmLaneRequestCompleteHandler;
|
|
AtmLaneProtChars.ReceiveHandler = AtmLaneReceiveHandler;
|
|
AtmLaneProtChars.ReceiveCompleteHandler = AtmLaneReceiveCompleteHandler;
|
|
AtmLaneProtChars.StatusHandler = AtmLaneStatusHandler;
|
|
AtmLaneProtChars.StatusCompleteHandler = AtmLaneStatusCompleteHandler;
|
|
NdisInitUnicodeString(&AtmLaneProtChars.Name, ATMLANE_PROTOCOL_STRING);
|
|
|
|
// ReceivePacketHandler;
|
|
AtmLaneProtChars.BindAdapterHandler = AtmLaneBindAdapterHandler;
|
|
AtmLaneProtChars.UnbindAdapterHandler = AtmLaneUnbindAdapterHandler;
|
|
AtmLaneProtChars.PnPEventHandler = AtmLanePnPEventHandler;
|
|
AtmLaneProtChars.UnloadHandler = AtmLaneUnloadProtocol;
|
|
|
|
AtmLaneProtChars.CoSendCompleteHandler = AtmLaneCoSendCompleteHandler;
|
|
AtmLaneProtChars.CoStatusHandler = AtmLaneCoStatusHandler;
|
|
AtmLaneProtChars.CoReceivePacketHandler = AtmLaneCoReceivePacketHandler;
|
|
AtmLaneProtChars.CoAfRegisterNotifyHandler = AtmLaneAfRegisterNotifyHandler;
|
|
|
|
//
|
|
// Register the Protocol with NDIS.
|
|
//
|
|
NdisRegisterProtocol(
|
|
&NdisStatus,
|
|
&NdisProtocolHandle,
|
|
&AtmLaneProtChars,
|
|
sizeof(AtmLaneProtChars));
|
|
if (NDIS_STATUS_SUCCESS == NdisStatus)
|
|
{
|
|
DBGP((3, "DriverEntry: NdisProtocolhandle %x\n",
|
|
NdisProtocolHandle));
|
|
//
|
|
// Save the NDIS Protocol handle.
|
|
//
|
|
pAtmLaneGlobalInfo->NdisProtocolHandle = NdisProtocolHandle;
|
|
}
|
|
else
|
|
{
|
|
DBGP((0, "DriverEntry: NdisRegisterProtocol failed! Status: %x\n",
|
|
NdisStatus));
|
|
break;
|
|
}
|
|
|
|
#ifndef LANE_WIN98
|
|
//
|
|
// Associate the miniport and protocol now
|
|
//
|
|
NdisIMAssociateMiniport(MiniportDriverHandle,
|
|
NdisProtocolHandle);
|
|
|
|
#endif // LANE_WIN98
|
|
|
|
//
|
|
// Register our protocol device name for special ioctls
|
|
//
|
|
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
|
|
{
|
|
DispatchTable[i] = AtmLaneDeviceControl;
|
|
}
|
|
|
|
NdisInitUnicodeString(&DeviceName, ATMLANE_NTDEVICE_STRING);
|
|
NdisInitUnicodeString(&DeviceLinkUnicodeString, ATMLANE_LINKNAME_STRING);
|
|
|
|
NdisStatus = NdisMRegisterDevice(
|
|
NdisWrapperHandle,
|
|
&DeviceName,
|
|
&DeviceLinkUnicodeString,
|
|
&DispatchTable[0],
|
|
&pAtmLaneGlobalInfo->pSpecialDeviceObject,
|
|
&pAtmLaneGlobalInfo->SpecialNdisDeviceHandle
|
|
);
|
|
|
|
if (NDIS_STATUS_SUCCESS != NdisStatus)
|
|
{
|
|
DBGP((0, "DriverEntry: NdisMRegisterDevice failed! Status: %x\n",
|
|
NdisStatus));
|
|
break;
|
|
}
|
|
|
|
DBGP((3, "DriverEntry: NdisMRegisterDevice: pDevObj %x DevHandle %x\n",
|
|
pAtmLaneGlobalInfo->pSpecialDeviceObject,
|
|
pAtmLaneGlobalInfo->SpecialNdisDeviceHandle));
|
|
|
|
NdisMRegisterUnloadHandler(NdisWrapperHandle,
|
|
AtmLaneUnload);
|
|
|
|
} while(FALSE);
|
|
|
|
|
|
if (NDIS_STATUS_SUCCESS != NdisStatus)
|
|
{
|
|
//
|
|
// Clean up.
|
|
//
|
|
if (NULL != NdisWrapperHandle)
|
|
{
|
|
NdisTerminateWrapper(
|
|
NdisWrapperHandle,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
TRACEOUT(DriverEntry);
|
|
|
|
return(NtStatus);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AtmLaneDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP pIrp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the function that hooks NDIS's Device Control IRP
|
|
handler to implement some protocol specific Ioctls.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to device object for target device
|
|
pIrp - Pointer to I/O request packet
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS -- Indicates whether the request was successfully queued.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
NTSTATUS Status;
|
|
|
|
TRACEIN(DeviceControl);
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
|
|
DBGP((3, "DeviceControl %x %s\n", pIrpSp->MajorFunction,
|
|
IrpToString(pIrpSp->MajorFunction)));
|
|
|
|
//
|
|
// We only hanle the IRP_MJ_DEVICE_CONTROL IRPs.
|
|
//
|
|
if (pIrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
|
|
{
|
|
DBGP((3, "DeviceControl: Handling request\n"));
|
|
Status = AtmLaneIoctlRequest(pIrp);
|
|
}
|
|
else
|
|
{
|
|
switch (pIrpSp->MajorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
case IRP_MJ_CLOSE:
|
|
case IRP_MJ_CLEANUP:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
case IRP_MJ_SHUTDOWN:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
default:
|
|
DBGP((3, "DeviceControl: MajorFunction not supported\n"));
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
ASSERT(STATUS_PENDING != Status);
|
|
|
|
pIrp->IoStatus.Status = Status;
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
TRACEOUT(DeviceControl);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmLaneUnload(
|
|
IN PDRIVER_OBJECT pDriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the system prior to unloading us.
|
|
Currently, we just undo everything we did in DriverEntry,
|
|
that is, de-register ourselves as an NDIS protocol, and delete
|
|
the device object we had created.
|
|
|
|
Arguments:
|
|
|
|
pDriverObject - Pointer to the driver object created by the system.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
UNICODE_STRING DeviceLinkUnicodeString;
|
|
NDIS_STATUS Status;
|
|
|
|
TRACEIN(Unload);
|
|
DBGP((0, "AtmLaneUnload\n"));
|
|
|
|
// Shut down the protocol first. This is synchronous (i.e. blocks)
|
|
|
|
AtmLaneUnloadProtocol();
|
|
|
|
// Delete the symbolic link created for the admin util
|
|
|
|
if (pAtmLaneGlobalInfo->SpecialNdisDeviceHandle)
|
|
{
|
|
DBGP((0, "Deregistering device handle %x from AtmLaneUnload\n",
|
|
pAtmLaneGlobalInfo->SpecialNdisDeviceHandle));
|
|
Status = NdisMDeregisterDevice(pAtmLaneGlobalInfo->SpecialNdisDeviceHandle);
|
|
pAtmLaneGlobalInfo->SpecialNdisDeviceHandle = NULL;
|
|
ASSERT(NDIS_STATUS_SUCCESS == Status);
|
|
}
|
|
|
|
TRACEOUT(Unload);
|
|
|
|
return;
|
|
}
|
|
|