+++ /dev/null
-/*++\r
-\r
-Copyright (c) 1992-2000 Microsoft Corporation\r
- \r
-Module Name:\r
- \r
- passthru.c\r
-\r
-Abstract:\r
-\r
- Ndis Intermediate Miniport driver sample. This is a passthru driver.\r
-\r
-Author:\r
-\r
-Environment:\r
-\r
-\r
-Revision History:\r
-\r
-\r
---*/\r
-\r
-\r
-#include "precomp.h"\r
-#pragma hdrstop\r
-\r
-#pragma NDIS_INIT_FUNCTION(DriverEntry)\r
-\r
-NDIS_HANDLE ProtHandle = NULL;\r
-NDIS_HANDLE DriverHandle = NULL;\r
-NDIS_MEDIUM MediumArray[4] =\r
- {\r
- NdisMedium802_3, // Ethernet\r
- NdisMedium802_5, // Token-ring\r
- NdisMediumFddi, // Fddi\r
- NdisMediumWan // NDISWAN\r
- };\r
-\r
-NDIS_SPIN_LOCK GlobalLock;\r
-\r
-PADAPT pAdaptList = NULL;\r
-LONG MiniportCount = 0;\r
-\r
-NDIS_HANDLE NdisWrapperHandle;\r
-\r
-//\r
-// To support ioctls from user-mode:\r
-//\r
-\r
-#define LINKNAME_STRING L"\\DosDevices\\Passthru"\r
-#define NTDEVICE_STRING L"\\Device\\Passthru"\r
-\r
-NDIS_HANDLE NdisDeviceHandle = NULL;\r
-PDEVICE_OBJECT ControlDeviceObject = NULL;\r
-\r
-enum _DEVICE_STATE\r
-{\r
- PS_DEVICE_STATE_READY = 0, // ready for create/delete\r
- PS_DEVICE_STATE_CREATING, // create operation in progress\r
- PS_DEVICE_STATE_DELETING // delete operation in progress\r
-} ControlDeviceState = PS_DEVICE_STATE_READY;\r
-\r
-\r
-\r
-NTSTATUS\r
-DriverEntry(\r
- IN PDRIVER_OBJECT DriverObject,\r
- IN PUNICODE_STRING RegistryPath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- First entry point to be called, when this driver is loaded.\r
- Register with NDIS as an intermediate driver.\r
-\r
-Arguments:\r
-\r
- DriverObject - pointer to the system's driver object structure\r
- for this driver\r
- \r
- RegistryPath - system's registry path for this driver\r
- \r
-Return Value:\r
-\r
- STATUS_SUCCESS if all initialization is successful, STATUS_XXX\r
- error code if not.\r
-\r
---*/\r
-{\r
- NDIS_STATUS Status;\r
- NDIS_PROTOCOL_CHARACTERISTICS PChars;\r
- NDIS_MINIPORT_CHARACTERISTICS MChars;\r
- NDIS_STRING Name;\r
-\r
- Status = NDIS_STATUS_SUCCESS;\r
- NdisAllocateSpinLock(&GlobalLock);\r
-\r
- NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);\r
-\r
- do\r
- {\r
- //\r
- // Register the miniport with NDIS. Note that it is the miniport\r
- // which was started as a driver and not the protocol. Also the miniport\r
- // must be registered prior to the protocol since the protocol's BindAdapter\r
- // handler can be initiated anytime and when it is, it must be ready to\r
- // start driver instances.\r
- //\r
-\r
- NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));\r
-\r
- MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;\r
- MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;\r
-\r
- MChars.InitializeHandler = MPInitialize;\r
- MChars.QueryInformationHandler = MPQueryInformation;\r
- MChars.SetInformationHandler = MPSetInformation;\r
- MChars.ResetHandler = NULL;\r
- MChars.TransferDataHandler = MPTransferData;\r
- MChars.HaltHandler = MPHalt;\r
-#ifdef NDIS51_MINIPORT\r
- MChars.CancelSendPacketsHandler = MPCancelSendPackets;\r
- MChars.PnPEventNotifyHandler = MPDevicePnPEvent;\r
- MChars.AdapterShutdownHandler = MPAdapterShutdown;\r
-#endif // NDIS51_MINIPORT\r
-\r
- //\r
- // We will disable the check for hang timeout so we do not\r
- // need a check for hang handler!\r
- //\r
- MChars.CheckForHangHandler = NULL;\r
- MChars.ReturnPacketHandler = MPReturnPacket;\r
-\r
- //\r
- // Either the Send or the SendPackets handler should be specified.\r
- // If SendPackets handler is specified, SendHandler is ignored\r
- //\r
- MChars.SendHandler = NULL; // MPSend;\r
- MChars.SendPacketsHandler = MPSendPackets;\r
-\r
- Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,\r
- &MChars,\r
- sizeof(MChars),\r
- &DriverHandle);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
-\r
-#ifndef WIN9X\r
- NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);\r
-#endif\r
-\r
- //\r
- // Now register the protocol.\r
- //\r
- NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));\r
- PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;\r
- PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;\r
-\r
- //\r
- // Make sure the protocol-name matches the service-name\r
- // (from the INF) under which this protocol is installed.\r
- // This is needed to ensure that NDIS can correctly determine\r
- // the binding and call us to bind to miniports below.\r
- //\r
- NdisInitUnicodeString(&Name, L"Passthru"); // Protocol name\r
- PChars.Name = Name;\r
- PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;\r
- PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;\r
- PChars.SendCompleteHandler = PtSendComplete;\r
- PChars.TransferDataCompleteHandler = PtTransferDataComplete;\r
- \r
- PChars.ResetCompleteHandler = PtResetComplete;\r
- PChars.RequestCompleteHandler = PtRequestComplete;\r
- PChars.ReceiveHandler = PtReceive;\r
- PChars.ReceiveCompleteHandler = PtReceiveComplete;\r
- PChars.StatusHandler = PtStatus;\r
- PChars.StatusCompleteHandler = PtStatusComplete;\r
- PChars.BindAdapterHandler = PtBindAdapter;\r
- PChars.UnbindAdapterHandler = PtUnbindAdapter;\r
- PChars.UnloadHandler = PtUnloadProtocol;\r
-\r
- PChars.ReceivePacketHandler = PtReceivePacket;\r
- PChars.PnPEventHandler= PtPNPHandler;\r
-\r
- NdisRegisterProtocol(&Status,\r
- &ProtHandle,\r
- &PChars,\r
- sizeof(NDIS_PROTOCOL_CHARACTERISTICS));\r
-\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- NdisIMDeregisterLayeredMiniport(DriverHandle);\r
- break;\r
- }\r
-\r
- NdisIMAssociateMiniport(DriverHandle, ProtHandle);\r
- }\r
- while (FALSE);\r
-\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- NdisTerminateWrapper(NdisWrapperHandle, NULL);\r
- }\r
-\r
- return(Status);\r
-}\r
-\r
-\r
-NDIS_STATUS\r
-PtRegisterDevice(\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Register an ioctl interface - a device object to be used for this\r
- purpose is created by NDIS when we call NdisMRegisterDevice.\r
-\r
- This routine is called whenever a new miniport instance is\r
- initialized. However, we only create one global device object,\r
- when the first miniport instance is initialized. This routine\r
- handles potential race conditions with PtDeregisterDevice via\r
- the ControlDeviceState and MiniportCount variables.\r
-\r
- NOTE: do not call this from DriverEntry; it will prevent the driver\r
- from being unloaded (e.g. on uninstall).\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Return Value:\r
-\r
- NDIS_STATUS_SUCCESS if we successfully register a device object.\r
-\r
---*/\r
-{\r
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
- UNICODE_STRING DeviceName;\r
- UNICODE_STRING DeviceLinkUnicodeString;\r
- PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\r
-\r
- DBGPRINT(("==>PtRegisterDevice\n"));\r
-\r
- NdisAcquireSpinLock(&GlobalLock);\r
-\r
- ++MiniportCount;\r
- \r
- if (1 == MiniportCount)\r
- {\r
- ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING);\r
-\r
- //\r
- // Another thread could be running PtDeregisterDevice on\r
- // behalf of another miniport instance. If so, wait for\r
- // it to exit.\r
- //\r
- while (ControlDeviceState != PS_DEVICE_STATE_READY)\r
- {\r
- NdisReleaseSpinLock(&GlobalLock);\r
- NdisMSleep(1);\r
- NdisAcquireSpinLock(&GlobalLock);\r
- }\r
-\r
- ControlDeviceState = PS_DEVICE_STATE_CREATING;\r
-\r
- NdisReleaseSpinLock(&GlobalLock);\r
-\r
- \r
- NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));\r
-\r
- DispatchTable[IRP_MJ_CREATE] = PtDispatch;\r
- DispatchTable[IRP_MJ_CLEANUP] = PtDispatch;\r
- DispatchTable[IRP_MJ_CLOSE] = PtDispatch;\r
- DispatchTable[IRP_MJ_DEVICE_CONTROL] = PtDispatch;\r
- \r
-\r
- NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);\r
- NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);\r
-\r
- //\r
- // Create a device object and register our dispatch handlers\r
- //\r
- \r
- Status = NdisMRegisterDevice(\r
- NdisWrapperHandle, \r
- &DeviceName,\r
- &DeviceLinkUnicodeString,\r
- &DispatchTable[0],\r
- &ControlDeviceObject,\r
- &NdisDeviceHandle\r
- );\r
-\r
- NdisAcquireSpinLock(&GlobalLock);\r
-\r
- ControlDeviceState = PS_DEVICE_STATE_READY;\r
- }\r
-\r
- NdisReleaseSpinLock(&GlobalLock);\r
-\r
- DBGPRINT(("<==PtRegisterDevice: %x\n", Status));\r
-\r
- return (Status);\r
-}\r
-\r
-\r
-NTSTATUS\r
-PtDispatch(\r
- IN PDEVICE_OBJECT DeviceObject,\r
- IN PIRP Irp\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- Process IRPs sent to this device.\r
-\r
-Arguments:\r
-\r
- DeviceObject - pointer to a device object\r
- Irp - pointer to an I/O Request Packet\r
-\r
-Return Value:\r
-\r
- NTSTATUS - STATUS_SUCCESS always - change this when adding\r
- real code to handle ioctls.\r
-\r
---*/\r
-{\r
- PIO_STACK_LOCATION irpStack;\r
- NTSTATUS status = STATUS_SUCCESS;\r
-\r
- UNREFERENCED_PARAMETER(DeviceObject);\r
- \r
- DBGPRINT(("==>Pt Dispatch\n"));\r
- irpStack = IoGetCurrentIrpStackLocation(Irp);\r
- \r
-\r
- switch (irpStack->MajorFunction)\r
- {\r
- case IRP_MJ_CREATE:\r
- break;\r
- \r
- case IRP_MJ_CLEANUP:\r
- break;\r
- \r
- case IRP_MJ_CLOSE:\r
- break; \r
- \r
- case IRP_MJ_DEVICE_CONTROL:\r
- //\r
- // Add code here to handle ioctl commands sent to passthru.\r
- //\r
- break; \r
- default:\r
- break;\r
- }\r
-\r
- Irp->IoStatus.Status = status;\r
- IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
-\r
- DBGPRINT(("<== Pt Dispatch\n"));\r
-\r
- return status;\r
-\r
-} \r
-\r
-\r
-NDIS_STATUS\r
-PtDeregisterDevice(\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Deregister the ioctl interface. This is called whenever a miniport\r
- instance is halted. When the last miniport instance is halted, we\r
- request NDIS to delete the device object\r
-\r
-Arguments:\r
-\r
- NdisDeviceHandle - Handle returned by NdisMRegisterDevice\r
-\r
-Return Value:\r
-\r
- NDIS_STATUS_SUCCESS if everything worked ok\r
-\r
---*/\r
-{\r
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
-\r
- DBGPRINT(("==>PassthruDeregisterDevice\n"));\r
-\r
- NdisAcquireSpinLock(&GlobalLock);\r
-\r
- ASSERT(MiniportCount > 0);\r
-\r
- --MiniportCount;\r
- \r
- if (0 == MiniportCount)\r
- {\r
- //\r
- // All miniport instances have been halted. Deregister\r
- // the control device.\r
- //\r
-\r
- ASSERT(ControlDeviceState == PS_DEVICE_STATE_READY);\r
-\r
- //\r
- // Block PtRegisterDevice() while we release the control\r
- // device lock and deregister the device.\r
- // \r
- ControlDeviceState = PS_DEVICE_STATE_DELETING;\r
-\r
- NdisReleaseSpinLock(&GlobalLock);\r
-\r
- if (NdisDeviceHandle != NULL)\r
- {\r
- Status = NdisMDeregisterDevice(NdisDeviceHandle);\r
- NdisDeviceHandle = NULL;\r
- }\r
-\r
- NdisAcquireSpinLock(&GlobalLock);\r
- ControlDeviceState = PS_DEVICE_STATE_READY;\r
- }\r
-\r
- NdisReleaseSpinLock(&GlobalLock);\r
-\r
- DBGPRINT(("<== PassthruDeregisterDevice: %x\n", Status));\r
- return Status;\r
- \r
-}\r
-\r
-VOID\r
-PtUnload(\r
- IN PDRIVER_OBJECT DriverObject\r
- )\r
-//\r
-// PassThru driver unload function\r
-//\r
-{\r
- UNREFERENCED_PARAMETER(DriverObject);\r
- \r
- DBGPRINT(("PtUnload: entered\n"));\r
- \r
- PtUnloadProtocol();\r
- \r
- NdisIMDeregisterLayeredMiniport(DriverHandle);\r
- \r
- NdisFreeSpinLock(&GlobalLock);\r
-\r
- DBGPRINT(("PtUnload: done!\n"));\r
-}\r
-\r