Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1762 lines
57 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. initpnp.c
  5. Abstract:
  6. NDIS wrapper functions initializing drivers.
  7. Author:
  8. Jameel Hyder (jameelh) 11-Aug-1995
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. --*/
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. #include <stdarg.h>
  16. //
  17. // Define the module number for debug code.
  18. //
  19. #define MODULE_NUMBER MODULE_INITPNP
  20. NDIS_STATUS
  21. ndisInitializeConfiguration(
  22. OUT PNDIS_WRAPPER_CONFIGURATION_HANDLE pConfigurationHandle,
  23. IN PNDIS_MINIPORT_BLOCK Miniport,
  24. OUT PUNICODE_STRING pExportName OPTIONAL
  25. )
  26. /*++
  27. Routine Description:
  28. Arguments:
  29. Return Value:
  30. --*/
  31. {
  32. #define PQueryTable pConfigurationHandle->ParametersQueryTable
  33. #define LQueryTable pConfigurationHandle->ParametersQueryTable
  34. NDIS_STATUS NdisStatus;
  35. PWSTR Export = NULL;
  36. NTSTATUS RegistryStatus;
  37. PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
  38. NDIS_CONFIGURATION_HANDLE CnfgHandle;
  39. NDIS_STRING BusNumberStr = NDIS_STRING_CONST("BusNumber");
  40. NDIS_STRING SlotNumberStr = NDIS_STRING_CONST("SlotNumber");
  41. NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType");
  42. NDIS_STRING PciIdStr = NDIS_STRING_CONST("AdapterCFID");
  43. NDIS_STRING PnPCapsStr = NDIS_STRING_CONST("PnPCapabilities");
  44. NDIS_STRING CharsStr = NDIS_STRING_CONST("Characteristics");
  45. NDIS_STRING RemoteBootStr = NDIS_STRING_CONST("RemoteBootCard");
  46. NDIS_STRING MediaDisconnectTimeOutStr = NDIS_STRING_CONST("MediaDisconnectToSleepTimeOut");
  47. NDIS_STRING PollMediaConnectivityStr = NDIS_STRING_CONST("RequiresMediaStatePoll");
  48. NDIS_STRING NdisDriverVerifyFlagsStr = NDIS_STRING_CONST("NdisDriverVerifyFlags");
  49. NDIS_STRING SGMapRegistersNeededStr = NDIS_STRING_CONST("SGMapRegistersNeeded");
  50. ULONG MediaDisconnectTimeOut;
  51. HANDLE Handle;
  52. PDEVICE_OBJECT PhysicalDeviceObject;
  53. NDIS_INTERFACE_TYPE BusType = Isa;
  54. UINT BusNumber = 0;
  55. ULONG ResultLength;
  56. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
  57. GUID BusTypeGuid;
  58. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  59. ("==>ndisInitializeConfiguration: Miniport %p\n", Miniport));
  60. CnfgHandle.ParameterList = NULL;
  61. do
  62. {
  63. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  64. if (Miniport->BindPaths == NULL)
  65. {
  66. NdisStatus = ndisReadBindPaths(Miniport, LQueryTable);
  67. if (NdisStatus != NDIS_STATUS_SUCCESS)
  68. {
  69. break;
  70. }
  71. }
  72. if (pExportName != NULL)
  73. {
  74. //
  75. // get a handle to "driver" section for PDO
  76. //
  77. #if NDIS_TEST_REG_FAILURE
  78. RegistryStatus = STATUS_UNSUCCESSFUL;
  79. Handle = NULL;
  80. #else
  81. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  82. PLUGPLAY_REGKEY_DRIVER,
  83. GENERIC_READ | MAXIMUM_ALLOWED,
  84. &Handle);
  85. #endif
  86. #if !NDIS_NO_REGISTRY
  87. if (!NT_SUCCESS(RegistryStatus))
  88. {
  89. NdisStatus = NDIS_STATUS_FAILURE;
  90. break;
  91. }
  92. //
  93. // Set up LQueryTable to do the following:
  94. //
  95. //
  96. // 1. Switch to the Linkage key below this driver instance key
  97. //
  98. LQueryTable[0].QueryRoutine = NULL;
  99. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  100. LQueryTable[0].Name = L"Linkage";
  101. //
  102. // 2. Call ndisReadParameter for "Export" (as a single multi-string)
  103. // which will allocate storage and save the data in Export.
  104. //
  105. LQueryTable[1].QueryRoutine = ndisReadParameter;
  106. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  107. LQueryTable[1].Name = L"Export";
  108. LQueryTable[1].EntryContext = (PVOID)&Export;
  109. LQueryTable[1].DefaultType = REG_NONE;
  110. //
  111. // 3. Stop
  112. //
  113. LQueryTable[2].QueryRoutine = NULL;
  114. LQueryTable[2].Flags = 0;
  115. LQueryTable[2].Name = NULL;
  116. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  117. Handle,
  118. LQueryTable,
  119. (PVOID)NULL, // no context needed
  120. NULL);
  121. ZwClose(Handle);
  122. if (!NT_SUCCESS(RegistryStatus))
  123. {
  124. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  125. ("ndisInitializeConfiguration: Could not read Bind/Export for %Z: %lx\n",
  126. &Miniport->BaseName,
  127. RegistryStatus));
  128. NdisStatus = NDIS_STATUS_FAILURE;
  129. break;
  130. }
  131. #else
  132. if (NT_SUCCESS(RegistryStatus))
  133. {
  134. //
  135. // Set up LQueryTable to do the following:
  136. //
  137. //
  138. // 1. Switch to the Linkage key below this driver instance key
  139. //
  140. LQueryTable[0].QueryRoutine = NULL;
  141. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  142. LQueryTable[0].Name = L"Linkage";
  143. //
  144. // 2. Call ndisReadParameter for "Export" (as a single multi-string)
  145. // which will allocate storage and save the data in Export.
  146. //
  147. LQueryTable[1].QueryRoutine = ndisReadParameter;
  148. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  149. LQueryTable[1].Name = L"Export";
  150. LQueryTable[1].EntryContext = (PVOID)&Export;
  151. LQueryTable[1].DefaultType = REG_NONE;
  152. //
  153. // 3. Stop
  154. //
  155. LQueryTable[2].QueryRoutine = NULL;
  156. LQueryTable[2].Flags = 0;
  157. LQueryTable[2].Name = NULL;
  158. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  159. Handle,
  160. LQueryTable,
  161. (PVOID)NULL, // no context needed
  162. NULL);
  163. ZwClose(Handle);
  164. if (!NT_SUCCESS(RegistryStatus))
  165. {
  166. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  167. ("ndisInitializeConfiguration: Could not read Bind/Export for %Z: %lx\n",
  168. &Miniport->BaseName,
  169. RegistryStatus));
  170. NdisStatus = NDIS_STATUS_FAILURE;
  171. break;
  172. }
  173. }
  174. else
  175. {
  176. //
  177. // we have to allocate space for default export name because the
  178. // caller will attempt to free it
  179. //
  180. Export = (PWSTR)ALLOC_FROM_POOL(sizeof(NDIS_DEFAULT_EXPORT_NAME),
  181. NDIS_TAG_NAME_BUF);
  182. if (Export == NULL)
  183. {
  184. NdisStatus = STATUS_INSUFFICIENT_RESOURCES;
  185. break;
  186. }
  187. RtlCopyMemory(Export, ndisDefaultExportName, sizeof(NDIS_DEFAULT_EXPORT_NAME));
  188. }
  189. #endif
  190. RtlInitUnicodeString(pExportName, Export);
  191. }
  192. //
  193. // NdisReadConfiguration assumes that ParametersQueryTable[3].Name is
  194. // a key below the services key where the Parameters should be read,
  195. // for layered drivers we store the last piece of Configuration
  196. // Path there, leading to the desired effect.
  197. //
  198. // I.e, ConfigurationPath == "...\Services\Driver".
  199. //
  200. //
  201. // 1) Call ndisSaveParameter for a parameter, which will allocate storage for it.
  202. //
  203. PQueryTable[0].QueryRoutine = NULL;
  204. PQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  205. PQueryTable[0].Name = L"";
  206. //
  207. // The following fields are filled in during NdisReadConfiguration
  208. //
  209. // PQueryTable[1].Name = KeywordBuffer;
  210. // PQueryTable[1].EntryContext = ParameterValue;
  211. PQueryTable[1].QueryRoutine = ndisSaveParameters;
  212. PQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  213. PQueryTable[1].DefaultType = REG_NONE;
  214. //
  215. // 2. Stop
  216. //
  217. PQueryTable[2].QueryRoutine = NULL;
  218. PQueryTable[2].Flags = 0;
  219. PQueryTable[2].Name = NULL;
  220. //
  221. // NOTE: Some fields in ParametersQueryTable[3 & 4] are used to
  222. // store information for later retrieval.
  223. // Save Adapter/Miniport block here. Later on, Adapter's PDO
  224. // will be used to open the appropiate registry key
  225. //
  226. (PVOID)PQueryTable[3].QueryRoutine = (PVOID)Miniport;
  227. PQueryTable[3].Name = L"";
  228. PQueryTable[3].EntryContext = NULL;
  229. PQueryTable[3].DefaultData = NULL;
  230. // Now read bustype/busnumber for this adapter and save it
  231. CnfgHandle.KeyQueryTable = PQueryTable;
  232. RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  233. DevicePropertyBusTypeGuid,
  234. sizeof(GUID),
  235. (PVOID)&BusTypeGuid,
  236. &ResultLength);
  237. //
  238. // try to get the -real- bus type by first querying the bustype guid
  239. // if we couldn't get the guid, try to get a legacy bustype. because
  240. // some bus drivers like pcmcia do not report the real bus type, we
  241. // have to query the bus type guid first.
  242. //
  243. if (NT_SUCCESS(RegistryStatus))
  244. {
  245. if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_INTERNAL, sizeof(GUID)))
  246. BusType = Internal;
  247. else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_PCMCIA, sizeof(GUID)))
  248. BusType = PCMCIABus;
  249. else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_PCI, sizeof(GUID)))
  250. BusType = PCIBus;
  251. else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_ISAPNP, sizeof(GUID)))
  252. BusType = PNPISABus;
  253. else if (!memcmp(&BusTypeGuid, &GUID_BUS_TYPE_EISA, sizeof(GUID)))
  254. {
  255. BusType = Eisa;
  256. ASSERT(BusType != Eisa);
  257. }
  258. else
  259. BusType = Isa;
  260. }
  261. if (BusType == Isa)
  262. {
  263. //
  264. // either the call to get BusTypeGuid failed or the returned guid
  265. // does not match any that we know of
  266. //
  267. RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  268. DevicePropertyLegacyBusType,
  269. sizeof(UINT),
  270. (PVOID)&BusType,
  271. &ResultLength);
  272. }
  273. if (!NT_SUCCESS(RegistryStatus)
  274. || (BusType == Isa)
  275. || (BusType == PCMCIABus))
  276. {
  277. if (NT_SUCCESS(RegistryStatus))
  278. {
  279. ASSERT(BusType != Isa);
  280. }
  281. //
  282. // if the call was unsuccessful or BusType is ISA or PCMCIABus
  283. // read BusType from registry
  284. //
  285. NdisReadConfiguration(&NdisStatus,
  286. &ReturnedValue,
  287. &CnfgHandle,
  288. &BusTypeStr,
  289. NdisParameterInteger);
  290. if (NdisStatus == NDIS_STATUS_SUCCESS)
  291. {
  292. BusType = (NDIS_INTERFACE_TYPE)(ReturnedValue->ParameterData.IntegerData);
  293. }
  294. }
  295. if ((BusType == PCIBus) ||
  296. (BusType == PCMCIABus))
  297. {
  298. ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  299. NdisStatus = ndisQueryBusInterface(Miniport);
  300. if (NdisStatus != NDIS_STATUS_SUCCESS)
  301. {
  302. ASSERT(FALSE);
  303. break;
  304. }
  305. }
  306. if ((BusType == Eisa) ||
  307. (BusType == MicroChannel))
  308. {
  309. NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
  310. break;
  311. }
  312. Miniport->BusType = BusType;
  313. //
  314. // Read PnP capabilities. By default the WOL feature should be disabled
  315. //
  316. //
  317. NdisReadConfiguration(&NdisStatus,
  318. &ReturnedValue,
  319. &CnfgHandle,
  320. &PnPCapsStr,
  321. NdisParameterInteger);
  322. if (NdisStatus == NDIS_STATUS_SUCCESS)
  323. {
  324. Miniport->PnPCapabilities = ReturnedValue->ParameterData.IntegerData;
  325. }
  326. else
  327. {
  328. Miniport->PnPCapabilities = NDIS_DEVICE_DISABLE_WAKE_UP;
  329. }
  330. //
  331. // try to get the bus number from PnP and if it fails
  332. // try reading it from registry
  333. //
  334. RegistryStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  335. DevicePropertyBusNumber,
  336. sizeof(UINT),
  337. (PVOID)&BusNumber,
  338. &ResultLength);
  339. if (!NT_SUCCESS(RegistryStatus))
  340. {
  341. //
  342. // if the call was unsuccessful
  343. // Read Bus Number from registry
  344. //
  345. NdisReadConfiguration(&NdisStatus,
  346. &ReturnedValue,
  347. &CnfgHandle,
  348. &BusNumberStr,
  349. NdisParameterInteger);
  350. if (NdisStatus == NDIS_STATUS_SUCCESS)
  351. {
  352. BusNumber = ReturnedValue->ParameterData.IntegerData;
  353. }
  354. }
  355. Miniport->BusNumber = BusNumber;
  356. //
  357. // Read Slot Number
  358. //
  359. NdisReadConfiguration(&NdisStatus,
  360. &ReturnedValue,
  361. &CnfgHandle,
  362. &SlotNumberStr,
  363. NdisParameterInteger);
  364. if (NdisStatus == NDIS_STATUS_SUCCESS)
  365. {
  366. Miniport->SlotNumber = ReturnedValue->ParameterData.IntegerData;
  367. }
  368. else
  369. {
  370. Miniport->SlotNumber = -1;
  371. }
  372. NdisReadConfiguration(&NdisStatus,
  373. &ReturnedValue,
  374. &CnfgHandle,
  375. &RemoteBootStr,
  376. NdisParameterHexInteger);
  377. if (NdisStatus == NDIS_STATUS_SUCCESS)
  378. {
  379. if (ReturnedValue->ParameterData.IntegerData != 0)
  380. {
  381. MINIPORT_SET_FLAG(Miniport, fMINIPORT_NETBOOT_CARD);
  382. Miniport->InfoFlags |= NDIS_MINIPORT_NETBOOT_CARD;
  383. }
  384. }
  385. //
  386. // read the value for media disconnect timer, set to 20 seconds if not present
  387. // default=disable pm when cable is disconnected
  388. //
  389. MediaDisconnectTimeOut = -1;
  390. NdisReadConfiguration(&NdisStatus,
  391. &ReturnedValue,
  392. &CnfgHandle,
  393. &MediaDisconnectTimeOutStr,
  394. NdisParameterHexInteger);
  395. if (NdisStatus == NDIS_STATUS_SUCCESS)
  396. {
  397. MediaDisconnectTimeOut = ReturnedValue->ParameterData.IntegerData;
  398. if (MediaDisconnectTimeOut == 0)
  399. {
  400. MediaDisconnectTimeOut = 1;
  401. }
  402. }
  403. Miniport->MediaDisconnectTimeOut = (USHORT)MediaDisconnectTimeOut;
  404. if (MediaDisconnectTimeOut == (ULONG)(-1))
  405. {
  406. Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT;
  407. }
  408. NdisReadConfiguration(&NdisStatus,
  409. &ReturnedValue,
  410. &CnfgHandle,
  411. &PollMediaConnectivityStr,
  412. NdisParameterInteger);
  413. if (NdisStatus == NDIS_STATUS_SUCCESS)
  414. {
  415. //
  416. // This miniport wants Ndis to poll it regularly for media connectivity.
  417. // Default value is FALSE for this flag. This flag will be cleared if miniport
  418. // can indicate media status or does not support media query
  419. //
  420. if (ReturnedValue->ParameterData.IntegerData == 1)
  421. {
  422. MINIPORT_SET_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING);
  423. }
  424. }
  425. NdisReadConfiguration(&NdisStatus,
  426. &ReturnedValue,
  427. &CnfgHandle,
  428. &SGMapRegistersNeededStr,
  429. NdisParameterInteger);
  430. if (NdisStatus == NDIS_STATUS_SUCCESS)
  431. {
  432. Miniport->SGMapRegistersNeeded = (USHORT)ReturnedValue->ParameterData.IntegerData;
  433. }
  434. else
  435. {
  436. Miniport->SGMapRegistersNeeded = NDIS_MAXIMUM_SCATTER_GATHER_SEGMENTS;
  437. }
  438. NdisReadConfiguration(&NdisStatus,
  439. &ReturnedValue,
  440. &CnfgHandle,
  441. &NdisDriverVerifyFlagsStr,
  442. NdisParameterHexInteger);
  443. if (NdisStatus == NDIS_STATUS_SUCCESS)
  444. {
  445. Miniport->DriverVerifyFlags = ReturnedValue->ParameterData.IntegerData;
  446. }
  447. PQueryTable[3].DefaultData = NULL;
  448. PQueryTable[3].Flags = 0;
  449. NdisStatus = NDIS_STATUS_SUCCESS;
  450. } while (FALSE);
  451. //
  452. // free NDIS_CONFIGURATION_PARAMETER_QUEUE nodes hanging from CnfgHandle
  453. //
  454. ParameterNode = CnfgHandle.ParameterList;
  455. while (ParameterNode != NULL)
  456. {
  457. CnfgHandle.ParameterList = ParameterNode->Next;
  458. FREE_POOL(ParameterNode);
  459. ParameterNode = CnfgHandle.ParameterList;
  460. }
  461. #undef PQueryTable
  462. #undef LQueryTable
  463. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  464. ("<==ndisInitializeConfiguration: Miniport %p\n", Miniport));
  465. return(NdisStatus);
  466. }
  467. NTSTATUS
  468. ndisReadBindPaths(
  469. IN PNDIS_MINIPORT_BLOCK Miniport,
  470. IN PRTL_QUERY_REGISTRY_TABLE LQueryTable
  471. )
  472. /*++
  473. Routine Description:
  474. Arguments:
  475. Return Value:
  476. --*/
  477. {
  478. NTSTATUS NtStatus;
  479. HANDLE Handle = NULL;
  480. PWSTR pPath, p, BindPathData = NULL;
  481. UINT i, Len, NumComponents;
  482. BOOLEAN FreeBindPathData = FALSE;
  483. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  484. ("==>ndisReadBindPaths: Miniport %p\n", Miniport));
  485. do
  486. {
  487. #if NDIS_TEST_REG_FAILURE
  488. NtStatus = STATUS_UNSUCCESSFUL;
  489. #else
  490. NtStatus = IoOpenDeviceRegistryKey(Miniport->PhysicalDeviceObject,
  491. PLUGPLAY_REGKEY_DRIVER,
  492. GENERIC_READ | MAXIMUM_ALLOWED,
  493. &Handle);
  494. #endif
  495. #if !NDIS_NO_REGISTRY
  496. if (!NT_SUCCESS(NtStatus))
  497. break;
  498. //
  499. // 1.
  500. // Switch to the Linkage key below this driver instance key
  501. //
  502. LQueryTable[0].QueryRoutine = NULL;
  503. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  504. LQueryTable[0].Name = L"Linkage";
  505. //
  506. // 2.
  507. // Read the RootDevice keywords
  508. //
  509. LQueryTable[1].QueryRoutine = ndisReadParameter;
  510. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  511. LQueryTable[1].Name = L"RootDevice";
  512. LQueryTable[1].EntryContext = (PVOID)&BindPathData;
  513. LQueryTable[1].DefaultType = REG_NONE;
  514. LQueryTable[2].QueryRoutine = NULL;
  515. LQueryTable[2].Flags = 0;
  516. LQueryTable[2].Name = NULL;
  517. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  518. Handle,
  519. LQueryTable,
  520. NULL,
  521. NULL);
  522. ZwClose(Handle);
  523. if (!NT_SUCCESS(NtStatus))
  524. break;
  525. #else
  526. if (NT_SUCCESS(NtStatus))
  527. {
  528. //
  529. // 1.
  530. // Switch to the Linkage key below this driver instance key
  531. //
  532. LQueryTable[0].QueryRoutine = NULL;
  533. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  534. LQueryTable[0].Name = L"Linkage";
  535. //
  536. // 2.
  537. // Read the RootDevice keywords
  538. //
  539. LQueryTable[1].QueryRoutine = ndisReadParameter;
  540. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  541. LQueryTable[1].Name = L"RootDevice";
  542. LQueryTable[1].EntryContext = (PVOID)&BindPathData;
  543. LQueryTable[1].DefaultType = REG_NONE;
  544. LQueryTable[2].QueryRoutine = NULL;
  545. LQueryTable[2].Flags = 0;
  546. LQueryTable[2].Name = NULL;
  547. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  548. Handle,
  549. LQueryTable,
  550. NULL,
  551. NULL);
  552. ZwClose(Handle);
  553. if (!NT_SUCCESS(NtStatus))
  554. break;
  555. }
  556. else
  557. {
  558. NtStatus = STATUS_SUCCESS;
  559. }
  560. #endif
  561. //
  562. // BindPath is a MULTI-SZ which starts at the top of the filter chain
  563. // and goes down to the miniport. It is of the form
  564. //
  565. // {FN} {FN-1} ... {F1} {Adapter}
  566. //
  567. // Where spaces are actually nulls and each of {Fn} is a filter instance.
  568. //
  569. if (BindPathData == NULL)
  570. {
  571. BindPathData = Miniport->BaseName.Buffer;
  572. }
  573. else
  574. {
  575. FreeBindPathData = TRUE;
  576. }
  577. //
  578. // Split bindpath into individual components. Start by determining how much
  579. // space we need.
  580. //
  581. Len = sizeof(NDIS_BIND_PATHS);
  582. for (pPath = BindPathData, NumComponents = 0; *pPath != 0; NOTHING)
  583. {
  584. NDIS_STRING us;
  585. RtlInitUnicodeString(&us, pPath);
  586. NumComponents++;
  587. Len += sizeof(NDIS_STRING) + us.Length + ndisDeviceStr.Length + sizeof(WCHAR);
  588. (PUCHAR)pPath += (us.Length + sizeof(WCHAR));
  589. }
  590. //
  591. // Allocate space for bindpaths. We have NumComponents paths
  592. // which consume Len bytes of space. We could be re-initialzing
  593. // so free any previous buffer allcoated for this.
  594. //
  595. if (Miniport->BindPaths != NULL)
  596. {
  597. FREE_POOL(Miniport->BindPaths);
  598. }
  599. Miniport->BindPaths = (PNDIS_BIND_PATHS)ALLOC_FROM_POOL(Len,
  600. NDIS_TAG_NAME_BUF);
  601. if (Miniport->BindPaths == NULL)
  602. {
  603. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  604. break;
  605. }
  606. ZeroMemory(Miniport->BindPaths, Len);
  607. Miniport->BindPaths->Number = NumComponents;
  608. if (NumComponents > 1)
  609. {
  610. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_FILTER_IM);
  611. }
  612. //
  613. // Create an array in reverse order of device-names in the filter path.
  614. //
  615. p = (PWSTR)((PUCHAR)Miniport->BindPaths +
  616. sizeof(NDIS_BIND_PATHS) +
  617. NumComponents*sizeof(NDIS_STRING));
  618. for (pPath = BindPathData, i = (NumComponents-1);
  619. *pPath != 0;
  620. i --)
  621. {
  622. NDIS_STRING Str, SubStr, *Bp;
  623. RtlInitUnicodeString(&Str, pPath);
  624. (PUCHAR)pPath += (Str.Length + sizeof(WCHAR));
  625. Bp = &Miniport->BindPaths->Paths[i];
  626. Bp->Buffer = p;
  627. Bp->Length = 0;
  628. Bp->MaximumLength = Str.Length + ndisDeviceStr.Length + sizeof(WCHAR);
  629. SubStr.Buffer = (PWSTR)((PUCHAR)p + ndisDeviceStr.Length);
  630. SubStr.MaximumLength = Str.Length + sizeof(WCHAR);
  631. SubStr.Length = 0;
  632. RtlCopyUnicodeString(Bp, &ndisDeviceStr);
  633. RtlUpcaseUnicodeString(&SubStr,
  634. &Str,
  635. FALSE);
  636. Bp->Length += SubStr.Length;
  637. (PUCHAR)p += Bp->MaximumLength;
  638. }
  639. } while (FALSE);
  640. if (FreeBindPathData)
  641. FREE_POOL(BindPathData);
  642. ;
  643. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  644. ("<==ndisReadBindPaths: Miniport %p\n", Miniport));
  645. return NtStatus;
  646. }
  647. NTSTATUS
  648. ndisCreateAdapterInstanceName(
  649. OUT PUNICODE_STRING * pAdapterInstanceName,
  650. IN PDEVICE_OBJECT PhysicalDeviceObject
  651. )
  652. {
  653. NTSTATUS NtStatus, SlotQueryStatus;
  654. DEVICE_REGISTRY_PROPERTY Property;
  655. PWCHAR pValueInfo = NULL;
  656. ULONG ResultLength = 0;
  657. PUNICODE_STRING AdapterInstanceName = NULL;
  658. ULONG SlotNumber;
  659. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  660. ("==>ndisCreateAdapterInstanceName: PDO %p\n", PhysicalDeviceObject));
  661. do
  662. {
  663. *pAdapterInstanceName = NULL;
  664. Property = DevicePropertyFriendlyName;
  665. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  666. Property,
  667. 0,
  668. NULL,
  669. &ResultLength);
  670. if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus))
  671. {
  672. Property = DevicePropertyDeviceDescription;
  673. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  674. Property,
  675. 0,
  676. NULL,
  677. &ResultLength);
  678. if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus))
  679. {
  680. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  681. ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject));
  682. break;
  683. }
  684. }
  685. //
  686. // Allocate space to hold the partial value information.
  687. //
  688. pValueInfo = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_DEFAULT);
  689. if (NULL == pValueInfo)
  690. {
  691. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  692. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  693. ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter description\n", PhysicalDeviceObject));
  694. break;
  695. }
  696. RtlZeroMemory(pValueInfo, ResultLength);
  697. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  698. Property,
  699. ResultLength,
  700. pValueInfo,
  701. &ResultLength);
  702. if (!NT_SUCCESS(NtStatus))
  703. {
  704. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  705. ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject));
  706. break;
  707. }
  708. //
  709. // Determine the size of the instance name buffer. This is a UNICODE_STRING
  710. // and it's associated buffer.
  711. //
  712. ResultLength += sizeof(UNICODE_STRING);
  713. //
  714. // Allocate the buffer.
  715. //
  716. AdapterInstanceName = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_NAME_BUF);
  717. if (NULL == AdapterInstanceName)
  718. {
  719. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  720. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  721. ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter instance name\n", PhysicalDeviceObject));
  722. break;
  723. }
  724. //
  725. // Initialize the buffer.
  726. //
  727. RtlZeroMemory(AdapterInstanceName, ResultLength);
  728. //
  729. // Initialize the UNICODE_STRING for the instance name.
  730. //
  731. AdapterInstanceName->Buffer = (PWSTR)((PUCHAR)AdapterInstanceName + sizeof(UNICODE_STRING));
  732. AdapterInstanceName->Length = 0;
  733. AdapterInstanceName->MaximumLength = (USHORT)(ResultLength - sizeof(UNICODE_STRING));
  734. RtlAppendUnicodeToString(AdapterInstanceName, pValueInfo);
  735. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  736. ("ndisCreateAdapterInstanceName: %ws\n", AdapterInstanceName->Buffer));
  737. //
  738. // Return the instance name.
  739. //
  740. *pAdapterInstanceName = AdapterInstanceName;
  741. //
  742. // get the slot number
  743. //
  744. Property = DevicePropertyUINumber;
  745. SlotQueryStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  746. Property,
  747. sizeof (ULONG),
  748. &SlotNumber,
  749. &ResultLength);
  750. if (NT_SUCCESS(SlotQueryStatus))
  751. {
  752. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  753. ("ndisCreateAdapterInstanceName: %ws, Slot Number: %ld\n",
  754. AdapterInstanceName->Buffer,
  755. SlotNumber));
  756. }
  757. else
  758. {
  759. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  760. ("ndisCreateAdapterInstanceName: couldn't get SlotNumber for %ws\n",
  761. AdapterInstanceName->Buffer));
  762. }
  763. } while (FALSE);
  764. if (NULL != pValueInfo)
  765. FREE_POOL(pValueInfo);
  766. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  767. ("<==ndisCreateAdapterInstanceName: PDO %p, Status 0x%x\n", PhysicalDeviceObject, NtStatus));
  768. return(NtStatus);
  769. }
  770. NDIS_STATUS
  771. ndisInitializeAdapter(
  772. IN PNDIS_M_DRIVER_BLOCK pMiniBlock,
  773. IN PDEVICE_OBJECT DeviceObject,
  774. IN PUNICODE_STRING InstanceName,
  775. IN NDIS_HANDLE DeviceContext OPTIONAL
  776. )
  777. {
  778. NDIS_WRAPPER_CONFIGURATION_HANDLE ConfigurationHandle;
  779. NDIS_STATUS NdisStatus;
  780. UNICODE_STRING ExportName;
  781. NDIS_CONFIGURATION_HANDLE TmpConfigHandle;
  782. PNDIS_MINIPORT_BLOCK Miniport= (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  783. TIME TS, TE, TD;
  784. #define PQueryTable ConfigurationHandle.ParametersQueryTable
  785. #define Db ConfigurationHandle.Db
  786. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  787. ("==>ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport));
  788. do
  789. {
  790. ZeroMemory(&ConfigurationHandle, sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE));
  791. ExportName.Buffer = NULL;
  792. //
  793. // Build the configuration handle.
  794. //
  795. NdisStatus = ndisInitializeConfiguration(&ConfigurationHandle,
  796. Miniport,
  797. &ExportName);
  798. if (NdisStatus != NDIS_STATUS_SUCCESS)
  799. {
  800. break;
  801. }
  802. //
  803. // OK, Now lock down all the filter packages. If a MAC or
  804. // Miniport driver uses any of these, then the filter package
  805. // will reference itself, to keep the image in memory.
  806. //
  807. #if ARCNET
  808. ArcReferencePackage();
  809. #endif
  810. EthReferencePackage();
  811. FddiReferencePackage();
  812. TrReferencePackage();
  813. MiniportReferencePackage();
  814. CoReferencePackage();
  815. ConfigurationHandle.DeviceObject = DeviceObject;
  816. ConfigurationHandle.DriverBaseName = InstanceName;
  817. KeQuerySystemTime(&TS);
  818. //
  819. // Save the Driver Object with the configuration handle.
  820. //
  821. ConfigurationHandle.DriverObject = pMiniBlock->NdisDriverInfo->DriverObject;
  822. NdisStatus = ndisMInitializeAdapter(pMiniBlock,
  823. &ConfigurationHandle,
  824. &ExportName,
  825. DeviceContext);
  826. KeQuerySystemTime(&TE);
  827. TD.QuadPart = TE.QuadPart - TS.QuadPart;
  828. TD.QuadPart /= 10000; // Convert to ms
  829. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)(ConfigurationHandle.DeviceObject->DeviceExtension) + 1);
  830. Miniport->InitTimeMs = TD.LowPart;
  831. if (ndisFlags & NDIS_GFLAG_INIT_TIME)
  832. {
  833. DbgPrint("NDIS: Init time (%Z) %ld ms\n", Miniport->pAdapterInstanceName, Miniport->InitTimeMs);
  834. }
  835. if (NdisStatus != NDIS_STATUS_SUCCESS)
  836. {
  837. ndisCloseULongRef(&Miniport->Ref);
  838. }
  839. //
  840. // OK, Now dereference all the filter packages. If a MAC or
  841. // Miniport driver uses any of these, then the filter package
  842. // will reference itself, to keep the image in memory.
  843. //
  844. #if ARCNET
  845. ArcDereferencePackage();
  846. #endif
  847. EthDereferencePackage();
  848. FddiDereferencePackage();
  849. TrDereferencePackage();
  850. MiniportDereferencePackage();
  851. CoDereferencePackage();
  852. } while (FALSE);
  853. if (ExportName.Buffer)
  854. FREE_POOL(ExportName.Buffer);
  855. //
  856. // free "Bind" data
  857. //
  858. if (PQueryTable[3].EntryContext != NULL)
  859. FREE_POOL(PQueryTable[3].EntryContext);
  860. #undef PQueryTable
  861. #undef Db
  862. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  863. ("<==ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport));
  864. return(NdisStatus);
  865. }
  866. VOID
  867. FASTCALL
  868. ndisCheckAdapterBindings(
  869. IN PNDIS_MINIPORT_BLOCK Miniport,
  870. IN PNDIS_PROTOCOL_BLOCK Protocol OPTIONAL
  871. )
  872. /*+++
  873. Routine Description:
  874. This function, reads the registry to get all the protocols that are supposed
  875. to bind to this adapter and for each protocol, calls ndisInitializeBinding
  876. Arguments:
  877. Adapter Pointer to ndis Adpater or Miniport block
  878. Protocol Optionally if a protocol is specified, initiate binding to only
  879. that protocol
  880. Return Value:
  881. None
  882. ---*/
  883. {
  884. RTL_QUERY_REGISTRY_TABLE LinkQueryTable[3];
  885. NTSTATUS RegistryStatus;
  886. PWSTR UpperBind = NULL;
  887. HANDLE Handle;
  888. PDEVICE_OBJECT PhysicalDeviceObject;
  889. UNICODE_STRING Us;
  890. PWSTR CurProtocolName;
  891. PNDIS_PROTOCOL_BLOCK CurProtocol;
  892. NTSTATUS NtStatus;
  893. KIRQL OldIrql;
  894. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  895. ("==>ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol));
  896. do
  897. {
  898. //
  899. // get a handle to driver section in registry
  900. //
  901. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  902. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SECONDARY))
  903. {
  904. //
  905. // Skip bind notifications for a secondary miniport
  906. //
  907. break;
  908. }
  909. #if NDIS_TEST_REG_FAILURE
  910. RegistryStatus = STATUS_UNSUCCESSFUL;
  911. Handle = NULL;
  912. #else
  913. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  914. PLUGPLAY_REGKEY_DRIVER,
  915. GENERIC_READ | MAXIMUM_ALLOWED,
  916. &Handle);
  917. #endif
  918. #if NDIS_NO_REGISTRY
  919. if (!NT_SUCCESS(RegistryStatus))
  920. {
  921. if (ARGUMENT_PRESENT(Protocol))
  922. {
  923. ndisInitializeBinding(Miniport, Protocol);
  924. break;
  925. }
  926. else
  927. {
  928. for (CurProtocol = ndisProtocolList;
  929. CurProtocol != NULL;
  930. CurProtocol = CurProtocol->NextProtocol)
  931. {
  932. ndisInitializeBinding(Miniport, CurProtocol);
  933. }
  934. }
  935. break;
  936. }
  937. #else
  938. if (!NT_SUCCESS(RegistryStatus))
  939. {
  940. break;
  941. }
  942. #endif
  943. //
  944. // Set up LinkQueryTable to do the following:
  945. //
  946. //
  947. // 1) Switch to the Linkage key below the xports registry key
  948. //
  949. LinkQueryTable[0].QueryRoutine = NULL;
  950. LinkQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  951. LinkQueryTable[0].Name = L"Linkage";
  952. //
  953. // 2) Call ndisReadParameter for "UpperBind" (as a single multi-string),
  954. // which will allocate storage and save the data in UpperBind.
  955. //
  956. LinkQueryTable[1].QueryRoutine = ndisReadParameter;
  957. LinkQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  958. LinkQueryTable[1].Name = L"UpperBind";
  959. LinkQueryTable[1].EntryContext = (PVOID)&UpperBind;
  960. LinkQueryTable[1].DefaultType = REG_NONE;
  961. //
  962. // 3) Stop
  963. //
  964. LinkQueryTable[2].QueryRoutine = NULL;
  965. LinkQueryTable[2].Flags = 0;
  966. LinkQueryTable[2].Name = NULL;
  967. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  968. Handle,
  969. LinkQueryTable,
  970. (PVOID)NULL, // no context needed
  971. NULL);
  972. ZwClose(Handle);
  973. if (NT_SUCCESS(RegistryStatus))
  974. {
  975. for (CurProtocolName = UpperBind;
  976. *CurProtocolName != 0;
  977. CurProtocolName = (PWCHAR)((PUCHAR)CurProtocolName + Us.MaximumLength))
  978. {
  979. RtlInitUnicodeString (&Us, CurProtocolName);
  980. if (ARGUMENT_PRESENT(Protocol))
  981. {
  982. if (RtlEqualUnicodeString(&Us, &Protocol->ProtocolCharacteristics.Name, TRUE))
  983. {
  984. ndisInitializeBinding(Miniport, Protocol);
  985. break;
  986. }
  987. }
  988. else
  989. {
  990. for (CurProtocol = ndisProtocolList;
  991. CurProtocol != NULL;
  992. CurProtocol = CurProtocol->NextProtocol)
  993. {
  994. if (RtlEqualUnicodeString(&Us, &CurProtocol->ProtocolCharacteristics.Name, TRUE))
  995. {
  996. ndisInitializeBinding(Miniport, CurProtocol);
  997. break;
  998. }
  999. }
  1000. }
  1001. }
  1002. }
  1003. //
  1004. // Handle proxy and rca filters.
  1005. //
  1006. if ((Miniport != NULL) &&
  1007. !ndisMediaTypeCl[Miniport->MediaType] &&
  1008. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1009. {
  1010. if (ARGUMENT_PRESENT(Protocol))
  1011. {
  1012. if (Protocol->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO)
  1013. {
  1014. ndisInitializeBinding(Miniport, Protocol);
  1015. }
  1016. }
  1017. else
  1018. {
  1019. for (CurProtocol = ndisProtocolList;
  1020. CurProtocol != NULL;
  1021. CurProtocol = CurProtocol->NextProtocol)
  1022. {
  1023. if (CurProtocol->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO)
  1024. {
  1025. ndisInitializeBinding(Miniport, CurProtocol);
  1026. }
  1027. }
  1028. }
  1029. }
  1030. } while (FALSE);
  1031. if (UpperBind != NULL)
  1032. FREE_POOL(UpperBind);
  1033. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1034. ("<==ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol));
  1035. }
  1036. BOOLEAN
  1037. FASTCALL
  1038. ndisProtocolAlreadyBound(
  1039. IN PNDIS_PROTOCOL_BLOCK Protocol,
  1040. IN PNDIS_MINIPORT_BLOCK Miniport
  1041. )
  1042. {
  1043. PNDIS_OPEN_BLOCK pOpen;
  1044. BOOLEAN rc = FALSE;
  1045. KIRQL OldIrql;
  1046. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1047. ("==>ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport));
  1048. PnPReferencePackage();
  1049. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1050. for (pOpen = Protocol->OpenQueue;
  1051. pOpen != NULL;
  1052. pOpen = pOpen->ProtocolNextOpen)
  1053. {
  1054. if (pOpen->MiniportHandle == Miniport)
  1055. {
  1056. rc = TRUE;
  1057. break;
  1058. }
  1059. }
  1060. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1061. PnPDereferencePackage();
  1062. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1063. ("<==ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport));
  1064. return rc;
  1065. }
  1066. NDIS_STATUS
  1067. NdisIMInitializeDeviceInstance(
  1068. IN NDIS_HANDLE DriverHandle,
  1069. IN PNDIS_STRING DeviceInstance
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Initialize an instance of a miniport device.
  1074. Arguments:
  1075. DriverHandle - Handle returned by NdisMRegisterLayeredMiniport.
  1076. It is a pointer to NDIS_M_DRIVER_BLOCK.
  1077. DeviceInstance -Points to the instance of the driver that must now
  1078. be initialized.
  1079. Return Value:
  1080. --*/
  1081. {
  1082. NDIS_STATUS Status;
  1083. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1084. ("==>NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1085. Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, DeviceInstance, NULL);
  1086. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1087. ("<==NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1088. return Status;
  1089. }
  1090. NDIS_STATUS
  1091. NdisIMInitializeDeviceInstanceEx(
  1092. IN NDIS_HANDLE DriverHandle,
  1093. IN PNDIS_STRING DeviceInstance,
  1094. IN NDIS_HANDLE DeviceContext
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. Initialize an instance of a miniport device. Incarnation of NdisIMInitializeDeviceInstance.
  1099. Arguments:
  1100. DriverHandle Handle returned by NdisMRegisterLayeredMiniport.
  1101. It is a pointer to NDIS_M_DRIVER_BLOCK.
  1102. DeviceInstance Points to the instance of the driver that must now
  1103. be initialized.
  1104. DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext.
  1105. Return Value:
  1106. --*/
  1107. {
  1108. NDIS_STATUS Status;
  1109. PNDIS_M_DRIVER_BLOCK MiniBlock = (PNDIS_M_DRIVER_BLOCK)DriverHandle;
  1110. KIRQL OldIrql;
  1111. PNDIS_MINIPORT_BLOCK Miniport;
  1112. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1113. ("==>NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p\n",
  1114. DriverHandle, DeviceInstance, DeviceContext));
  1115. PnPReferencePackage();
  1116. WAIT_FOR_OBJECT(&MiniBlock->IMStartRemoveMutex, NULL);
  1117. do
  1118. {
  1119. Miniport = ndisFindMiniportOnGlobalList(DeviceInstance);
  1120. if (Miniport != NULL)
  1121. {
  1122. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_RECEIVED_START) &&
  1123. !MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REMOVE_IN_PROGRESS | fMINIPORT_PM_HALTED))
  1124. {
  1125. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1126. ("NdisIMInitializeDeviceInstanceEx: we have already received START_IRP for Miniport %p\n",
  1127. Miniport));
  1128. //
  1129. // check to make sure the miniport has not been initialized already
  1130. // i.e. we are not getting duplicate NdisIMInitializeDeviceInstance
  1131. // a device that has already been initialized
  1132. //
  1133. if (ndisIsMiniportStarted(Miniport))
  1134. {
  1135. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_ERR,
  1136. ("NdisIMInitializeDeviceInstanceEx: we have already initialized this device. Miniport %p\n",
  1137. Miniport));
  1138. Status = NDIS_STATUS_NOT_ACCEPTED;
  1139. break;
  1140. }
  1141. Status = ndisIMInitializeDeviceInstance(Miniport,
  1142. DeviceContext,
  1143. FALSE);
  1144. if (Status != NDIS_STATUS_SUCCESS)
  1145. {
  1146. //
  1147. // since we have already succeeded the START_IRP, signal PnP to remove this device
  1148. // by tagging the device as failed and requesting a QUERY_PNP_DEVICE_STATE IRP
  1149. //
  1150. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_FAILED);
  1151. IoInvalidateDeviceState(Miniport->PhysicalDeviceObject);
  1152. }
  1153. break;
  1154. }
  1155. }
  1156. //
  1157. // device is not started or not added yet.
  1158. //
  1159. Status = ndisIMQueueDeviceInstance(DriverHandle,
  1160. DeviceInstance,
  1161. DeviceContext);
  1162. } while (FALSE);
  1163. RELEASE_MUTEX(&MiniBlock->IMStartRemoveMutex);
  1164. PnPDereferencePackage();
  1165. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1166. ("<==NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p, Status %lx\n",
  1167. DriverHandle, DeviceInstance, DeviceContext, Status));
  1168. return Status;
  1169. }
  1170. NDIS_STATUS
  1171. ndisIMInitializeDeviceInstance(
  1172. IN PNDIS_MINIPORT_BLOCK Miniport,
  1173. IN NDIS_HANDLE DeviceContext,
  1174. IN BOOLEAN fStartIrp
  1175. )
  1176. /*++
  1177. Routine Description:
  1178. This routine is called when we have received NdisIMInitializeDeviceInstance
  1179. -AND- START IRP for an IM miniport.
  1180. Initialize an instance of a miniport device.
  1181. Arguments:
  1182. Miniport Handle to NDIS_MINIPORT_BLOCK
  1183. DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext.
  1184. fStartIrp flag to signal if we are in the context of handling START IRP
  1185. Return Value:
  1186. --*/
  1187. {
  1188. NDIS_STATUS Status;
  1189. NTSTATUS NtStatus;
  1190. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1191. ("==>ndisIMInitializeDeviceInstance: Miniport %p, Context %p, fStartIrp %lx\n", Miniport, DeviceContext, fStartIrp));
  1192. //
  1193. // it is quite possible we are dealing with a miniport block that has been "used"
  1194. // several times. inother words, it has been started and DeviceInitialized, then
  1195. // Device-De-Initialized and then has received a few query_stop and cancel_stop.
  1196. // in this case the miniport block has to be cleaned up. otherwise, ndisPnPStartDevice
  1197. // is not going to detect that miniport block needs re-initalization
  1198. //
  1199. ndisReinitializeMiniportBlock(Miniport);
  1200. Miniport->DeviceContext = DeviceContext;
  1201. Status = ndisPnPStartDevice(Miniport->DeviceObject, NULL); // no Irp
  1202. if (Status == NDIS_STATUS_SUCCESS)
  1203. {
  1204. //
  1205. // if we are in the context of start IRP, queue a workitem to initialize
  1206. // the bindings on this adapter to avoid the delay
  1207. //
  1208. if (!fStartIrp)
  1209. {
  1210. //
  1211. // Now set the device class association so that people can reference this.
  1212. //
  1213. NtStatus = IoSetDeviceInterfaceState(&Miniport->SymbolicLinkName, TRUE);
  1214. if (NT_SUCCESS(NtStatus))
  1215. {
  1216. //
  1217. // Do protocol notifications
  1218. //
  1219. ndisCheckAdapterBindings(Miniport, NULL);
  1220. }
  1221. else
  1222. {
  1223. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  1224. ("ndisCheckAdapterBindings: IoSetDeviceInterfaceState failed: Miniport %p, Status %lx\n", Miniport, NtStatus));
  1225. Status = NDIS_STATUS_FAILURE;
  1226. }
  1227. }
  1228. else
  1229. {
  1230. Status = ndisQueueBindWorkitem(Miniport);
  1231. }
  1232. }
  1233. else
  1234. {
  1235. //
  1236. // ndisPnPStartDevice can return an internal Error Code if the call
  1237. // to ndisMInitializeAdapter fails. convert this to NDIS_STATUS
  1238. //
  1239. Status = NDIS_STATUS_FAILURE;
  1240. }
  1241. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1242. ("<==ndisIMInitializeDeviceInstance: Miniport %p, Context %p, Status %lx\n", Miniport, DeviceContext, Status));
  1243. return Status;
  1244. }
  1245. NDIS_STATUS
  1246. ndisIMQueueDeviceInstance(
  1247. IN PNDIS_M_DRIVER_BLOCK MiniBlock,
  1248. IN PNDIS_STRING DeviceInstance,
  1249. IN NDIS_HANDLE DeviceContext
  1250. )
  1251. {
  1252. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1253. PNDIS_PENDING_IM_INSTANCE NewImInstance, pTemp;
  1254. KIRQL OldIrql;
  1255. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1256. ("==>ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p\n",
  1257. MiniBlock, DeviceInstance, DeviceContext));
  1258. do
  1259. {
  1260. //
  1261. // Queue the device name for which we have received an InitializeDeviceInstance
  1262. // from an IM driver. Check for duplicates.
  1263. //
  1264. NewImInstance = (PNDIS_PENDING_IM_INSTANCE)ALLOC_FROM_POOL(sizeof(NDIS_PENDING_IM_INSTANCE) +
  1265. DeviceInstance->Length +
  1266. sizeof(WCHAR),
  1267. NDIS_TAG_IM_DEVICE_INSTANCE);
  1268. if (NULL == NewImInstance)
  1269. {
  1270. Status = NDIS_STATUS_RESOURCES;
  1271. break;
  1272. }
  1273. NewImInstance->Context = DeviceContext;
  1274. NewImInstance->Name.MaximumLength = DeviceInstance->Length + sizeof(WCHAR);
  1275. NewImInstance->Name.Length = 0;
  1276. NewImInstance->Name.Buffer = (PWSTR)((PUCHAR)NewImInstance + sizeof(NDIS_PENDING_IM_INSTANCE));
  1277. RtlUpcaseUnicodeString(&NewImInstance->Name,
  1278. DeviceInstance,
  1279. FALSE);
  1280. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1281. for (pTemp = MiniBlock->PendingDeviceList;
  1282. pTemp != NULL;
  1283. pTemp = pTemp->Next)
  1284. {
  1285. if (NDIS_EQUAL_UNICODE_STRING(&NewImInstance->Name,
  1286. &pTemp->Name))
  1287. {
  1288. FREE_POOL(NewImInstance);
  1289. Status = NDIS_STATUS_NOT_ACCEPTED;
  1290. break;
  1291. }
  1292. }
  1293. if (Status == NDIS_STATUS_SUCCESS)
  1294. {
  1295. NewImInstance->Next = MiniBlock->PendingDeviceList;
  1296. MiniBlock->PendingDeviceList = NewImInstance;
  1297. }
  1298. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1299. } while (FALSE);
  1300. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1301. ("<==ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p, Status %lx\n",
  1302. MiniBlock, DeviceInstance, DeviceContext, Status));
  1303. return Status;
  1304. }
  1305. BOOLEAN
  1306. ndisIMCheckDeviceInstance(
  1307. IN PNDIS_M_DRIVER_BLOCK MiniBlock,
  1308. IN PUNICODE_STRING DeviceInstanceName,
  1309. OUT PNDIS_HANDLE DeviceContext OPTIONAL
  1310. )
  1311. {
  1312. PNDIS_PENDING_IM_INSTANCE pDI, *ppDI;
  1313. PNDIS_PROTOCOL_BLOCK Protocol = MiniBlock->AssociatedProtocol;
  1314. KIRQL OldIrql;
  1315. BOOLEAN rc = FALSE;
  1316. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1317. ("==>ndisIMCheckDeviceInstance: Driver %p, DeviceInstanceName %p\n",
  1318. MiniBlock, DeviceInstanceName));
  1319. PnPReferencePackage();
  1320. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1321. for (ppDI = &MiniBlock->PendingDeviceList;
  1322. (pDI = *ppDI) != NULL;
  1323. ppDI = &pDI->Next)
  1324. {
  1325. if (NDIS_EQUAL_UNICODE_STRING(&pDI->Name,
  1326. DeviceInstanceName))
  1327. {
  1328. if (ARGUMENT_PRESENT(DeviceContext))
  1329. {
  1330. *DeviceContext = pDI->Context;
  1331. }
  1332. *ppDI = pDI->Next;
  1333. FREE_POOL(pDI);
  1334. rc = TRUE;
  1335. break;
  1336. }
  1337. }
  1338. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1339. PnPDereferencePackage();
  1340. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1341. ("<==ndisIMCheckDeviceInstance: Driver %p, Name %p, Context %p\n",
  1342. MiniBlock, DeviceInstanceName, DeviceContext));
  1343. if (!rc && ARGUMENT_PRESENT(DeviceContext))
  1344. {
  1345. //
  1346. // Send a reconfig notification to the protocol associated with this IM
  1347. // so it can re-initialize any device(s) it wants to
  1348. //
  1349. if (((Protocol = MiniBlock->AssociatedProtocol) != NULL) &&
  1350. (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL))
  1351. {
  1352. //
  1353. // We got a start device for an IM. Make sure its protocol
  1354. // half has all the requisite bindings. This can happen
  1355. // if an IM is disconnected and reconnected, for example.
  1356. // Also give it a NULL reconfig event. ATMLANE uses that
  1357. //
  1358. NET_PNP_EVENT NetPnpEvent;
  1359. KEVENT Event;
  1360. NDIS_STATUS Status;
  1361. NdisZeroMemory(&NetPnpEvent, sizeof(NetPnpEvent));
  1362. INITIALIZE_EVENT(&Event);
  1363. NetPnpEvent.NetEvent = NetEventReconfigure;
  1364. PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent)->pEvent = &Event;
  1365. WAIT_FOR_PROTO_MUTEX(Protocol);
  1366. Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(NULL, &NetPnpEvent);
  1367. if (NDIS_STATUS_PENDING == Status)
  1368. {
  1369. //
  1370. // Wait for completion.
  1371. //
  1372. WAIT_FOR_PROTOCOL(Protocol, &Event);
  1373. }
  1374. RELEASE_PROT_MUTEX(Protocol);
  1375. }
  1376. }
  1377. return rc;
  1378. }
  1379. NDIS_STATUS
  1380. NdisIMCancelInitializeDeviceInstance(
  1381. IN NDIS_HANDLE DriverHandle,
  1382. IN PNDIS_STRING DeviceInstance
  1383. )
  1384. {
  1385. NDIS_STATUS Status;
  1386. UNICODE_STRING UpcaseDevice;
  1387. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1388. ("==>NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1389. //
  1390. // change to upper case
  1391. //
  1392. UpcaseDevice.Length = DeviceInstance->Length;
  1393. UpcaseDevice.MaximumLength = DeviceInstance->Length + sizeof(WCHAR);
  1394. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  1395. if (UpcaseDevice.Buffer == NULL)
  1396. {
  1397. return NDIS_STATUS_RESOURCES;
  1398. }
  1399. Status = RtlUpcaseUnicodeString(&UpcaseDevice, (PUNICODE_STRING)DeviceInstance, FALSE);
  1400. ASSERT (NT_SUCCESS(Status));
  1401. Status = (ndisIMCheckDeviceInstance((PNDIS_M_DRIVER_BLOCK)DriverHandle,
  1402. &UpcaseDevice,
  1403. NULL) == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
  1404. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1405. ("<==NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p, Status %lx\n",
  1406. DriverHandle, DeviceInstance, Status));
  1407. FREE_POOL(UpcaseDevice.Buffer);
  1408. return Status;
  1409. }
  1410. NDIS_HANDLE
  1411. NdisIMGetDeviceContext(
  1412. IN NDIS_HANDLE MiniportAdapterHandle
  1413. )
  1414. {
  1415. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1416. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1417. ("==>NdisIMGetDeviceContext: Miniport %p\n", Miniport));
  1418. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1419. ("<==NdisIMGetDeviceContext: Miniport %p\n", Miniport));
  1420. return(Miniport->DeviceContext);
  1421. }
  1422. NDIS_HANDLE
  1423. NdisIMGetBindingContext(
  1424. IN NDIS_HANDLE ProtocolBindingContext
  1425. )
  1426. {
  1427. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)ProtocolBindingContext;
  1428. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1429. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1430. ("==>NdisIMGetBindingContext: Open %p\n", Open));
  1431. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1432. ("<==NdisIMGetBindingContext: Open %p\n", Open));
  1433. return(Miniport->DeviceContext);
  1434. }