Leaked source code of windows server 2003
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.

1814 lines
61 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 PnPCapsStr = NDIS_STRING_CONST("PnPCapabilities");
  43. NDIS_STRING RemoteBootStr = NDIS_STRING_CONST("RemoteBootCard");
  44. NDIS_STRING PollMediaConnectivityStr = NDIS_STRING_CONST("RequiresMediaStatePoll");
  45. NDIS_STRING NdisDriverVerifyFlagsStr = NDIS_STRING_CONST("NdisDriverVerifyFlags");
  46. NDIS_STRING SGMapRegistersNeededStr = NDIS_STRING_CONST("SGMapRegistersNeeded");
  47. #ifdef NDIS_MEDIA_DISCONNECT_POWER_OFF
  48. NDIS_STRING MediaDisconnectTimeOutStr = NDIS_STRING_CONST("MediaDisconnectToSleepTimeOut");
  49. ULONG MediaDisconnectTimeOut = (ULONG)-1;
  50. #endif
  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 = (ULONG)-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. #ifdef NDIS_MEDIA_DISCONNECT_POWER_OFF
  386. //1 for .NET this is not supported, it should be ifdef'ed out
  387. //
  388. // read the value for media disconnect timer, set to 20 seconds if not present
  389. // default=disable pm when cable is disconnected
  390. //
  391. MediaDisconnectTimeOut = (ULONG)-1;
  392. NdisReadConfiguration(&NdisStatus,
  393. &ReturnedValue,
  394. &CnfgHandle,
  395. &MediaDisconnectTimeOutStr,
  396. NdisParameterHexInteger);
  397. if (NdisStatus == NDIS_STATUS_SUCCESS)
  398. {
  399. MediaDisconnectTimeOut = ReturnedValue->ParameterData.IntegerData;
  400. if (MediaDisconnectTimeOut == 0)
  401. {
  402. MediaDisconnectTimeOut = 1;
  403. }
  404. }
  405. Miniport->MediaDisconnectTimeOut = (USHORT)MediaDisconnectTimeOut;
  406. if (MediaDisconnectTimeOut == (ULONG)(-1))
  407. {
  408. Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT;
  409. }
  410. #else
  411. Miniport->MediaDisconnectTimeOut = (USHORT)-1;
  412. Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT;
  413. #endif
  414. //1 this (media polling) is not needed any more.
  415. NdisReadConfiguration(&NdisStatus,
  416. &ReturnedValue,
  417. &CnfgHandle,
  418. &PollMediaConnectivityStr,
  419. NdisParameterInteger);
  420. if (NdisStatus == NDIS_STATUS_SUCCESS)
  421. {
  422. //
  423. // This miniport wants Ndis to poll it regularly for media connectivity.
  424. // Default value is FALSE for this flag. This flag will be cleared if miniport
  425. // can indicate media status or does not support media query
  426. //
  427. if (ReturnedValue->ParameterData.IntegerData == 1)
  428. {
  429. MINIPORT_SET_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING);
  430. }
  431. }
  432. //1 check for range
  433. NdisReadConfiguration(&NdisStatus,
  434. &ReturnedValue,
  435. &CnfgHandle,
  436. &SGMapRegistersNeededStr,
  437. NdisParameterInteger);
  438. if (NdisStatus == NDIS_STATUS_SUCCESS)
  439. {
  440. Miniport->SGMapRegistersNeeded = (USHORT)ReturnedValue->ParameterData.IntegerData;
  441. }
  442. else
  443. {
  444. Miniport->SGMapRegistersNeeded = NDIS_MAXIMUM_SCATTER_GATHER_SEGMENTS;
  445. }
  446. NdisReadConfiguration(&NdisStatus,
  447. &ReturnedValue,
  448. &CnfgHandle,
  449. &NdisDriverVerifyFlagsStr,
  450. NdisParameterHexInteger);
  451. if (NdisStatus == NDIS_STATUS_SUCCESS)
  452. {
  453. Miniport->DriverVerifyFlags = ReturnedValue->ParameterData.IntegerData;
  454. }
  455. PQueryTable[3].DefaultData = NULL;
  456. PQueryTable[3].Flags = 0;
  457. NdisStatus = NDIS_STATUS_SUCCESS;
  458. } while (FALSE);
  459. //
  460. // free NDIS_CONFIGURATION_PARAMETER_QUEUE nodes hanging from CnfgHandle
  461. //
  462. ParameterNode = CnfgHandle.ParameterList;
  463. while (ParameterNode != NULL)
  464. {
  465. CnfgHandle.ParameterList = ParameterNode->Next;
  466. FREE_POOL(ParameterNode);
  467. ParameterNode = CnfgHandle.ParameterList;
  468. }
  469. #undef PQueryTable
  470. #undef LQueryTable
  471. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  472. ("<==ndisInitializeConfiguration: Miniport %p\n", Miniport));
  473. return(NdisStatus);
  474. }
  475. NTSTATUS
  476. ndisReadBindPaths(
  477. IN PNDIS_MINIPORT_BLOCK Miniport,
  478. IN PRTL_QUERY_REGISTRY_TABLE LQueryTable
  479. )
  480. /*++
  481. Routine Description:
  482. Arguments:
  483. Return Value:
  484. --*/
  485. {
  486. NTSTATUS NtStatus;
  487. HANDLE Handle = NULL;
  488. PWSTR pPath, p, BindPathData = NULL;
  489. UINT i, Len, NumComponents;
  490. BOOLEAN FreeBindPathData = FALSE;
  491. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  492. ("==>ndisReadBindPaths: Miniport %p\n", Miniport));
  493. do
  494. {
  495. #if NDIS_TEST_REG_FAILURE
  496. NtStatus = STATUS_UNSUCCESSFUL;
  497. #else
  498. NtStatus = IoOpenDeviceRegistryKey(Miniport->PhysicalDeviceObject,
  499. PLUGPLAY_REGKEY_DRIVER,
  500. GENERIC_READ | MAXIMUM_ALLOWED,
  501. &Handle);
  502. #endif
  503. #if !NDIS_NO_REGISTRY
  504. if (!NT_SUCCESS(NtStatus))
  505. break;
  506. //
  507. // 1.
  508. // Switch to the Linkage key below this driver instance key
  509. //
  510. LQueryTable[0].QueryRoutine = NULL;
  511. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  512. LQueryTable[0].Name = L"Linkage";
  513. //
  514. // 2.
  515. // Read the RootDevice keywords
  516. //
  517. LQueryTable[1].QueryRoutine = ndisReadParameter;
  518. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  519. LQueryTable[1].Name = L"RootDevice";
  520. LQueryTable[1].EntryContext = (PVOID)&BindPathData;
  521. LQueryTable[1].DefaultType = REG_NONE;
  522. LQueryTable[2].QueryRoutine = NULL;
  523. LQueryTable[2].Flags = 0;
  524. LQueryTable[2].Name = NULL;
  525. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  526. Handle,
  527. LQueryTable,
  528. NULL,
  529. NULL);
  530. ZwClose(Handle);
  531. if (!NT_SUCCESS(NtStatus))
  532. {
  533. break;
  534. }
  535. #else
  536. if (NT_SUCCESS(NtStatus))
  537. {
  538. //
  539. // 1.
  540. // Switch to the Linkage key below this driver instance key
  541. //
  542. LQueryTable[0].QueryRoutine = NULL;
  543. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  544. LQueryTable[0].Name = L"Linkage";
  545. //
  546. // 2.
  547. // Read the RootDevice keywords
  548. //
  549. LQueryTable[1].QueryRoutine = ndisReadParameter;
  550. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  551. LQueryTable[1].Name = L"RootDevice";
  552. LQueryTable[1].EntryContext = (PVOID)&BindPathData;
  553. LQueryTable[1].DefaultType = REG_NONE;
  554. LQueryTable[2].QueryRoutine = NULL;
  555. LQueryTable[2].Flags = 0;
  556. LQueryTable[2].Name = NULL;
  557. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  558. Handle,
  559. LQueryTable,
  560. NULL,
  561. NULL);
  562. ZwClose(Handle);
  563. if (!NT_SUCCESS(NtStatus))
  564. break;
  565. }
  566. else
  567. {
  568. NtStatus = STATUS_SUCCESS;
  569. }
  570. #endif
  571. //
  572. // BindPath is a MULTI-SZ which starts at the top of the filter chain
  573. // and goes down to the miniport. It is of the form
  574. //
  575. // {FN} {FN-1} ... {F1} {Adapter}
  576. //
  577. // Where spaces are actually nulls and each of {Fn} is a filter instance.
  578. //
  579. if (BindPathData == NULL)
  580. {
  581. BindPathData = Miniport->BaseName.Buffer;
  582. }
  583. else
  584. {
  585. FreeBindPathData = TRUE;
  586. }
  587. //
  588. // Split bindpath into individual components. Start by determining how much
  589. // space we need.
  590. //
  591. Len = sizeof(NDIS_BIND_PATHS);
  592. for (pPath = BindPathData, NumComponents = 0; *pPath != 0; NOTHING)
  593. {
  594. NDIS_STRING us;
  595. RtlInitUnicodeString(&us, pPath);
  596. NumComponents++;
  597. Len += sizeof(NDIS_STRING) + us.Length + ndisDeviceStr.Length + sizeof(WCHAR);
  598. (PUCHAR)pPath += (us.Length + sizeof(WCHAR));
  599. }
  600. //
  601. // Allocate space for bindpaths. We have NumComponents paths
  602. // which consume Len bytes of space. We could be re-initialzing
  603. // so free any previous buffer allcoated for this.
  604. //
  605. if (Miniport->BindPaths != NULL)
  606. {
  607. FREE_POOL(Miniport->BindPaths);
  608. }
  609. Miniport->BindPaths = (PNDIS_BIND_PATHS)ALLOC_FROM_POOL(Len,
  610. NDIS_TAG_NAME_BUF);
  611. if (Miniport->BindPaths == NULL)
  612. {
  613. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  614. break;
  615. }
  616. ZeroMemory(Miniport->BindPaths, Len);
  617. Miniport->BindPaths->Number = NumComponents;
  618. if (NumComponents > 1)
  619. {
  620. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_FILTER_IM);
  621. Miniport->InfoFlags |= NDIS_MINIPORT_FILTER_IM;
  622. }
  623. //
  624. // Create an array in reverse order of device-names in the filter path.
  625. //
  626. p = (PWSTR)((PUCHAR)Miniport->BindPaths +
  627. sizeof(NDIS_BIND_PATHS) +
  628. NumComponents*sizeof(NDIS_STRING));
  629. for (pPath = BindPathData, i = (NumComponents-1);
  630. *pPath != 0;
  631. i --)
  632. {
  633. NDIS_STRING Str, SubStr, *Bp;
  634. RtlInitUnicodeString(&Str, pPath);
  635. (PUCHAR)pPath += (Str.Length + sizeof(WCHAR));
  636. Bp = &Miniport->BindPaths->Paths[i];
  637. Bp->Buffer = p;
  638. Bp->Length = 0;
  639. Bp->MaximumLength = Str.Length + ndisDeviceStr.Length + sizeof(WCHAR);
  640. SubStr.Buffer = (PWSTR)((PUCHAR)p + ndisDeviceStr.Length);
  641. SubStr.MaximumLength = Str.Length + sizeof(WCHAR);
  642. SubStr.Length = 0;
  643. RtlCopyUnicodeString(Bp, &ndisDeviceStr);
  644. RtlUpcaseUnicodeString(&SubStr,
  645. &Str,
  646. FALSE);
  647. Bp->Length += SubStr.Length;
  648. (PUCHAR)p += Bp->MaximumLength;
  649. }
  650. } while (FALSE);
  651. if (FreeBindPathData)
  652. FREE_POOL(BindPathData);
  653. ;
  654. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  655. ("<==ndisReadBindPaths: Miniport %p\n", Miniport));
  656. return NtStatus;
  657. }
  658. NTSTATUS
  659. ndisCreateAdapterInstanceName(
  660. OUT PUNICODE_STRING * pAdapterInstanceName,
  661. IN PDEVICE_OBJECT PhysicalDeviceObject
  662. )
  663. {
  664. NTSTATUS NtStatus, SlotQueryStatus;
  665. DEVICE_REGISTRY_PROPERTY Property;
  666. PWCHAR pValueInfo = NULL;
  667. ULONG ResultLength = 0;
  668. PUNICODE_STRING AdapterInstanceName = NULL;
  669. ULONG SlotNumber;
  670. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  671. ("==>ndisCreateAdapterInstanceName: PDO %p\n", PhysicalDeviceObject));
  672. do
  673. {
  674. //1 add comments and check to see if the DevicePropertyFriendlyName should always be there.
  675. *pAdapterInstanceName = NULL;
  676. Property = DevicePropertyFriendlyName;
  677. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  678. Property,
  679. 0,
  680. NULL,
  681. &ResultLength);
  682. if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus))
  683. {
  684. Property = DevicePropertyDeviceDescription;
  685. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  686. Property,
  687. 0,
  688. NULL,
  689. &ResultLength);
  690. if ((NtStatus != STATUS_BUFFER_TOO_SMALL) && !NT_SUCCESS(NtStatus))
  691. {
  692. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  693. ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject));
  694. break;
  695. }
  696. }
  697. //
  698. // Allocate space to hold the partial value information.
  699. //
  700. pValueInfo = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_DEFAULT);
  701. if (NULL == pValueInfo)
  702. {
  703. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  704. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  705. ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter description\n", PhysicalDeviceObject));
  706. break;
  707. }
  708. RtlZeroMemory(pValueInfo, ResultLength);
  709. NtStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  710. Property,
  711. ResultLength,
  712. pValueInfo,
  713. &ResultLength);
  714. if (!NT_SUCCESS(NtStatus))
  715. {
  716. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  717. ("ndisCreateAdapterInstanceName: PDO %p, Failed to query the adapter description\n", PhysicalDeviceObject));
  718. break;
  719. }
  720. //
  721. // Determine the size of the instance name buffer. This is a UNICODE_STRING
  722. // and it's associated buffer.
  723. //
  724. ResultLength += sizeof(UNICODE_STRING);
  725. //
  726. // Allocate the buffer.
  727. //
  728. AdapterInstanceName = ALLOC_FROM_POOL(ResultLength, NDIS_TAG_NAME_BUF);
  729. if (NULL == AdapterInstanceName)
  730. {
  731. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  732. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  733. ("ndisCreateAdapterInstanceName: PDO %p, Failed to allocate storage for the adapter instance name\n", PhysicalDeviceObject));
  734. break;
  735. }
  736. //
  737. // Initialize the buffer.
  738. //
  739. RtlZeroMemory(AdapterInstanceName, ResultLength);
  740. //
  741. // Initialize the UNICODE_STRING for the instance name.
  742. //
  743. AdapterInstanceName->Buffer = (PWSTR)((PUCHAR)AdapterInstanceName + sizeof(UNICODE_STRING));
  744. AdapterInstanceName->Length = 0;
  745. AdapterInstanceName->MaximumLength = (USHORT)(ResultLength - sizeof(UNICODE_STRING));
  746. RtlAppendUnicodeToString(AdapterInstanceName, pValueInfo);
  747. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  748. ("ndisCreateAdapterInstanceName: %ws\n", AdapterInstanceName->Buffer));
  749. //
  750. // Return the instance name.
  751. //
  752. *pAdapterInstanceName = AdapterInstanceName;
  753. //1 this should be in checked builds only.
  754. //
  755. // get the slot number
  756. //
  757. Property = DevicePropertyUINumber;
  758. SlotQueryStatus = IoGetDeviceProperty(PhysicalDeviceObject,
  759. Property,
  760. sizeof (ULONG),
  761. &SlotNumber,
  762. &ResultLength);
  763. if (NT_SUCCESS(SlotQueryStatus))
  764. {
  765. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  766. ("ndisCreateAdapterInstanceName: %ws, Slot Number: %ld\n",
  767. AdapterInstanceName->Buffer,
  768. SlotNumber));
  769. }
  770. else
  771. {
  772. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  773. ("ndisCreateAdapterInstanceName: couldn't get SlotNumber for %ws\n",
  774. AdapterInstanceName->Buffer));
  775. }
  776. } while (FALSE);
  777. if (NULL != pValueInfo)
  778. FREE_POOL(pValueInfo);
  779. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  780. ("<==ndisCreateAdapterInstanceName: PDO %p, Status 0x%x\n", PhysicalDeviceObject, NtStatus));
  781. return(NtStatus);
  782. }
  783. NDIS_STATUS
  784. ndisInitializeAdapter(
  785. IN PNDIS_M_DRIVER_BLOCK pMiniBlock,
  786. IN PDEVICE_OBJECT DeviceObject,
  787. IN PUNICODE_STRING InstanceName,
  788. IN NDIS_HANDLE DeviceContext OPTIONAL
  789. )
  790. {
  791. NDIS_WRAPPER_CONFIGURATION_HANDLE ConfigurationHandle;
  792. NDIS_STATUS NdisStatus;
  793. UNICODE_STRING ExportName;
  794. PNDIS_MINIPORT_BLOCK Miniport= (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  795. TIME TS, TE, TD;
  796. #define PQueryTable ConfigurationHandle.ParametersQueryTable
  797. #define Db ConfigurationHandle.Db
  798. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  799. ("==>ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport));
  800. do
  801. {
  802. ZeroMemory(&ConfigurationHandle, sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE));
  803. ExportName.Buffer = NULL;
  804. //
  805. // Build the configuration handle.
  806. //
  807. NdisStatus = ndisInitializeConfiguration(&ConfigurationHandle,
  808. Miniport,
  809. &ExportName);
  810. if (NdisStatus != NDIS_STATUS_SUCCESS)
  811. {
  812. break;
  813. }
  814. //
  815. // OK, Now lock down all the filter packages. If a MAC or
  816. // Miniport driver uses any of these, then the filter package
  817. // will reference itself, to keep the image in memory.
  818. //
  819. #if ARCNET
  820. ArcReferencePackage();
  821. #endif
  822. EthReferencePackage();
  823. FddiReferencePackage();
  824. TrReferencePackage();
  825. MiniportReferencePackage();
  826. CoReferencePackage();
  827. ConfigurationHandle.DeviceObject = DeviceObject;
  828. ConfigurationHandle.DriverBaseName = InstanceName;
  829. KeQuerySystemTime(&TS);
  830. //
  831. // Save the Driver Object with the configuration handle.
  832. //
  833. ConfigurationHandle.DriverObject = pMiniBlock->NdisDriverInfo->DriverObject;
  834. NdisStatus = ndisMInitializeAdapter(pMiniBlock,
  835. &ConfigurationHandle,
  836. &ExportName,
  837. DeviceContext);
  838. KeQuerySystemTime(&TE);
  839. TD.QuadPart = TE.QuadPart - TS.QuadPart;
  840. TD.QuadPart /= 10000; // Convert to ms
  841. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)(ConfigurationHandle.DeviceObject->DeviceExtension) + 1);
  842. Miniport->InitTimeMs = TD.LowPart;
  843. if (ndisFlags & NDIS_GFLAG_INIT_TIME)
  844. {
  845. DbgPrint("NDIS: Init time (%Z) %ld ms\n", Miniport->pAdapterInstanceName, Miniport->InitTimeMs);
  846. }
  847. if (NdisStatus != NDIS_STATUS_SUCCESS)
  848. {
  849. ndisCloseULongRef(&Miniport->Ref);
  850. }
  851. //
  852. // OK, Now dereference all the filter packages. If a MAC or
  853. // Miniport driver uses any of these, then the filter package
  854. // will reference itself, to keep the image in memory.
  855. //
  856. #if ARCNET
  857. ArcDereferencePackage();
  858. #endif
  859. EthDereferencePackage();
  860. FddiDereferencePackage();
  861. TrDereferencePackage();
  862. MiniportDereferencePackage();
  863. CoDereferencePackage();
  864. } while (FALSE);
  865. if (ExportName.Buffer)
  866. FREE_POOL(ExportName.Buffer);
  867. //
  868. // free "Bind" data
  869. //
  870. if (PQueryTable[3].EntryContext != NULL)
  871. FREE_POOL(PQueryTable[3].EntryContext);
  872. #undef PQueryTable
  873. #undef Db
  874. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  875. ("<==ndisInitializeAdapter: Miniport/Adapter %p\n", Miniport));
  876. return(NdisStatus);
  877. }
  878. VOID
  879. FASTCALL
  880. ndisCheckAdapterBindings(
  881. IN PNDIS_MINIPORT_BLOCK Miniport,
  882. IN PNDIS_PROTOCOL_BLOCK Protocol OPTIONAL
  883. )
  884. /*+++
  885. Routine Description:
  886. This function, reads the registry to get all the protocols that are supposed
  887. to bind to this adapter and for each protocol, calls ndisInitializeBinding
  888. Arguments:
  889. Adapter Pointer to ndis Adpater or Miniport block
  890. Protocol Optionally if a protocol is specified, initiate binding to only
  891. that protocol
  892. Return Value:
  893. None
  894. ---*/
  895. {
  896. RTL_QUERY_REGISTRY_TABLE LinkQueryTable[3];
  897. NTSTATUS RegistryStatus;
  898. PWSTR UpperBind = NULL;
  899. HANDLE Handle;
  900. PDEVICE_OBJECT PhysicalDeviceObject;
  901. UNICODE_STRING Us;
  902. PWSTR CurProtocolName;
  903. PNDIS_PROTOCOL_BLOCK CurProtocol, NextProtocol;
  904. KIRQL OldIrql;
  905. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  906. ("==>ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol));
  907. do
  908. {
  909. //
  910. // get a handle to driver section in registry
  911. //
  912. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  913. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SECONDARY))
  914. {
  915. //
  916. // Skip bind notifications for a secondary miniport
  917. //
  918. break;
  919. }
  920. #if NDIS_TEST_REG_FAILURE
  921. RegistryStatus = STATUS_UNSUCCESSFUL;
  922. Handle = NULL;
  923. #else
  924. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  925. PLUGPLAY_REGKEY_DRIVER,
  926. GENERIC_READ | MAXIMUM_ALLOWED,
  927. &Handle);
  928. #endif
  929. #if NDIS_NO_REGISTRY
  930. if (!NT_SUCCESS(RegistryStatus))
  931. {
  932. if (ARGUMENT_PRESENT(Protocol))
  933. {
  934. ndisInitializeBinding(Miniport, Protocol);
  935. break;
  936. }
  937. else
  938. {
  939. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  940. for (CurProtocol = ndisProtocolList;
  941. CurProtocol != NULL;
  942. CurProtocol = NextProtocol)
  943. {
  944. if (ndisReferenceProtocol(CurProtocol))
  945. {
  946. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  947. ndisInitializeBinding(Miniport, CurProtocol);
  948. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  949. NextProtocol = CurProtocol->NextProtocol;
  950. ndisDereferenceProtocol(CurProtocol, TRUE);
  951. }
  952. else
  953. {
  954. NextProtocol = CurProtocol->NextProtocol;
  955. }
  956. }
  957. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  958. }
  959. break;
  960. }
  961. #else
  962. if (!NT_SUCCESS(RegistryStatus))
  963. {
  964. break;
  965. }
  966. #endif
  967. //
  968. // Set up LinkQueryTable to do the following:
  969. //
  970. //
  971. // 1) Switch to the Linkage key below the xports registry key
  972. //
  973. LinkQueryTable[0].QueryRoutine = NULL;
  974. LinkQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  975. LinkQueryTable[0].Name = L"Linkage";
  976. //
  977. // 2) Call ndisReadParameter for "UpperBind" (as a single multi-string),
  978. // which will allocate storage and save the data in UpperBind.
  979. //
  980. LinkQueryTable[1].QueryRoutine = ndisReadParameter;
  981. LinkQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  982. LinkQueryTable[1].Name = L"UpperBind";
  983. LinkQueryTable[1].EntryContext = (PVOID)&UpperBind;
  984. LinkQueryTable[1].DefaultType = REG_NONE;
  985. //
  986. // 3) Stop
  987. //
  988. LinkQueryTable[2].QueryRoutine = NULL;
  989. LinkQueryTable[2].Flags = 0;
  990. LinkQueryTable[2].Name = NULL;
  991. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  992. Handle,
  993. LinkQueryTable,
  994. (PVOID)NULL, // no context needed
  995. NULL);
  996. ZwClose(Handle);
  997. if (NT_SUCCESS(RegistryStatus))
  998. {
  999. for (CurProtocolName = UpperBind;
  1000. *CurProtocolName != 0;
  1001. CurProtocolName = (PWCHAR)((PUCHAR)CurProtocolName + Us.MaximumLength))
  1002. {
  1003. RtlInitUnicodeString (&Us, CurProtocolName);
  1004. if (ARGUMENT_PRESENT(Protocol))
  1005. {
  1006. if (RtlEqualUnicodeString(&Us, &Protocol->ProtocolCharacteristics.Name, TRUE))
  1007. {
  1008. ndisInitializeBinding(Miniport, Protocol);
  1009. break;
  1010. }
  1011. }
  1012. else
  1013. {
  1014. CurProtocol = NULL;
  1015. if (ndisReferenceProtocolByName(&Us, &CurProtocol, FALSE) == NDIS_STATUS_SUCCESS)
  1016. {
  1017. ndisInitializeBinding(Miniport, CurProtocol);
  1018. ndisDereferenceProtocol(CurProtocol, FALSE);
  1019. }
  1020. }
  1021. }
  1022. }
  1023. //
  1024. // Handle proxy and rca filters.
  1025. //
  1026. if ((Miniport != NULL) &&
  1027. !ndisMediaTypeCl[Miniport->MediaType] &&
  1028. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1029. {
  1030. BOOLEAN bCanMiniportBindtoAllCoProtocol = FALSE;
  1031. if (ARGUMENT_PRESENT(Protocol))
  1032. {
  1033. //
  1034. // Only create the binding between the bind_all_Co protocol if the miniport
  1035. // does not veto it
  1036. //
  1037. bCanMiniportBindtoAllCoProtocol = \
  1038. ((Protocol->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO) &&
  1039. (!(Miniport->MiniportAttributes & NDIS_ATTRIBUTE_DO_NOT_BIND_TO_ALL_CO )));
  1040. if (bCanMiniportBindtoAllCoProtocol)
  1041. {
  1042. ndisInitializeBinding(Miniport, Protocol);
  1043. }
  1044. }
  1045. else
  1046. {
  1047. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  1048. for (CurProtocol = ndisProtocolList;
  1049. CurProtocol != NULL;
  1050. CurProtocol = NextProtocol)
  1051. {
  1052. bCanMiniportBindtoAllCoProtocol = \
  1053. ((CurProtocol ->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_BIND_ALL_CO) &&
  1054. (!(Miniport->MiniportAttributes & NDIS_ATTRIBUTE_DO_NOT_BIND_TO_ALL_CO )));
  1055. if (bCanMiniportBindtoAllCoProtocol &&
  1056. ndisReferenceProtocol(CurProtocol))
  1057. {
  1058. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  1059. ndisInitializeBinding(Miniport, CurProtocol);
  1060. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  1061. NextProtocol = CurProtocol->NextProtocol;
  1062. ndisDereferenceProtocol(CurProtocol, TRUE);
  1063. }
  1064. else
  1065. {
  1066. NextProtocol = CurProtocol->NextProtocol;
  1067. }
  1068. }
  1069. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  1070. }
  1071. }
  1072. } while (FALSE);
  1073. if (UpperBind != NULL)
  1074. FREE_POOL(UpperBind);
  1075. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1076. ("<==ndisCheckAdapterBindings: Miniport %p, Protocol %p\n", Miniport, Protocol));
  1077. }
  1078. BOOLEAN
  1079. FASTCALL
  1080. ndisProtocolAlreadyBound(
  1081. IN PNDIS_PROTOCOL_BLOCK Protocol,
  1082. IN PNDIS_MINIPORT_BLOCK Miniport
  1083. )
  1084. {
  1085. PNDIS_OPEN_BLOCK pOpen;
  1086. BOOLEAN rc = FALSE;
  1087. KIRQL OldIrql;
  1088. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1089. ("==>ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport));
  1090. PnPReferencePackage();
  1091. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1092. for (pOpen = Protocol->OpenQueue;
  1093. pOpen != NULL;
  1094. pOpen = pOpen->ProtocolNextOpen)
  1095. {
  1096. if (pOpen->MiniportHandle == Miniport)
  1097. {
  1098. rc = TRUE;
  1099. break;
  1100. }
  1101. }
  1102. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1103. PnPDereferencePackage();
  1104. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1105. ("<==ndisProtocolAlreadyBound: Protocol %p, Miniport %p\n", Protocol, Miniport));
  1106. return rc;
  1107. }
  1108. NDIS_STATUS
  1109. NdisIMInitializeDeviceInstance(
  1110. IN NDIS_HANDLE DriverHandle,
  1111. IN PNDIS_STRING DeviceInstance
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. Initialize an instance of a miniport device.
  1116. Arguments:
  1117. DriverHandle - Handle returned by NdisMRegisterLayeredMiniport.
  1118. It is a pointer to NDIS_M_DRIVER_BLOCK.
  1119. DeviceInstance -Points to the instance of the driver that must now
  1120. be initialized.
  1121. Return Value:
  1122. --*/
  1123. {
  1124. NDIS_STATUS Status;
  1125. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1126. ("==>NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1127. Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, DeviceInstance, NULL);
  1128. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1129. ("<==NdisIMInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1130. return Status;
  1131. }
  1132. NDIS_STATUS
  1133. NdisIMInitializeDeviceInstanceEx(
  1134. IN NDIS_HANDLE DriverHandle,
  1135. IN PNDIS_STRING DeviceInstance,
  1136. IN NDIS_HANDLE DeviceContext
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. Initialize an instance of a miniport device. Incarnation of NdisIMInitializeDeviceInstance.
  1141. Arguments:
  1142. DriverHandle Handle returned by NdisMRegisterLayeredMiniport.
  1143. It is a pointer to NDIS_M_DRIVER_BLOCK.
  1144. DeviceInstance Points to the instance of the driver that must now
  1145. be initialized.
  1146. DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext.
  1147. Return Value:
  1148. --*/
  1149. {
  1150. NDIS_STATUS Status;
  1151. PNDIS_M_DRIVER_BLOCK MiniBlock = (PNDIS_M_DRIVER_BLOCK)DriverHandle;
  1152. PNDIS_MINIPORT_BLOCK Miniport;
  1153. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1154. ("==>NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p\n",
  1155. DriverHandle, DeviceInstance, DeviceContext));
  1156. PnPReferencePackage();
  1157. WAIT_FOR_OBJECT(&MiniBlock->IMStartRemoveMutex, NULL);
  1158. do
  1159. {
  1160. Miniport = ndisFindMiniportOnGlobalList(DeviceInstance);
  1161. //1 we need some protection so miniport does not go away. (Should ref the miniport)
  1162. if (Miniport != NULL)
  1163. {
  1164. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_RECEIVED_START) &&
  1165. !MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REMOVE_IN_PROGRESS | fMINIPORT_PM_HALTED))
  1166. {
  1167. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1168. ("NdisIMInitializeDeviceInstanceEx: we have already received START_IRP for Miniport %p\n",
  1169. Miniport));
  1170. //
  1171. // check to make sure the miniport has not been initialized already
  1172. // i.e. we are not getting duplicate NdisIMInitializeDeviceInstance
  1173. // a device that has already been initialized
  1174. //
  1175. if (ndisIsMiniportStarted(Miniport))
  1176. {
  1177. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_ERR,
  1178. ("NdisIMInitializeDeviceInstanceEx: we have already initialized this device. Miniport %p\n",
  1179. Miniport));
  1180. Status = NDIS_STATUS_NOT_ACCEPTED;
  1181. break;
  1182. }
  1183. Status = ndisIMInitializeDeviceInstance(Miniport,
  1184. DeviceContext,
  1185. FALSE);
  1186. if (Status != NDIS_STATUS_SUCCESS)
  1187. {
  1188. //
  1189. // since we have already succeeded the START_IRP, signal PnP to remove this device
  1190. // by tagging the device as failed and requesting a QUERY_PNP_DEVICE_STATE IRP
  1191. //
  1192. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_FAILED);
  1193. IoInvalidateDeviceState(Miniport->PhysicalDeviceObject);
  1194. }
  1195. break;
  1196. }
  1197. }
  1198. //
  1199. // device is not started or not added yet.
  1200. //
  1201. Status = ndisIMQueueDeviceInstance(DriverHandle,
  1202. DeviceInstance,
  1203. DeviceContext);
  1204. } while (FALSE);
  1205. RELEASE_MUTEX(&MiniBlock->IMStartRemoveMutex);
  1206. PnPDereferencePackage();
  1207. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1208. ("<==NdisIMInitializeDeviceInstanceEx: Driver %p, Instance %p, Context %p, Status %lx\n",
  1209. DriverHandle, DeviceInstance, DeviceContext, Status));
  1210. return Status;
  1211. }
  1212. NDIS_STATUS
  1213. ndisIMInitializeDeviceInstance(
  1214. IN PNDIS_MINIPORT_BLOCK Miniport,
  1215. IN NDIS_HANDLE DeviceContext,
  1216. IN BOOLEAN fStartIrp
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. This routine is called when we have received NdisIMInitializeDeviceInstance
  1221. -AND- START IRP for an IM miniport.
  1222. Initialize an instance of a miniport device.
  1223. Arguments:
  1224. Miniport Handle to NDIS_MINIPORT_BLOCK
  1225. DeviceContext Context to associate with the device. Retrieved via NdisIMGetDeviceContext.
  1226. fStartIrp flag to signal if we are in the context of handling START IRP
  1227. Return Value:
  1228. --*/
  1229. {
  1230. NDIS_STATUS Status;
  1231. NTSTATUS NtStatus;
  1232. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1233. ("==>ndisIMInitializeDeviceInstance: Miniport %p, Context %p, fStartIrp %lx\n", Miniport, DeviceContext, fStartIrp));
  1234. //
  1235. // it is quite possible we are dealing with a miniport block that has been "used"
  1236. // several times. inother words, it has been started and DeviceInitialized, then
  1237. // Device-De-Initialized and then has received a few query_stop and cancel_stop.
  1238. // in this case the miniport block has to be cleaned up. otherwise, ndisPnPStartDevice
  1239. // is not going to detect that miniport block needs re-initalization
  1240. //
  1241. ndisReinitializeMiniportBlock(Miniport);
  1242. Miniport->DeviceContext = DeviceContext;
  1243. Status = ndisPnPStartDevice(Miniport->DeviceObject, NULL); // no Irp
  1244. if (Status == NDIS_STATUS_SUCCESS)
  1245. {
  1246. //
  1247. // if we are in the context of start IRP, queue a workitem to initialize
  1248. // the bindings on this adapter to avoid the delay
  1249. //
  1250. if (!fStartIrp)
  1251. {
  1252. //
  1253. // Now set the device class association so that people can reference this.
  1254. //
  1255. NtStatus = IoSetDeviceInterfaceState(&Miniport->SymbolicLinkName, TRUE);
  1256. if (NT_SUCCESS(NtStatus))
  1257. {
  1258. //
  1259. // Do protocol notifications
  1260. //
  1261. ndisCheckAdapterBindings(Miniport, NULL);
  1262. }
  1263. else
  1264. {
  1265. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  1266. ("ndisCheckAdapterBindings: IoSetDeviceInterfaceState failed: Miniport %p, Status %lx\n", Miniport, NtStatus));
  1267. Status = NDIS_STATUS_FAILURE;
  1268. }
  1269. }
  1270. else
  1271. {
  1272. Status = ndisQueueBindWorkitem(Miniport);
  1273. }
  1274. }
  1275. else
  1276. {
  1277. //
  1278. // ndisPnPStartDevice can return an internal Error Code if the call
  1279. // to ndisMInitializeAdapter fails. convert this to NDIS_STATUS
  1280. //
  1281. Status = NDIS_STATUS_FAILURE;
  1282. }
  1283. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1284. ("<==ndisIMInitializeDeviceInstance: Miniport %p, Context %p, Status %lx\n", Miniport, DeviceContext, Status));
  1285. return Status;
  1286. }
  1287. NDIS_STATUS
  1288. ndisIMQueueDeviceInstance(
  1289. IN PNDIS_M_DRIVER_BLOCK MiniBlock,
  1290. IN PNDIS_STRING DeviceInstance,
  1291. IN NDIS_HANDLE DeviceContext
  1292. )
  1293. {
  1294. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1295. PNDIS_PENDING_IM_INSTANCE NewImInstance, pTemp;
  1296. KIRQL OldIrql;
  1297. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1298. ("==>ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p\n",
  1299. MiniBlock, DeviceInstance, DeviceContext));
  1300. do
  1301. {
  1302. //
  1303. // Queue the device name for which we have received an InitializeDeviceInstance
  1304. // from an IM driver. Check for duplicates.
  1305. //
  1306. NewImInstance = (PNDIS_PENDING_IM_INSTANCE)ALLOC_FROM_POOL(sizeof(NDIS_PENDING_IM_INSTANCE) +
  1307. DeviceInstance->Length +
  1308. sizeof(WCHAR),
  1309. NDIS_TAG_IM_DEVICE_INSTANCE);
  1310. if (NULL == NewImInstance)
  1311. {
  1312. Status = NDIS_STATUS_RESOURCES;
  1313. break;
  1314. }
  1315. NewImInstance->Context = DeviceContext;
  1316. NewImInstance->Name.MaximumLength = DeviceInstance->Length + sizeof(WCHAR);
  1317. NewImInstance->Name.Length = 0;
  1318. NewImInstance->Name.Buffer = (PWSTR)((PUCHAR)NewImInstance + sizeof(NDIS_PENDING_IM_INSTANCE));
  1319. RtlUpcaseUnicodeString(&NewImInstance->Name,
  1320. DeviceInstance,
  1321. FALSE);
  1322. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1323. for (pTemp = MiniBlock->PendingDeviceList;
  1324. pTemp != NULL;
  1325. pTemp = pTemp->Next)
  1326. {
  1327. if (NDIS_EQUAL_UNICODE_STRING(&NewImInstance->Name,
  1328. &pTemp->Name))
  1329. {
  1330. FREE_POOL(NewImInstance);
  1331. Status = NDIS_STATUS_NOT_ACCEPTED;
  1332. break;
  1333. }
  1334. }
  1335. if (Status == NDIS_STATUS_SUCCESS)
  1336. {
  1337. NewImInstance->Next = MiniBlock->PendingDeviceList;
  1338. MiniBlock->PendingDeviceList = NewImInstance;
  1339. }
  1340. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1341. } while (FALSE);
  1342. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1343. ("<==ndisIMQueueDeviceInstance: Driver %p, Instance %p, Context %p, Status %lx\n",
  1344. MiniBlock, DeviceInstance, DeviceContext, Status));
  1345. return Status;
  1346. }
  1347. BOOLEAN
  1348. ndisIMCheckDeviceInstance(
  1349. IN PNDIS_M_DRIVER_BLOCK MiniBlock,
  1350. IN PUNICODE_STRING DeviceInstanceName,
  1351. OUT PNDIS_HANDLE DeviceContext OPTIONAL
  1352. )
  1353. {
  1354. PNDIS_PENDING_IM_INSTANCE pDI, *ppDI;
  1355. PNDIS_PROTOCOL_BLOCK Protocol = MiniBlock->AssociatedProtocol;
  1356. KIRQL OldIrql;
  1357. BOOLEAN rc = FALSE;
  1358. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1359. ("==>ndisIMCheckDeviceInstance: Driver %p, DeviceInstanceName %p\n",
  1360. MiniBlock, DeviceInstanceName));
  1361. PnPReferencePackage();
  1362. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1363. for (ppDI = &MiniBlock->PendingDeviceList;
  1364. (pDI = *ppDI) != NULL;
  1365. ppDI = &pDI->Next)
  1366. {
  1367. if (NDIS_EQUAL_UNICODE_STRING(&pDI->Name,
  1368. DeviceInstanceName))
  1369. {
  1370. if (ARGUMENT_PRESENT(DeviceContext))
  1371. {
  1372. *DeviceContext = pDI->Context;
  1373. }
  1374. *ppDI = pDI->Next;
  1375. FREE_POOL(pDI);
  1376. rc = TRUE;
  1377. break;
  1378. }
  1379. }
  1380. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1381. PnPDereferencePackage();
  1382. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1383. ("<==ndisIMCheckDeviceInstance: Driver %p, Name %p, Context %p\n",
  1384. MiniBlock, DeviceInstanceName, DeviceContext));
  1385. if (!rc && ARGUMENT_PRESENT(DeviceContext))
  1386. {
  1387. //
  1388. // Send a reconfig notification to the protocol associated with this IM
  1389. // so it can re-initialize any device(s) it wants to
  1390. //
  1391. if (((Protocol = MiniBlock->AssociatedProtocol) != NULL) &&
  1392. (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL))
  1393. {
  1394. //
  1395. // We got a start device for an IM. Make sure its protocol
  1396. // half has all the requisite bindings. This can happen
  1397. // if an IM is disconnected and reconnected, for example.
  1398. // Also give it a NULL reconfig event. ATMLANE uses that
  1399. //
  1400. NET_PNP_EVENT NetPnpEvent;
  1401. KEVENT Event;
  1402. NDIS_STATUS Status;
  1403. NdisZeroMemory(&NetPnpEvent, sizeof(NetPnpEvent));
  1404. INITIALIZE_EVENT(&Event);
  1405. NetPnpEvent.NetEvent = NetEventReconfigure;
  1406. PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent)->pEvent = &Event;
  1407. WAIT_FOR_PROTO_MUTEX(Protocol);
  1408. Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(NULL, &NetPnpEvent);
  1409. if (NDIS_STATUS_PENDING == Status)
  1410. {
  1411. //
  1412. // Wait for completion.
  1413. //
  1414. WAIT_FOR_PROTOCOL(Protocol, &Event);
  1415. }
  1416. RELEASE_PROT_MUTEX(Protocol);
  1417. }
  1418. }
  1419. return rc;
  1420. }
  1421. NDIS_STATUS
  1422. NdisIMCancelInitializeDeviceInstance(
  1423. IN NDIS_HANDLE DriverHandle,
  1424. IN PNDIS_STRING DeviceInstance
  1425. )
  1426. {
  1427. NDIS_STATUS Status;
  1428. UNICODE_STRING UpcaseDevice;
  1429. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1430. ("==>NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p\n", DriverHandle, DeviceInstance));
  1431. //
  1432. // change to upper case
  1433. //
  1434. UpcaseDevice.Length = DeviceInstance->Length;
  1435. UpcaseDevice.MaximumLength = DeviceInstance->Length + sizeof(WCHAR);
  1436. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  1437. if (UpcaseDevice.Buffer == NULL)
  1438. {
  1439. return NDIS_STATUS_RESOURCES;
  1440. }
  1441. Status = RtlUpcaseUnicodeString(&UpcaseDevice, (PUNICODE_STRING)DeviceInstance, FALSE);
  1442. ASSERT (NT_SUCCESS(Status));
  1443. Status = (ndisIMCheckDeviceInstance((PNDIS_M_DRIVER_BLOCK)DriverHandle,
  1444. &UpcaseDevice,
  1445. NULL) == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
  1446. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1447. ("<==NdisIMCancelInitializeDeviceInstance: Driver %p, DeviceInstance %p, Status %lx\n",
  1448. DriverHandle, DeviceInstance, Status));
  1449. FREE_POOL(UpcaseDevice.Buffer);
  1450. return Status;
  1451. }
  1452. NDIS_HANDLE
  1453. NdisIMGetDeviceContext(
  1454. IN NDIS_HANDLE MiniportAdapterHandle
  1455. )
  1456. {
  1457. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1458. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1459. ("==>NdisIMGetDeviceContext: Miniport %p\n", Miniport));
  1460. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1461. ("<==NdisIMGetDeviceContext: Miniport %p\n", Miniport));
  1462. return(Miniport->DeviceContext);
  1463. }
  1464. NDIS_HANDLE
  1465. NdisIMGetBindingContext(
  1466. IN NDIS_HANDLE ProtocolBindingContext
  1467. )
  1468. {
  1469. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)ProtocolBindingContext;
  1470. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1471. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1472. ("==>NdisIMGetBindingContext: Open %p\n", Open));
  1473. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1474. ("<==NdisIMGetBindingContext: Open %p\n", Open));
  1475. return(Miniport->DeviceContext);
  1476. }