/*++ 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; }