/*++ Copyright (c) 1990-1995 Microsoft Corporation Module Name: initpnp.c Abstract: NDIS wrapper functions initializing drivers. Author: Jameel Hyder (jameelh) 11-Aug-1995 Environment: Kernel mode, FSD Revision History: --*/ #include #pragma hdrstop #include // // Define the module number for debug code. // #define MODULE_NUMBER MODULE_INITPNP NDIS_STATUS ndisInitializeConfiguration( OUT PNDIS_WRAPPER_CONFIGURATION_HANDLE pConfigurationHandle, IN PNDIS_MINIPORT_BLOCK Miniport, OUT PUNICODE_STRING pExportName OPTIONAL ) /*++ Routine Description: Arguments: Return Value: --*/ { #define PQueryTable pConfigurationHandle->ParametersQueryTable #define LQueryTable pConfigurationHandle->ParametersQueryTable NDIS_STATUS NdisStatus; PWSTR Export = NULL; NTSTATUS RegistryStatus; PNDIS_CONFIGURATION_PARAMETER ReturnedValue; NDIS_CONFIGURATION_HANDLE CnfgHandle; NDIS_STRING BusNumberStr = NDIS_STRING_CONST("BusNumber"); NDIS_STRING SlotNumberStr = NDIS_STRING_CONST("SlotNumber"); NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType"); NDIS_STRING PnPCapsStr = NDIS_STRING_CONST("PnPCapabilities"); NDIS_STRING RemoteBootStr = NDIS_STRING_CONST("RemoteBootCard"); NDIS_STRING PollMediaConnectivityStr = NDIS_STRING_CONST("RequiresMediaStatePoll"); NDIS_STRING NdisDriverVerifyFlagsStr = NDIS_STRING_CONST("NdisDriverVerifyFlags"); NDIS_STRING SGMapRegistersNeededStr = NDIS_STRING_CONST("SGMapRegistersNeeded"); #ifdef NDIS_MEDIA_DISCONNECT_POWER_OFF NDIS_STRING MediaDisconnectTimeOutStr = NDIS_STRING_CONST("MediaDisconnectToSleepTimeOut"); ULONG MediaDisconnectTimeOut = (ULONG)-1; #endif HANDLE Handle; PDEVICE_OBJECT PhysicalDeviceObject; NDIS_INTERFACE_TYPE BusType = Isa; UINT BusNumber = 0; ULONG ResultLength; PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode; GUID BusTypeGuid; DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("==>ndisInitializeConfiguration: Miniport %p\n", Miniport)); CnfgHandle.ParameterList = NULL; do { PhysicalDeviceObject = Miniport->PhysicalDeviceObject; if (Miniport->BindPaths == NULL) { NdisStatus = ndisReadBindPaths(Miniport, LQueryTable); if (NdisStatus != NDIS_STATUS_SUCCESS) { break; } } if (pExportName != NULL) { // // get a handle to "driver" section for PDO // #if NDIS_TEST_REG_FAILURE RegistryStatus = STATUS_UNSUCCESSFUL; Handle = NULL; #else RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ | MAXIMUM_ALLOWED, &Handle); #endif #if !NDIS_NO_REGISTRY if (!NT_SUCCESS(RegistryStatus)) { NdisStatus = NDIS_STATUS_FAILURE; break; } // // Set up LQueryTable to do the following: // // // 1. Switch to the Linkage key below this driver instance key // LQueryTable[0].QueryRoutine = NULL; LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; LQueryTable[0].Name = L"Linkage"; // // 2. Call ndisReadParameter for "Export" (as a single multi-string) // which will allocate storage and save the data in Export. // LQueryTable[1].QueryRoutine = ndisReadParameter; LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; LQueryTable[1].Name = L"Export"; LQueryTable[1].EntryContext = (PVOID)&Export; LQueryTable[1].DefaultType = REG_NONE; // // 3. Stop // LQueryTable[2].QueryRoutine = NULL; LQueryTable[2].Flags = 0; LQueryTable[2].Name = NULL; RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, Handle, LQueryTable, (PVOID)NULL, // no context needed NULL); ZwClose(Handle); if (!NT_SUCCESS(RegistryStatus)) { DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR, ("ndisInitializeConfiguration: Could not read Bind/Export for %Z: %lx\n", &Miniport->BaseName, RegistryStatus)); NdisStatus = NDIS_STATUS_FAILURE; break; } #else if (NT_SUCCESS(RegistryStatus)) { // // Set up LQueryTable to do the following: // // // 1. Switch to the Linkage key below this driver instance key // LQueryTable[0].QueryRoutine = NULL; LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; LQueryTable[0].Name = L"Linkage"; // // 2. Call ndisReadParameter for "Export" (as a single multi-string) // which will allocate storage and save the data in Export. // LQueryTable[1].QueryRoutine = ndisReadParameter; LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; LQueryTable[1].Name = L"Export"; LQueryTable[1].EntryContext = (PVOID)&Export; LQueryTable[1].DefaultType = REG_NONE; // // 3. Stop // LQueryTable[2].QueryRoutine = NULL; LQueryTable[2].Flags = 0; LQueryTable[2].Name = NULL; RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, Handle, LQueryTable, (PVOID)NULL, // no context needed NULL); ZwClose(Handle); if (!NT_SUCCESS(RegistryStatus)) { DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR, ("ndisInitializeConfiguration: Could not read Bind/Export for %Z: %lx\n", &Miniport->BaseName, RegistryStatus)); NdisStatus = NDIS_STATUS_FAILURE; break; } } else { // // we have to allocate space for default export name because the // caller will attempt to free it // Export = (PWSTR)ALLOC_FROM_POOL(sizeof(NDIS_DEFAULT_EXPORT_NAME), NDIS_TAG_NAME_BUF); if (Export == NULL) { NdisStatus = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory(Export, ndisDefaultExportName, sizeof(NDIS_DEFAULT_EXPORT_NAME)); } #endif RtlInitUnicodeString(pExportName, Export); } // // NdisReadConfiguration assumes that ParametersQueryTable[3].Name is // a key below the services key where the Parameters should be read, // for layered drivers we store the last piece of Configuration // Path there, leading to the desired effect. // // I.e, ConfigurationPath == "...\Services\Driver". // // // 1) Call ndisSaveParameter for a parameter, which will allocate storage for it. // PQueryTable[0].QueryRoutine = NULL; PQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; PQueryTable[0].Name = L""; // // The following fields are filled in during NdisReadConfiguration // // PQueryTable[1].Name = KeywordBuffer; // PQueryTable[1].EntryContext = ParameterValue; PQueryTable[1].QueryRoutine = ndisSaveParameters; PQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; PQueryTable[1].DefaultType = REG_NONE; // // 2. Stop // PQueryTable[2].QueryRoutine = NULL; PQueryTable[2].Flags = 0; PQueryTable[2].Name = NULL; // // NOTE: Some fields in ParametersQueryTable[3 & 4] are used to // store information for later retrieval. // Save Adapter/Miniport block here. Later on, Adapter's PDO // will be used to open the appropiate registry key // (PVOID)PQueryTable[3].QueryRoutine = (PVOID)Miniport; PQueryTable[3].Name = L""; PQueryTable[3].EntryContext = NULL; PQueryTable[3].DefaultData = NULL; // Now read bustype/busnumber for this adapter and save it CnfgHandle.KeyQueryTable = PQueryTable; RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusTypeGuid, sizeof(GUID), (PVOID)&BusTypeGuid, &ResultLength); // // try to get the -real- bus type by first querying the bustype guid // if we couldn't get the guid, try to get a legacy bustype. because // some bus drivers like pcmcia do not report the real bus type, we // have to query the bus type guid first. // if (NT_SUCCESS(RegistryStatus)) { if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_INTERNAL, sizeof(GUID))) BusType = Internal; else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_PCMCIA, sizeof(GUID))) BusType = PCMCIABus; else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_PCI, sizeof(GUID))) BusType = PCIBus; else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_ISAPNP, sizeof(GUID))) BusType = PNPISABus; else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_EISA, sizeof(GUID))) { BusType = Eisa; ASSERT(BusType != Eisa); } else BusType = Isa; } if (BusType == Isa) { // // either the call to get BusTypeGuid failed or the returned guid // does not match any that we know of // RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyLegacyBusType, sizeof(UINT), (PVOID)&BusType, &ResultLength); } if (!NT_SUCCESS(RegistryStatus) || (BusType == Isa) || (BusType == PCMCIABus)) { if (NT_SUCCESS(RegistryStatus)) { ASSERT(BusType != Isa); } // // if the call was unsuccessful or BusType is ISA or PCMCIABus // read BusType from registry // NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &BusTypeStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { BusType = (NDIS_INTERFACE_TYPE)(ReturnedValue->ParameterData.IntegerData); } } if ((BusType == PCIBus) || (BusType == PCMCIABus)) { ASSERT(CURRENT_IRQL < DISPATCH_LEVEL); NdisStatus = ndisQueryBusInterface(Miniport); if (NdisStatus != NDIS_STATUS_SUCCESS) { ASSERT(FALSE); break; } } if ((BusType == Eisa) || (BusType == MicroChannel)) { NdisStatus = NDIS_STATUS_NOT_SUPPORTED; break; } Miniport->BusType = BusType; // // Read PnP capabilities. By default the WOL feature should be disabled // // NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &PnPCapsStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { Miniport->PnPCapabilities = ReturnedValue->ParameterData.IntegerData; } else { Miniport->PnPCapabilities = NDIS_DEVICE_DISABLE_WAKE_UP; } // // try to get the bus number from PnP and if it fails // try reading it from registry // RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusNumber, sizeof(UINT), (PVOID)&BusNumber, &ResultLength); if (!NT_SUCCESS(RegistryStatus)) { // // if the call was unsuccessful // Read Bus Number from registry // NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &BusNumberStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { BusNumber = ReturnedValue->ParameterData.IntegerData; } } Miniport->BusNumber = BusNumber; // // Read Slot Number // NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &SlotNumberStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { Miniport->SlotNumber = ReturnedValue->ParameterData.IntegerData; } else { Miniport->SlotNumber = (ULONG)-1; } NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &RemoteBootStr, NdisParameterHexInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { if (ReturnedValue->ParameterData.IntegerData != 0) { MINIPORT_SET_FLAG(Miniport, fMINIPORT_NETBOOT_CARD); Miniport->InfoFlags |= NDIS_MINIPORT_NETBOOT_CARD; } } #ifdef NDIS_MEDIA_DISCONNECT_POWER_OFF //1 for .NET this is not supported, it should be ifdef'ed out // // read the value for media disconnect timer, set to 20 seconds if not present // default=disable pm when cable is disconnected // MediaDisconnectTimeOut = (ULONG)-1; NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &MediaDisconnectTimeOutStr, NdisParameterHexInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { MediaDisconnectTimeOut = ReturnedValue->ParameterData.IntegerData; if (MediaDisconnectTimeOut == 0) { MediaDisconnectTimeOut = 1; } } Miniport->MediaDisconnectTimeOut = (USHORT)MediaDisconnectTimeOut; if (MediaDisconnectTimeOut == (ULONG)(-1)) { Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT; } #else Miniport->MediaDisconnectTimeOut = (USHORT)-1; Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT; #endif //1 this (media polling) is not needed any more. NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &PollMediaConnectivityStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { // // This miniport wants Ndis to poll it regularly for media connectivity. // Default value is FALSE for this flag. This flag will be cleared if miniport // can indicate media status or does not support media query // if (ReturnedValue->ParameterData.IntegerData == 1) { MINIPORT_SET_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING); } } //1 check for range NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &SGMapRegistersNeededStr, NdisParameterInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { Miniport->SGMapRegistersNeeded = (USHORT)ReturnedValue->ParameterData.IntegerData; } else { Miniport->SGMapRegistersNeeded = NDIS_MAXIMUM_SCATTER_GATHER_SEGMENTS; } NdisReadConfiguration(&NdisStatus, &ReturnedValue, &CnfgHandle, &NdisDriverVerifyFlagsStr, NdisParameterHexInteger); if (NdisStatus == NDIS_STATUS_SUCCESS) { Miniport->DriverVerifyFlags = ReturnedValue->ParameterData.IntegerData; } PQueryTable[3].DefaultData = NULL; PQueryTable[3].Flags = 0; NdisStatus = NDIS_STATUS_SUCCESS; } while (FALSE); // // free NDIS_CONFIGURATION_PARAMETER_QUEUE nodes hanging from CnfgHandle // ParameterNode = CnfgHandle.ParameterList; while (ParameterNode != NULL) { CnfgHandle.ParameterList = ParameterNode->Next; FREE_POOL(ParameterNode); ParameterNode = CnfgHandle.ParameterList; } #undef PQueryTable #undef LQueryTable DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("<==ndisInitializeConfiguration: Miniport %p\n", Miniport)); return(NdisStatus); } NTSTATUS ndisReadBindPaths( IN PNDIS_MINIPORT_BLOCK Miniport, IN PRTL_QUERY_REGISTRY_TABLE LQueryTable ) /*++ Routine Description: Arguments: Return Value: --*/ { NTSTATUS NtStatus; HANDLE Handle = NULL; PWSTR pPath, p, BindPathData = NULL; UINT i, Len, NumComponents; BOOLEAN FreeBindPathData = FALSE; DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("==>ndisReadBindPaths: Miniport %p\n", Miniport)); do { #if NDIS_TEST_REG_FAILURE NtStatus = STATUS_UNSUCCESSFUL; #else NtStatus = IoOpenDeviceRegistryKey(Miniport->PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ | MAXIMUM_ALLOWED, &Handle); #endif #if !NDIS_NO_REGISTRY if (!NT_SUCCESS(NtStatus)) break; // // 1. // Switch to the Linkage key below this driver instance key // LQueryTable[0].QueryRoutine = NULL; LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; LQueryTable[0].Name = L"Linkage"; // // 2. // Read the RootDevice keywords // LQueryTable[1].QueryRoutine = ndisReadParameter; LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND; LQueryTable[1].Name = L"RootDevice"; LQueryTable[1].EntryContext = (PVOID)&BindPathData; LQueryTable[1].DefaultType = REG_NONE; LQueryTable[2].QueryRoutine = NULL; LQueryTable[2].Flags = 0; LQueryTable[2].Name = NULL; NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, Handle, LQueryTable, NULL, NULL); ZwClose(Handle); if (!NT_SUCCESS(NtStatus)) { break; } #else if (NT_SUCCESS(NtStatus)) { // // 1. // Switch to the Linkage key below this driver instance key // LQueryTable[0].QueryRoutine = NULL; LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; LQueryTable[0].Name = L"Linkage"; // // 2. // Read the RootDevice keywords // LQueryTable[1].QueryRoutine = ndisReadParameter; LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND; LQueryTable[1].Name = L"RootDevice"; LQueryTable[1].EntryContext = (PVOID)&BindPathData; LQueryTable[1].DefaultType = REG_NONE; LQueryTable[2].QueryRoutine = NULL; LQueryTable[2].Flags = 0; LQueryTable[2].Name = NULL; NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, Handle, LQueryTable, NULL, NULL); ZwClose(Handle); if (!NT_SUCCESS(NtStatus)) break; } else { NtStatus = STATUS_SUCCESS; } #endif // // BindPath is a MULTI-SZ which starts at the top of the filter chain // and goes down to the miniport. It is of the form // // {FN} {FN-1} ... {F1} {Adapter} // // Where spaces are actually nulls and each of {Fn} is a filter instance. // if (BindPathData == NULL) { BindPathData = Miniport->BaseName.Buffer; } else { FreeBindPathData = TRUE; } // // Split bindpath into individual components. Start by determining how much // space we need. // Len = sizeof(NDIS_BIND_PATHS); for (pPath = BindPathData, NumComponents = 0; *pPath != 0; NOTHING) { NDIS_STRING us; RtlInitUnicodeString(&us, pPath); NumComponents++; Len += sizeof(NDIS_STRING) + us.Length + ndisDeviceStr.Length + sizeof(WCHAR); (PUCHAR)pPath += (us.Length + sizeof(WCHAR)); } // // Allocate space for bindpaths. We have NumComponents paths // which consume Len bytes of space. We could be re-initialzing // so free any previous buffer allcoated for this. // if (Miniport->BindPaths != NULL) { FREE_POOL(Miniport->BindPaths); } Miniport->BindPaths = (PNDIS_BIND_PATHS)ALLOC_FROM_POOL(Len, NDIS_TAG_NAME_BUF); if (Miniport->BindPaths == NULL) { NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } ZeroMemory(Miniport->BindPaths, Len); Miniport->BindPaths->Number = NumComponents; if (NumComponents > 1) { MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_FILTER_IM); Miniport->InfoFlags |= NDIS_MINIPORT_FILTER_IM; } // // Create an array in reverse order of device-names in the filter path. // p = (PWSTR)((PUCHAR)Miniport->BindPaths + sizeof(NDIS_BIND_PATHS) + NumComponents*sizeof(NDIS_STRING)); for (pPath = BindPathData, i = (NumComponents-1); *pPath != 0; i --) { NDIS_STRING Str, SubStr, *Bp; RtlInitUnicodeString(&Str, pPath); (PUCHAR)pPath += (Str.Length + sizeof(WCHAR)); Bp = &Miniport->BindPaths->Paths[i]; Bp->Buffer = p; Bp->Length = 0; Bp->MaximumLength = Str.Length + ndisDeviceStr.Length + sizeof(WCHAR); SubStr.Buffer = (PWSTR)((PUCHAR)p + ndisDeviceStr.Length); SubStr.MaximumLength = Str.Length + sizeof(WCHAR); SubStr.Length = 0; RtlCopyUnicodeString(Bp, &ndisDeviceStr); RtlUpcaseUnicodeString(&SubStr, &Str, FALSE); Bp->Length += SubStr.Length; (PUCHAR)p += Bp->MaximumLength; } } while (FALSE); if (FreeBindPathData) FREE_POOL(BindPathData); ; DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("<==ndisReadBindPaths: Miniport %p\n", Miniport)); return NtStatus; } NTSTATUS ndisCreateAdapterInstanceName( OUT PUNICODE_STRING * pAdapterInstanceName, IN PDEVICE_OBJECT PhysicalDeviceObject ) { NTSTATUS NtStatus, SlotQueryStatus; DEVICE_REGISTRY_PROPERTY Property; PWCHAR pValueInfo = NULL; ULONG ResultLength = 0; PUNICODE_STRING AdapterInstanceName = NULL; ULONG SlotNumber; DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO, ("==>ndisCreateAdapterInstanceName: PDO %p\n", PhysicalDeviceObject)); do { //1 add comments and check to see if the DevicePropertyFriendlyName should always be there. *pAdapterInstanceName = NULL; Property = DevicePropertyFriendlyName; NtStatus = IoGetDeviceProperty(PhysicalDeviceObject, Property, 0, NULL, &ResultLength); if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus)) { Property = DevicePropertyDeviceDescription; NtStatus = IoGetDeviceProperty(PhysicalDeviceObject, Property, 0, NULL, &ResultLength); if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus)) { DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR, ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject)); break; } } // // Allocate space to hold the partial value information. // pValueInfo = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_DEFAULT); if (NULL == pValueInfo) { NtStatus = STATUS_INSUFFICIENT_RESOURCES; DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR, ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter description\n", PhysicalDeviceObject)); break; } RtlZeroMemory(pValueInfo, ResultLength); NtStatus = IoGetDeviceProperty(PhysicalDeviceObject, Property, ResultLength, pValueInfo, &ResultLength); if (!NT_SUCCESS(NtStatus)) { DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR, ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject)); break; } // // Determine the size of the instance name buffer. This is a UNICODE_STRING // and it's associated buffer. // ResultLength += sizeof(UNICODE_STRING); // // Allocate the buffer. // AdapterInstanceName = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_NAME_BUF); if (NULL == AdapterInstanceName) { NtStatus = STATUS_INSUFFICIENT_RESOURCES; DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR, ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter instance name\n", PhysicalDeviceObject)); break; } // // Initialize the buffer. // RtlZeroMemory(AdapterInstanceName, ResultLength); // // Initialize the UNICODE_STRING for the instance name. // AdapterInstanceName->Buffer = (PWSTR)((PUCHAR)AdapterInstanceName + sizeof(UNICODE_STRING)); AdapterInstanceName->Length = 0; AdapterInstanceName->MaximumLength = (USHORT)(ResultLength - sizeof(UNICODE_STRING)); RtlAppendUnicodeToString(AdapterInstanceName, pValueInfo); DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO, ("ndisCreateAdapterInstanceName: %ws\n", AdapterInstanceName->Buffer)); // // Return the instance name. // *pAdapterInstanceName = AdapterInstanceName; //1 this should be in checked builds only. // // get the slot number // Property = DevicePropertyUINumber; SlotQueryStatus = IoGetDeviceProperty(PhysicalDeviceObject, Property, sizeof (ULONG), &SlotNumber, &ResultLength); if (NT_SUCCESS(SlotQueryStatus)) { DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO, ("ndisCreateAdapterInstanceName: %ws, Slot Number: %ld\n", AdapterInstanceName->Buffer, SlotNumber)); } else { DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO, ("ndisCreateAdapterInstanceName: couldn't get SlotNumber for %ws\n", AdapterInstanceName->Buffer)); } } while (FALSE); if (NULL != pValueInfo) FREE_POOL(pValueInfo); DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO, ("<==ndisCreateAdapterInstanceName: PDO %p, Status 0x%x\n", PhysicalDeviceObject, NtStatus)); return(NtStatus); } NDIS_STATUS ndisInitializeAdapter( IN PNDIS_M_DRIVER_BLOCK pMiniBlock, IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING InstanceName, IN NDIS_HANDLE DeviceContext OPTIONAL ) { NDIS_WRAPPER_CONFIGURATION_HANDLE ConfigurationHandle; NDIS_STATUS NdisStatus; UNICODE_STRING ExportName; PNDIS_MINIPORT_BLOCK Miniport= (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1); TIME TS, TE, TD; #define PQueryTable ConfigurationHandle.ParametersQueryTable #define Db ConfigurationHandle.Db DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("==>ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport)); do { ZeroMemory(&ConfigurationHandle, sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE)); ExportName.Buffer = NULL; // // Build the configuration handle. // NdisStatus = ndisInitializeConfiguration(&ConfigurationHandle, Miniport, &ExportName); if (NdisStatus != NDIS_STATUS_SUCCESS) { break; } // // OK, Now lock down all the filter packages. If a MAC or // Miniport driver uses any of these, then the filter package // will reference itself, to keep the image in memory. // #if ARCNET ArcReferencePackage(); #endif EthReferencePackage(); FddiReferencePackage(); TrReferencePackage(); MiniportReferencePackage(); CoReferencePackage(); ConfigurationHandle.DeviceObject = DeviceObject; ConfigurationHandle.DriverBaseName = InstanceName; KeQuerySystemTime(&TS); // // Save the Driver Object with the configuration handle. // ConfigurationHandle.DriverObject = pMiniBlock->NdisDriverInfo->DriverObject; NdisStatus = ndisMInitializeAdapter(pMiniBlock, &ConfigurationHandle, &ExportName, DeviceContext); KeQuerySystemTime(&TE); TD.QuadPart = TE.QuadPart - TS.QuadPart; TD.QuadPart /= 10000; // Convert to ms Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)(ConfigurationHandle.DeviceObject->DeviceExtension) + 1); Miniport->InitTimeMs = TD.LowPart; if (ndisFlags & NDIS_GFLAG_INIT_TIME) { DbgPrint("NDIS: Init time (%Z) %ld ms\n", Miniport->pAdapterInstanceName, Miniport->InitTimeMs); } if (NdisStatus != NDIS_STATUS_SUCCESS) { ndisCloseULongRef(&Miniport->Ref); } // // OK, Now dereference all the filter packages. If a MAC or // Miniport driver uses any of these, then the filter package // will reference itself, to keep the image in memory. // #if ARCNET ArcDereferencePackage(); #endif EthDereferencePackage(); FddiDereferencePackage(); TrDereferencePackage(); MiniportDereferencePackage(); CoDereferencePackage(); } while (FALSE); if (ExportName.Buffer) FREE_POOL(ExportName.Buffer); // // free "Bind" data // if (PQueryTable[3].EntryContext != NULL) FREE_POOL(PQueryTable[3].EntryContext); #undef PQueryTable #undef Db DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("<==ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport)); return(NdisStatus); } VOID FASTCALL ndisCheckAdapterBindings( IN PNDIS_MINIPORT_BLOCK Miniport, IN PNDIS_PROTOCOL_BLOCK Protocol OPTIONAL ) /*+++ Routine Description: This function, reads the registry to get all the protocols that are supposed to bind to this adapter and for each protocol, calls ndisInitializeBinding Arguments: Adapter Pointer to ndis Adpater or Miniport block Protocol Optionally if a protocol is specified, initiate binding to only that protocol Return Value: None ---*/ { RTL_QUERY_REGISTRY_TABLE LinkQueryTable[3]; NTSTATUS RegistryStatus; PWSTR UpperBind = NULL; HANDLE Handle; PDEVICE_OBJECT PhysicalDeviceObject; UNICODE_STRING Us; PWSTR CurProtocolName; PNDIS_PROTOCOL_BLOCK CurProtocol, NextProtocol; KIRQL OldIrql; DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("==>ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol)); do { // // get a handle to driver section in registry // PhysicalDeviceObject = Miniport->PhysicalDeviceObject; if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SECONDARY)) { // // Skip bind notifications for a secondary miniport // break; } #if NDIS_TEST_REG_FAILURE RegistryStatus = STATUS_UNSUCCESSFUL; Handle = NULL; #else RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ | MAXIMUM_ALLOWED, &Handle); #endif #if NDIS_NO_REGISTRY if (!NT_SUCCESS(RegistryStatus)) { if (ARGUMENT_PRESENT(Protocol)) { ndisInitializeBinding(Miniport, Protocol); break; } else { ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql); for (CurProtocol = ndisProtocolList; CurProtocol != NULL; CurProtocol = NextProtocol) { if (ndisReferenceProtocol(CurProtocol)) { RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql); ndisInitializeBinding(Miniport, CurProtocol); ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql); NextProtocol = CurProtocol->NextProtocol; ndisDereferenceProtocol(CurProtocol, TRUE); } else { NextProtocol = CurProtocol->NextProtocol; } } RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql); } break; } #else if (!NT_SUCCESS(RegistryStatus)) { break; } #endif // // Set up LinkQueryTable to do the following: // // // 1) Switch to the Linkage key below the xports registry key // LinkQueryTable[0].QueryRoutine = NULL; LinkQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; LinkQueryTable[0].Name = L"Linkage"; // // 2) Call ndisReadParameter for "UpperBind" (as a single multi-string), // which will allocate storage and save the data in UpperBind. // LinkQueryTable[1].QueryRoutine = ndisReadParameter; LinkQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; LinkQueryTable[1].Name = L"UpperBind"; LinkQueryTable[1].EntryContext = (PVOID)&UpperBind; LinkQueryTable[1].DefaultType = REG_NONE; // // 3) Stop // LinkQueryTable[2].QueryRoutine = NULL; LinkQueryTable[2].Flags = 0; LinkQueryTable[2].Name = NULL; RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, Handle, LinkQueryTable, (PVOID)NULL, // no context needed NULL); ZwClose(Handle); if (NT_SUCCESS(RegistryStatus)) { for (CurProtocolName = UpperBind; *CurProtocolName != 0; CurProtocolName = (PWCHAR)((PUCHAR)CurProtocolName + Us.MaximumLength)) { RtlInitUnicodeString (&Us, CurProtocolName); if (ARGUMENT_PRESENT(Protocol)) { if (RtlEqualUnicodeString(&Us, &Protocol->ProtocolCharacteristics.Name, TRUE)) { ndisInitializeBinding(Miniport, Protocol); break; } } else { CurProtocol = NULL; if (ndisReferenceProtocolByName(&Us, &CurProtocol, FALSE) == NDIS_STATUS_SUCCESS) { ndisInitializeBinding(Miniport, CurProtocol); ndisDereferenceProtocol(CurProtocol, FALSE); } } } } // // Handle proxy and rca filters. // if ((Miniport != NULL) && !ndisMediaTypeCl[Miniport->MediaType] && MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO)) { BOOLEAN bCanMiniportBindtoAllCoProtocol = FALSE; if (ARGUMENT_PRESENT(Protocol)) { // // Only create the binding between the bind_all_Co protocol if the miniport // does not veto it // bCanMiniportBindtoAllCoProtocol = \ ((Protocol->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO) && (!(Miniport->MiniportAttributes & NDIS_ATTRIBUTE_DO_NOT_BIND_TO_ALL_CO ))); if (bCanMiniportBindtoAllCoProtocol) { ndisInitializeBinding(Miniport, Protocol); } } else { ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql); for (CurProtocol = ndisProtocolList; CurProtocol != NULL; CurProtocol = NextProtocol) { bCanMiniportBindtoAllCoProtocol = \ ((CurProtocol ->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO) && (!(Miniport->MiniportAttributes & NDIS_ATTRIBUTE_DO_NOT_BIND_TO_ALL_CO ))); if (bCanMiniportBindtoAllCoProtocol && ndisReferenceProtocol(CurProtocol)) { RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql); ndisInitializeBinding(Miniport, CurProtocol); ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql); NextProtocol = CurProtocol->NextProtocol; ndisDereferenceProtocol(CurProtocol, TRUE); } else { NextProtocol = CurProtocol->NextProtocol; } } RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql); } } } while (FALSE); if (UpperBind != NULL) FREE_POOL(UpperBind); DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("<==ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol)); } BOOLEAN FASTCALL ndisProtocolAlreadyBound( IN PNDIS_PROTOCOL_BLOCK Protocol, IN PNDIS_MINIPORT_BLOCK Miniport ) { PNDIS_OPEN_BLOCK pOpen; BOOLEAN rc = FALSE; KIRQL OldIrql; DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO, ("==>ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport)); PnPReferencePackage(); ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql); for (pOpen = Protocol->OpenQueue; pOpen != NULL; pOpen = pOpen->ProtocolNextOpen) { if (pOpen->MiniportHandle == Miniport) { rc = TRUE; break; } } RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql); PnPDereferencePackage(); DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO, ("<==ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport)); return rc; } NDIS_STATUS NdisIMInitializeDeviceInstance( IN NDIS_HANDLE DriverHandle, IN PNDIS_STRING DeviceInstance ) /*++ Routine Description: Initialize an instance of a miniport device. Arguments: DriverHandle - Handle returned by NdisMRegisterLayeredMiniport. It is a pointer to NDIS_M_DRIVER_BLOCK. DeviceInstance -Points to the instance of the driver that must now be initialized. Return Value: --*/ { NDIS_STATUS Status; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance)); Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, DeviceInstance, NULL); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance)); return Status; } NDIS_STATUS NdisIMInitializeDeviceInstanceEx( IN NDIS_HANDLE DriverHandle, IN PNDIS_STRING DeviceInstance, IN NDIS_HANDLE DeviceContext ) /*++ Routine Description: Initialize an instance of a miniport device. Incarnation of NdisIMInitializeDeviceInstance. Arguments: DriverHandle Handle returned by NdisMRegisterLayeredMiniport. It is a pointer to NDIS_M_DRIVER_BLOCK. DeviceInstance Points to the instance of the driver that must now be initialized. DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext. Return Value: --*/ { NDIS_STATUS Status; PNDIS_M_DRIVER_BLOCK MiniBlock = (PNDIS_M_DRIVER_BLOCK)DriverHandle; PNDIS_MINIPORT_BLOCK Miniport; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p\n", DriverHandle, DeviceInstance, DeviceContext)); PnPReferencePackage(); WAIT_FOR_OBJECT(&MiniBlock->IMStartRemoveMutex, NULL); do { Miniport = ndisFindMiniportOnGlobalList(DeviceInstance); //1 we need some protection so miniport does not go away. (Should ref the miniport) if (Miniport != NULL) { if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_RECEIVED_START) && !MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REMOVE_IN_PROGRESS | fMINIPORT_PM_HALTED)) { DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("NdisIMInitializeDeviceInstanceEx: we have already received START_IRP for Miniport %p\n", Miniport)); // // check to make sure the miniport has not been initialized already // i.e. we are not getting duplicate NdisIMInitializeDeviceInstance // a device that has already been initialized // if (ndisIsMiniportStarted(Miniport)) { DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_ERR, ("NdisIMInitializeDeviceInstanceEx: we have already initialized this device. Miniport %p\n", Miniport)); Status = NDIS_STATUS_NOT_ACCEPTED; break; } Status = ndisIMInitializeDeviceInstance(Miniport, DeviceContext, FALSE); if (Status != NDIS_STATUS_SUCCESS) { // // since we have already succeeded the START_IRP, signal PnP to remove this device // by tagging the device as failed and requesting a QUERY_PNP_DEVICE_STATE IRP // MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_FAILED); IoInvalidateDeviceState(Miniport->PhysicalDeviceObject); } break; } } // // device is not started or not added yet. // Status = ndisIMQueueDeviceInstance(DriverHandle, DeviceInstance, DeviceContext); } while (FALSE); RELEASE_MUTEX(&MiniBlock->IMStartRemoveMutex); PnPDereferencePackage(); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p, Status %lx\n", DriverHandle, DeviceInstance, DeviceContext, Status)); return Status; } NDIS_STATUS ndisIMInitializeDeviceInstance( IN PNDIS_MINIPORT_BLOCK Miniport, IN NDIS_HANDLE DeviceContext, IN BOOLEAN fStartIrp ) /*++ Routine Description: This routine is called when we have received NdisIMInitializeDeviceInstance -AND- START IRP for an IM miniport. Initialize an instance of a miniport device. Arguments: Miniport Handle to NDIS_MINIPORT_BLOCK DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext. fStartIrp flag to signal if we are in the context of handling START IRP Return Value: --*/ { NDIS_STATUS Status; NTSTATUS NtStatus; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>ndisIMInitializeDeviceInstance: Miniport %p, Context %p, fStartIrp %lx\n", Miniport, DeviceContext, fStartIrp)); // // it is quite possible we are dealing with a miniport block that has been "used" // several times. inother words, it has been started and DeviceInitialized, then // Device-De-Initialized and then has received a few query_stop and cancel_stop. // in this case the miniport block has to be cleaned up. otherwise, ndisPnPStartDevice // is not going to detect that miniport block needs re-initalization // ndisReinitializeMiniportBlock(Miniport); Miniport->DeviceContext = DeviceContext; Status = ndisPnPStartDevice(Miniport->DeviceObject, NULL); // no Irp if (Status == NDIS_STATUS_SUCCESS) { // // if we are in the context of start IRP, queue a workitem to initialize // the bindings on this adapter to avoid the delay // if (!fStartIrp) { // // Now set the device class association so that people can reference this. // NtStatus = IoSetDeviceInterfaceState(&Miniport->SymbolicLinkName, TRUE); if (NT_SUCCESS(NtStatus)) { // // Do protocol notifications // ndisCheckAdapterBindings(Miniport, NULL); } else { DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR, ("ndisCheckAdapterBindings: IoSetDeviceInterfaceState failed: Miniport %p, Status %lx\n", Miniport, NtStatus)); Status = NDIS_STATUS_FAILURE; } } else { Status = ndisQueueBindWorkitem(Miniport); } } else { // // ndisPnPStartDevice can return an internal Error Code if the call // to ndisMInitializeAdapter fails. convert this to NDIS_STATUS // Status = NDIS_STATUS_FAILURE; } DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==ndisIMInitializeDeviceInstance: Miniport %p, Context %p, Status %lx\n", Miniport, DeviceContext, Status)); return Status; } NDIS_STATUS ndisIMQueueDeviceInstance( IN PNDIS_M_DRIVER_BLOCK MiniBlock, IN PNDIS_STRING DeviceInstance, IN NDIS_HANDLE DeviceContext ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PNDIS_PENDING_IM_INSTANCE NewImInstance, pTemp; KIRQL OldIrql; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p\n", MiniBlock, DeviceInstance, DeviceContext)); do { // // Queue the device name for which we have received an InitializeDeviceInstance // from an IM driver. Check for duplicates. // NewImInstance = (PNDIS_PENDING_IM_INSTANCE)ALLOC_FROM_POOL(sizeof(NDIS_PENDING_IM_INSTANCE) + DeviceInstance->Length + sizeof(WCHAR), NDIS_TAG_IM_DEVICE_INSTANCE); if (NULL == NewImInstance) { Status = NDIS_STATUS_RESOURCES; break; } NewImInstance->Context = DeviceContext; NewImInstance->Name.MaximumLength = DeviceInstance->Length + sizeof(WCHAR); NewImInstance->Name.Length = 0; NewImInstance->Name.Buffer = (PWSTR)((PUCHAR)NewImInstance + sizeof(NDIS_PENDING_IM_INSTANCE)); RtlUpcaseUnicodeString(&NewImInstance->Name, DeviceInstance, FALSE); ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql); for (pTemp = MiniBlock->PendingDeviceList; pTemp != NULL; pTemp = pTemp->Next) { if (NDIS_EQUAL_UNICODE_STRING(&NewImInstance->Name, &pTemp->Name)) { FREE_POOL(NewImInstance); Status = NDIS_STATUS_NOT_ACCEPTED; break; } } if (Status == NDIS_STATUS_SUCCESS) { NewImInstance->Next = MiniBlock->PendingDeviceList; MiniBlock->PendingDeviceList = NewImInstance; } RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql); } while (FALSE); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p, Status %lx\n", MiniBlock, DeviceInstance, DeviceContext, Status)); return Status; } BOOLEAN ndisIMCheckDeviceInstance( IN PNDIS_M_DRIVER_BLOCK MiniBlock, IN PUNICODE_STRING DeviceInstanceName, OUT PNDIS_HANDLE DeviceContext OPTIONAL ) { PNDIS_PENDING_IM_INSTANCE pDI, *ppDI; PNDIS_PROTOCOL_BLOCK Protocol = MiniBlock->AssociatedProtocol; KIRQL OldIrql; BOOLEAN rc = FALSE; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>ndisIMCheckDeviceInstance: Driver %p, DeviceInstanceName %p\n", MiniBlock, DeviceInstanceName)); PnPReferencePackage(); ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql); for (ppDI = &MiniBlock->PendingDeviceList; (pDI = *ppDI) != NULL; ppDI = &pDI->Next) { if (NDIS_EQUAL_UNICODE_STRING(&pDI->Name, DeviceInstanceName)) { if (ARGUMENT_PRESENT(DeviceContext)) { *DeviceContext = pDI->Context; } *ppDI = pDI->Next; FREE_POOL(pDI); rc = TRUE; break; } } RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql); PnPDereferencePackage(); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==ndisIMCheckDeviceInstance: Driver %p, Name %p, Context %p\n", MiniBlock, DeviceInstanceName, DeviceContext)); if (!rc && ARGUMENT_PRESENT(DeviceContext)) { // // Send a reconfig notification to the protocol associated with this IM // so it can re-initialize any device(s) it wants to // if (((Protocol = MiniBlock->AssociatedProtocol) != NULL) && (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL)) { // // We got a start device for an IM. Make sure its protocol // half has all the requisite bindings. This can happen // if an IM is disconnected and reconnected, for example. // Also give it a NULL reconfig event. ATMLANE uses that // NET_PNP_EVENT NetPnpEvent; KEVENT Event; NDIS_STATUS Status; NdisZeroMemory(&NetPnpEvent, sizeof(NetPnpEvent)); INITIALIZE_EVENT(&Event); NetPnpEvent.NetEvent = NetEventReconfigure; PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent)->pEvent = &Event; WAIT_FOR_PROTO_MUTEX(Protocol); Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(NULL, &NetPnpEvent); if (NDIS_STATUS_PENDING == Status) { // // Wait for completion. // WAIT_FOR_PROTOCOL(Protocol, &Event); } RELEASE_PROT_MUTEX(Protocol); } } return rc; } NDIS_STATUS NdisIMCancelInitializeDeviceInstance( IN NDIS_HANDLE DriverHandle, IN PNDIS_STRING DeviceInstance ) { NDIS_STATUS Status; UNICODE_STRING UpcaseDevice; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance)); // // change to upper case // UpcaseDevice.Length = DeviceInstance->Length; UpcaseDevice.MaximumLength = DeviceInstance->Length + sizeof(WCHAR); UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING); if (UpcaseDevice.Buffer == NULL) { return NDIS_STATUS_RESOURCES; } Status = RtlUpcaseUnicodeString(&UpcaseDevice, (PUNICODE_STRING)DeviceInstance, FALSE); ASSERT (NT_SUCCESS(Status)); Status = (ndisIMCheckDeviceInstance((PNDIS_M_DRIVER_BLOCK)DriverHandle, &UpcaseDevice, NULL) == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p, Status %lx\n", DriverHandle, DeviceInstance, Status)); FREE_POOL(UpcaseDevice.Buffer); return Status; } NDIS_HANDLE NdisIMGetDeviceContext( IN NDIS_HANDLE MiniportAdapterHandle ) { PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisIMGetDeviceContext: Miniport %p\n", Miniport)); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisIMGetDeviceContext: Miniport %p\n", Miniport)); return(Miniport->DeviceContext); } NDIS_HANDLE NdisIMGetBindingContext( IN NDIS_HANDLE ProtocolBindingContext ) { PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)ProtocolBindingContext; PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle; DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisIMGetBindingContext: Open %p\n", Open)); DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisIMGetBindingContext: Open %p\n", Open)); return(Miniport->DeviceContext); }