|
|
/***************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
WDMUTIL.C
Abstract:
Stuff that does not fit well with NDIS header files Environment:
kernel mode only
Notes:
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.
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
Revision History:
5/17/99 : created
Author:
Tom Green
****************************************************************************/
#include "precomp.h"
/****************************************************************************/ /* DeviceObjectToDriverObject */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Get driver object associated with device object. NDIS has no notion */ /* of the shape of a device object, so we put this here for ease of */ /* building *
/* */ /* Arguments: */ /* */ /* DeviceObject - device object we to get associated driver object for */ /* */ /* Return: */ /* */ /* PDRIVER_OBJECT */ /* */ /****************************************************************************/ PDRIVER_OBJECT DeviceObjectToDriverObject(IN PDEVICE_OBJECT DeviceObject) { return DeviceObject->DriverObject; } // DeviceObjectToDriverObject
/****************************************************************************/ /* GetDeviceFriendlyName */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Return the friendly name associated with the given device object. */ /* */ /* Arguments: */ /* */ /* pDeviceObject - device object we to get associated driver object for */ /* ppName - Place to return a pointer to an ANSI string containing name */ /* pNameLength - Place to return length of above string */ /* */ /* Return: */ /* */ /* NTSTATUS */ /* */ /****************************************************************************/ NTSTATUS GetDeviceFriendlyName(IN PDEVICE_OBJECT pDeviceObject, OUT PANSI_STRING pAnsiName, OUT PUNICODE_STRING pUnicodeName) { NTSTATUS NtStatus; NDIS_STATUS Status; ULONG ResultLength; DEVICE_REGISTRY_PROPERTY Property; UNICODE_STRING UnicodeString; ANSI_STRING AnsiString; USHORT AnsiMaxLength; PWCHAR pValueInfo; ULONG i;
pValueInfo = NULL; AnsiString.Buffer = NULL;
do { Property = DevicePropertyFriendlyName;
for (i = 0; i < 2; i++) { NtStatus = IoGetDeviceProperty(pDeviceObject, Property, 0, NULL, &ResultLength);
if (NtStatus != STATUS_BUFFER_TOO_SMALL) { ASSERT(!NT_SUCCESS(NtStatus)); Property = DevicePropertyDeviceDescription; } }
Status = MemAlloc(&pValueInfo, ResultLength); if (Status != NDIS_STATUS_SUCCESS) { NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; }
NtStatus = IoGetDeviceProperty(pDeviceObject, Property, ResultLength, pValueInfo, &ResultLength);
if (NtStatus != STATUS_SUCCESS) { TRACE1(("IoGetDeviceProperty returned %x\n", NtStatus)); break; }
RtlInitUnicodeString(&UnicodeString, pValueInfo);
//
// Allocate space for ANSI version.
//
AnsiMaxLength = UnicodeString.MaximumLength / sizeof(WCHAR); Status = MemAlloc(&AnsiString.Buffer, AnsiMaxLength);
if (Status != NDIS_STATUS_SUCCESS) { NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; }
RtlFillMemory(AnsiString.Buffer, AnsiMaxLength, 0); AnsiString.MaximumLength = AnsiMaxLength; AnsiString.Length = 0;
NtStatus = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
if (!NT_SUCCESS(NtStatus)) { ASSERT(FALSE); break; }
*pAnsiName = AnsiString; *pUnicodeName = UnicodeString; break; } while (FALSE);
if (!NT_SUCCESS(NtStatus)) { if (pValueInfo) { MemFree(pValueInfo, -1); }
if (AnsiString.Buffer) { MemFree(AnsiString.Buffer, AnsiString.MaximumLength); } }
return (NtStatus); }
/****************************************************************************/ /* HookPnpDispatchRoutine */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Set up the driver object for the specified microport driver to */ /* intercept the IRP_MJ_PNP dispatch routine before it gets to NDIS. */ /* This is in order to support surprise removal on platforms where we */ /* don't have NDIS 5.1 support. If we are running on >= NDIS 5.1, don't */ /* do anything. */ /* */ /* Arguments: */ /* */ /* DriverBlock - pointer to driver block structure for this microport. */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID HookPnpDispatchRoutine(IN PDRIVER_BLOCK DriverBlock) { if ((DriverBlock->MajorNdisVersion < 5) || ((DriverBlock->MajorNdisVersion == 5) && (DriverBlock->MinorNdisVersion < 1))) { DriverBlock->SavedPnPDispatch = DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP]; DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = PnPDispatch; } }
/****************************************************************************/ /* PnPDispatch */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Dispatch routine for IRP_MJ_PNP that is called by the I/O system. */ /* We process surprise removal and query capabilities. */ /* In all cases, we pass on the IRP to NDIS for further processing. */ /* */ /* Arguments: */ /* */ /* pDeviceObject - pointer to Device Object */ /* pIrp - pointer to IRP */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ NTSTATUS PnPDispatch(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) { PIO_STACK_LOCATION pIrpSp; NTSTATUS Status; PDRIVER_BLOCK DriverBlock; PRNDISMP_ADAPTER pAdapter;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
DeviceObjectToAdapterAndDriverBlock(pDeviceObject, &pAdapter, &DriverBlock);
TRACE3(("PnPDispatch: Adapter %x, MinorFunction %x\n", pAdapter, pIrpSp->MinorFunction));
switch (pIrpSp->MinorFunction) { case IRP_MN_QUERY_CAPABILITIES: pIrpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = 1; break; case IRP_MN_SURPRISE_REMOVAL: TRACE1(("PnPDispatch: PDO %p, Adapter %p, surprise removal!\n", pDeviceObject, pAdapter)); if (pAdapter) { RndismpInternalHalt((NDIS_HANDLE)pAdapter, FALSE); } break;
default: break; }
Status = (DriverBlock->SavedPnPDispatch)( pDeviceObject, pIrp);
return (Status); }
#ifdef BUILD_WIN9X
/****************************************************************************/ /* HookNtKernCMHandler */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Swap the CM handler routine within NDIS' data structures such that */ /* we get called when NDIS forwards a CM message. This can only work on */ /* Win98 and Win98SE. */ /* */ /* Arguments: */ /* */ /* Adapter - pointer to our adapter block */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID HookNtKernCMHandler(IN PRNDISMP_ADAPTER pAdapter) { PVOID pNdisWrapperAdapterBlock; PVOID pDetect; ULONG WrapContextOffset;
pDetect = (PVOID)((ULONG_PTR)pAdapter->MiniportAdapterHandle + 0x29c);
if (*(PVOID *)pDetect == (PVOID)pAdapter->pPhysDeviceObject) { // Win98Gold
WrapContextOffset = 0xf8; pAdapter->bRunningOnWin98Gold = TRUE; } else { // Win98SE
WrapContextOffset = 0x60; pAdapter->bRunningOnWin98Gold = FALSE; } pAdapter->WrapContextOffset = WrapContextOffset;
pNdisWrapperAdapterBlock = *(PVOID *)((ULONG_PTR)pAdapter->MiniportAdapterHandle + WrapContextOffset);
// Save away the old handler:
pAdapter->NdisCmConfigHandler = (MY_CMCONFIGHANDLER) (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78));
// Insert our routine:
(*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78)) = (PVOID)RndisCMHandler;
// Save the devnode to use on lookups based on devnode:
pAdapter->DevNode = (MY_DEVNODE) (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x38));
TRACE1(("HookNtKernCMHandler: Adapter %p, NdisHandler %p, DevNode %x\n", pAdapter, pAdapter->NdisCmConfigHandler, pAdapter->DevNode)); }
/****************************************************************************/ /* UnHookNtKernCMHandler */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Put back the swapped Config Mgr handler in NDIS' data structures */ /* */ /* Arguments: */ /* */ /* Adapter - pointer to our adapter block */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID UnHookNtKernCMHandler(IN PRNDISMP_ADAPTER pAdapter) { PVOID pNdisWrapperAdapterBlock;
if (pAdapter->NdisCmConfigHandler) { pNdisWrapperAdapterBlock = *(PVOID *)((ULONG_PTR)pAdapter->MiniportAdapterHandle + pAdapter->WrapContextOffset); (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78)) = (PVOID)pAdapter->NdisCmConfigHandler; }
TRACE1(("UnhookNtKernCMHandler: Adapter %p, NdisHandler %p, DevNode %x\n", pAdapter, pAdapter->NdisCmConfigHandler, pAdapter->DevNode)); }
/****************************************************************************/ /* RndisCMHandler */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Handler to intercept Config Mgr messages forwarded by NDIS. The only */ /* message of interest is a CONFIG_PREREMOVE, which is our only indication */ /* on Win98 and Win98SE that the device is being removed. */ /* */ /* Arguments: */ /* */ /* Various - documented in Win9x CFmgr header. */ /* */ /* Return: */ /* */ /* MY_CONFIGRET */ /* */ /****************************************************************************/ MY_CONFIGRET __cdecl RndisCMHandler(IN MY_CONFIGFUNC cfFuncName, IN MY_SUBCONFIGFUNC cfSubFuncName, IN MY_DEVNODE cfDevNode, IN ULONG dwRefData, IN ULONG ulFlags) { PRNDISMP_ADAPTER pAdapter, pTmpAdapter; PDRIVER_BLOCK pDriverBlock; MY_CONFIGRET crRetCode;
do { //
// Find the adapter to which this is addressed.
//
pAdapter = NULL; NdisAcquireSpinLock(&RndismpGlobalLock);
for (pDriverBlock = RndismpMiniportBlockListHead.NextDriverBlock; (pDriverBlock != NULL) && (pAdapter == NULL); pDriverBlock = pDriverBlock->NextDriverBlock) { for (pTmpAdapter = pDriverBlock->AdapterList; pTmpAdapter != NULL; pTmpAdapter = pTmpAdapter->NextAdapter) { if (pTmpAdapter->DevNode == cfDevNode) { pAdapter = pTmpAdapter; break; } } }
NdisReleaseSpinLock(&RndismpGlobalLock);
ASSERT(pAdapter != NULL);
TRACE1(("CMHandler: Adapter %p, CfFuncName %x\n", pAdapter, cfFuncName));
//
// Forward this on before acting on it.
//
if (pAdapter && (pAdapter->NdisCmConfigHandler != NULL)) { crRetCode = pAdapter->NdisCmConfigHandler( cfFuncName, cfSubFuncName, cfDevNode, dwRefData, ulFlags);
if ((cfFuncName == MY_CONFIG_PREREMOVE) || ((cfFuncName == MY_CONFIG_PRESHUTDOWN) && (pAdapter->bRunningOnWin98Gold))) { RndismpInternalHalt((NDIS_HANDLE)pAdapter, FALSE); } } else { crRetCode = MY_CR_SUCCESS; } } while (FALSE);
return (crRetCode); }
#endif // BUILD_WIN9X
|