/*++ Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved. Module Name: atmsmdrv.c Abstract: A sample ATM Client driver. This sample demonstrates establishment and tear down of P-P or PMP connections over ATM. This module contains the driver entry routine. Author: Anil Francis Thomas (10/98) Environment: Kernel Revision History: --*/ #include "precomp.h" #pragma hdrstop #define MODULE_ID MODULE_INIT #pragma NDIS_INIT_FUNCTION(DriverEntry) VOID AtmSmUnload( IN PDRIVER_OBJECT pDriverObject ); VOID AtmSmInitializeGlobal( IN PDRIVER_OBJECT pDriverObject ); VOID AtmSmCleanupGlobal(); NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) /*++ Routine Description: This is the "init" routine, called by the system when the AtmSmDrv module is loaded. We initialize all our global objects, fill in our Dispatch and Unload routine addresses in the driver object, and create a device object for receiving I/O requests. Arguments: pDriverObject - Pointer to the driver object created by the system. pRegistryPath - Pointer to our global registry path. This is ignored. Return Value: NT Status code: STATUS_SUCCESS if successful, error code otherwise. --*/ { NDIS_STATUS Status; NDIS_PROTOCOL_CHARACTERISTICS PChars; PNDIS_CONFIGURATION_PARAMETER Param; PDEVICE_OBJECT pDeviceObject; UNICODE_STRING DeviceName; UNICODE_STRING SymbolicName; HANDLE ThreadHandle; int i; TraceIn(DriverEntry); #if DBG DbgPrint("AtmSmDebugFlag: Address = %p Value = 0x%x\n", &AtmSmDebugFlag, AtmSmDebugFlag); #endif DbgLoud(("Sizeof TCHAR = %hu\n",sizeof(TCHAR))); AtmSmInitializeGlobal(pDriverObject); // // Initialize the debug memory allocator // ATMSM_INITIALIZE_AUDIT_MEM(); // // Initialize the Driver Object. // pDriverObject->DriverUnload = AtmSmUnload; pDriverObject->FastIoDispatch = NULL; for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { pDriverObject->MajorFunction[i] = AtmSmDispatch; } do { // break off loop // // Create a device object for atm sample module. The device object // is used by the user mode app for I/O // RtlInitUnicodeString(&DeviceName, ATM_SAMPLE_CLIENT_DEVICE_NAME); Status = IoCreateDevice( pDriverObject, 0, &DeviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject ); if(NDIS_STATUS_SUCCESS != Status) { DbgErr(("Failed to create device object - Error - 0x%X\n", Status)); break; } // we are doing direct IO for sends and recvs pDeviceObject->Flags |= DO_DIRECT_IO; // Save the device object AtmSmGlobal.pDeviceObject = pDeviceObject; AtmSmGlobal.ulInitSeqFlag |= CREATED_IO_DEVICE; // // Set up a symbolic name for interaction with the user-mode // application. // RtlInitUnicodeString(&SymbolicName, ATM_SAMPLE_CLIENT_SYMBOLIC_NAME); IoCreateSymbolicLink(&SymbolicName, &DeviceName); AtmSmGlobal.ulInitSeqFlag |= REGISTERED_SYM_NAME; // // We are doing direct I/O. // pDeviceObject->Flags |= DO_DIRECT_IO; // // Now register the protocol. // Status = AtmSmInitializeNdis(); if(NDIS_STATUS_SUCCESS != Status) { DbgErr(("Failed to Register protocol - Error - 0x%X\n", Status)); break; } AtmSmGlobal.ulInitSeqFlag |= REGISTERED_WITH_NDIS; }while(FALSE); if(NDIS_STATUS_SUCCESS != Status) { // // Clean up will happen in Unload routine // } TraceOut(DriverEntry); return(Status); } VOID AtmSmUnload( 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 SymbolicName; NDIS_STATUS Status; TraceIn(Unload); // call the shutdown handler AtmSmShutDown(); // Remove the Symbolic Name created by us if(0 != (AtmSmGlobal.ulInitSeqFlag & REGISTERED_SYM_NAME)) { RtlInitUnicodeString(&SymbolicName, ATM_SAMPLE_CLIENT_SYMBOLIC_NAME); IoDeleteSymbolicLink(&SymbolicName); } // Remove the Device created by us if(0 != (AtmSmGlobal.ulInitSeqFlag & CREATED_IO_DEVICE)) { IoDeleteDevice(AtmSmGlobal.pDeviceObject); } ATMSM_SHUTDOWN_AUDIT_MEM(); AtmSmCleanupGlobal(); TraceOut(Unload); return; } VOID AtmSmShutDown() /*++ Routine Description: Called when the system is being shutdown. Here we unbind all the adapters that we bound to previously. Arguments: None Return Value: None --*/ { PATMSM_ADAPTER pAdapt, pNextAdapt; NDIS_STATUS Status; #if DBG KIRQL EntryIrql, ExitIrql; #endif TraceIn(AtmSmShutDown); ATMSM_GET_ENTRY_IRQL(EntryIrql); // // grab the global lock and Unbind each of the adapters. // ACQUIRE_GLOBAL_LOCK(); for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt; pAdapt = pNextAdapt) { pNextAdapt = pAdapt->pAdapterNext; RELEASE_GLOBAL_LOCK(); AtmSmUnbindAdapter(&Status, (NDIS_HANDLE)pAdapt, (NDIS_HANDLE)NULL); ACQUIRE_GLOBAL_LOCK(); } RELEASE_GLOBAL_LOCK(); // Deregister from NDIS if(0 != (AtmSmGlobal.ulInitSeqFlag & REGISTERED_WITH_NDIS)) AtmSmDeinitializeNdis(); ATMSM_CHECK_EXIT_IRQL(EntryIrql, ExitIrql); TraceOut(AtmSmShutDown); } VOID AtmSmInitializeGlobal( IN PDRIVER_OBJECT pDriverObject ) { NdisZeroMemory(&AtmSmGlobal, sizeof(ATMSM_GLOBAL)); AtmSmGlobal.ulSignature = atmsm_global_signature; AtmSmGlobal.pDriverObject = pDriverObject; NdisAllocateSpinLock(&AtmSmGlobal.Lock); } VOID AtmSmCleanupGlobal() { NdisFreeSpinLock(&AtmSmGlobal.Lock); } NDIS_STATUS AtmSmInitializeNdis() /*++ Routine Description: Arguments: Return Value: --*/ { NDIS_STATUS Status; NDIS_PROTOCOL_CHARACTERISTICS Chars; // // Register with NDIS as a protocol. // RtlZeroMemory(&Chars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); Chars.MajorNdisVersion = 5; Chars.MinorNdisVersion = 0; Chars.OpenAdapterCompleteHandler = AtmSmOpenAdapterComplete; Chars.CloseAdapterCompleteHandler = AtmSmCloseAdapterComplete; Chars.StatusHandler = AtmSmStatus; Chars.RequestCompleteHandler = AtmSmRequestComplete; Chars.ReceiveCompleteHandler = AtmSmReceiveComplete; Chars.StatusCompleteHandler = AtmSmStatusComplete; Chars.BindAdapterHandler = AtmSmBindAdapter; Chars.UnbindAdapterHandler = AtmSmUnbindAdapter; Chars.PnPEventHandler = AtmSmPnPEvent; Chars.CoSendCompleteHandler = AtmSmCoSendComplete; Chars.CoStatusHandler = AtmSmCoStatus; Chars.CoReceivePacketHandler = AtmSmCoReceivePacket; Chars.CoAfRegisterNotifyHandler = AtmSmCoAfRegisterNotify; RtlInitUnicodeString(&Chars.Name, ATMSM_SERVICE_NAME_L); NdisRegisterProtocol(&Status, &AtmSmGlobal.ProtHandle, &Chars, sizeof(Chars)); return Status; } NDIS_STATUS AtmSmDeinitializeNdis() { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; TraceIn(AtmSmDeinitializeNdis); if(NULL != AtmSmGlobal.ProtHandle) { NdisDeregisterProtocol(&Status, AtmSmGlobal.ProtHandle); AtmSmGlobal.ProtHandle = NULL; } TraceOut(AtmSmDeinitializeNdis); return Status; }