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.

3793 lines
110 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. ndis.c
  5. Abstract:
  6. NDIS wrapper functions
  7. Author:
  8. Adam Barr (adamba) 11-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. 10-Jul-1995 JameelH Make NDIS.SYS a device-driver and add PnP support
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. // #include "ndis.tmh"
  17. //
  18. // Define the module number for debug code.
  19. //
  20. #define MODULE_NUMBER MODULE_NDIS
  21. #define NDIS_DEVICE_NAME L"\\Device\\Ndis"
  22. #define NDIS_SYMBOLIC_NAME L"\\Global??\\NDIS"
  23. #define GET_TEXT_1(_T) #_T
  24. #define GET_TEXT(_T) GET_TEXT_1(_T)
  25. NTSTATUS
  26. DriverEntry(
  27. IN PDRIVER_OBJECT DriverObject,
  28. IN PUNICODE_STRING RegistryPath
  29. )
  30. /*++
  31. Routine Description:
  32. NDIS wrapper driver entry point.
  33. Arguments:
  34. DriverObject - Pointer to the driver object created by the system.
  35. RegistryPath - Pointer to the registry section where the parameters reside.
  36. Return Value:
  37. Return value from IoCreateDevice
  38. --*/
  39. {
  40. NTSTATUS Status = STATUS_SUCCESS;
  41. UNICODE_STRING DeviceName;
  42. UINT i;
  43. OBJECT_ATTRIBUTES ObjectAttr;
  44. UNICODE_STRING CallbackObjectName;
  45. NTSTATUS NtStatus;
  46. SYSTEM_BATTERY_STATE ndisSystemBatteryState;
  47. HANDLE ThreadHandle;
  48. BOOLEAN fDerefCallbackObject = FALSE, fDeregisterCallback = FALSE;
  49. UNREFERENCED_PARAMETER(RegistryPath);
  50. // WPP_INIT_TRACING(DriverObject, RegistryPath);
  51. // LOG_INFO("==>Ndis: DriverEntry");
  52. NdisInitializeString(&ndisBuildDate, (PUCHAR)__DATE__);
  53. NdisInitializeString(&ndisBuildTime, (PUCHAR)__TIME__);
  54. NdisInitializeString(&ndisBuiltBy, (PUCHAR)GET_TEXT(BUILT_BY));
  55. ndisDriverObject = DriverObject;
  56. //
  57. // Create the device object.
  58. //
  59. RtlInitUnicodeString(&DeviceName, NDIS_DEVICE_NAME);
  60. //1 in Longhorn, number of processors may vary during a session
  61. ndisNumberOfProcessors = KeNumberProcessors;
  62. Status = IoCreateDevice(DriverObject, // DriverObject
  63. 0, // DeviceExtension
  64. &DeviceName, // DeviceName
  65. FILE_DEVICE_NETWORK, // DeviceType
  66. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  67. FALSE, // Exclusive
  68. &ndisDeviceObject); // DeviceObject
  69. if (NT_SUCCESS(Status))
  70. {
  71. UNICODE_STRING SymbolicLinkName;
  72. // Create a symbolic link to this device
  73. RtlInitUnicodeString(&SymbolicLinkName, NDIS_SYMBOLIC_NAME);
  74. Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
  75. ndisDeviceObject->Flags |= DO_DIRECT_IO;
  76. // Initialize the driver object for this file system driver.
  77. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  78. {
  79. DriverObject->MajorFunction[i] = ndisDispatchRequest;
  80. }
  81. //
  82. // create a security descriptor for NDIS device object
  83. //
  84. Status = ndisCreateSecurityDescriptor(ndisDeviceObject,
  85. &ndisSecurityDescriptor,
  86. TRUE,
  87. TRUE);
  88. //1 check for status
  89. Status = CreateDeviceDriverSecurityDescriptor(DriverObject, TRUE, NULL);
  90. Status = CreateDeviceDriverSecurityDescriptor(DriverObject->DeviceObject, TRUE, NULL);
  91. Status = CreateDeviceDriverSecurityDescriptor(ndisDeviceObject, TRUE, NULL);
  92. //
  93. // disable for now
  94. //
  95. #if NDIS_UNLOAD
  96. DriverObject->DriverUnload = ndisUnload;
  97. #else
  98. DriverObject->DriverUnload = NULL;
  99. #endif
  100. INITIALIZE_SPIN_LOCK(&ndisGlobalLock);
  101. INITIALIZE_SPIN_LOCK(&ndisMiniDriverListLock);
  102. INITIALIZE_SPIN_LOCK(&ndisProtocolListLock);
  103. INITIALIZE_SPIN_LOCK(&ndisMiniportListLock);
  104. INITIALIZE_SPIN_LOCK(&ndisGlobalPacketPoolListLock);
  105. INITIALIZE_SPIN_LOCK(&ndisGlobalOpenListLock);
  106. ndisDmaAlignment = HalGetDmaAlignmentRequirement();
  107. if (sizeof(ULONG) > ndisDmaAlignment)
  108. {
  109. ndisDmaAlignment = sizeof(ULONG);
  110. }
  111. ndisTimeIncrement = KeQueryTimeIncrement();
  112. //
  113. // Get handles for all conditionally lockable sections
  114. //
  115. for (i = 0; i < MAX_PKG; i++)
  116. {
  117. ndisInitializePackage(&ndisPkgs[i]);
  118. }
  119. ExInitializeResourceLite(&SharedMemoryResource);
  120. ndisReadRegistry();
  121. //
  122. // don't let use set this bit through registry
  123. //
  124. ndisFlags &= ~NDIS_GFLAG_TRACK_MEM_ALLOCATION;
  125. Status = STATUS_SUCCESS;
  126. ndisSystemProcess = NtCurrentProcess();
  127. //
  128. // Now create a worker thread for use by NDIS
  129. // This is so that when we queue PnP events upto transports
  130. // and they need worker threads as well ...
  131. //
  132. KeInitializeQueue(&ndisWorkerQueue, 0);
  133. Status = PsCreateSystemThread(&ThreadHandle,
  134. THREAD_ALL_ACCESS,
  135. NULL,
  136. NtCurrentProcess(),
  137. NULL,
  138. ndisWorkerThread,
  139. NULL);
  140. if (!NT_SUCCESS(Status))
  141. {
  142. //1 do more error processing here
  143. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  144. ("NDIS DriverEntry: Cannot create worker thread, Status %lx\n", Status));
  145. }
  146. else
  147. {
  148. NtClose(ThreadHandle);
  149. }
  150. }
  151. KeQuerySystemTime(&KeBootTime);
  152. ConvertSecondsToTicks(POOL_AGING_TIME, &PoolAgingTicks);
  153. //
  154. // verifir intialization. in case ndis tester wants to verify
  155. // the drivers by intercepting ndis entry points, ndis should
  156. // not verify the calls
  157. //
  158. if (!(ndisFlags & NDIS_GFLAG_DONT_VERIFY))
  159. ndisVerifierInitialization();
  160. #if DBG
  161. if (ndisDebugBreakPoint)
  162. {
  163. DbgPrint("Ndis: DriverEntry\n");
  164. DbgBreakPoint();
  165. }
  166. #endif
  167. #ifdef TRACK_MOPEN_REFCOUNTS
  168. NdisZeroMemory (&ndisLogfile, sizeof(UINT) * NDIS_LOGFILE_SIZE);
  169. #endif
  170. #ifdef TRACK_MINIPORT_REFCOUNTS
  171. NdisZeroMemory (&ndisMiniportLogfile, sizeof(UINT) * NDIS_MINIPORT_LOGFILE_SIZE);
  172. #endif
  173. #ifdef NDIS_LOG_ABORTED_REQUESTS
  174. for (i = 0; i < 16; i++)
  175. {
  176. NdisZeroMemory (&ndisAbortedRequests[i], sizeof (NDIS_REQUEST));
  177. }
  178. #endif
  179. //
  180. // create a callback options for those kernel mode components that like
  181. // to hear about Bind/Unbind events
  182. //
  183. RtlInitUnicodeString(&CallbackObjectName, NDIS_BIND_UNBIND_CALLBACK_NAME);
  184. InitializeObjectAttributes(&ObjectAttr,
  185. &CallbackObjectName,
  186. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE,
  187. NULL,
  188. NULL);
  189. NtStatus = ExCreateCallback(&ndisBindUnbindCallbackObject,
  190. &ObjectAttr,
  191. TRUE, // create
  192. TRUE); // allow multiple callback registeration
  193. if (!NT_SUCCESS(NtStatus))
  194. {
  195. DbgPrint("Ndis: failed to create a Callback object. Status %lx\n", NtStatus);
  196. }
  197. #if 0
  198. else
  199. {
  200. //
  201. // for test purpose
  202. //
  203. ndisBindUnbindCallbackRegisterationHandle = ExRegisterCallback(ndisBindUnbindCallbackObject,
  204. ndisBindUnbindCallback,
  205. (PVOID)NULL);
  206. if (ndisBindUnbindCallbackRegisterationHandle == NULL)
  207. {
  208. DbgPrint("Ndis: failed to register a BindUnbind callback routine\n");
  209. }
  210. }
  211. #endif
  212. //
  213. // register a notification callback for power state changes
  214. //
  215. RtlInitUnicodeString(&CallbackObjectName, L"\\CallBack\\PowerState");
  216. InitializeObjectAttributes(&ObjectAttr,
  217. &CallbackObjectName,
  218. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE,
  219. NULL,
  220. NULL);
  221. NtStatus = ExCreateCallback(&ndisPowerStateCallbackObject,
  222. &ObjectAttr,
  223. FALSE,
  224. TRUE);
  225. if (!NT_SUCCESS(Status))
  226. {
  227. DbgPrint("Ndis: failed to create a Callback object. Status %lx\n", NtStatus);
  228. }
  229. else
  230. {
  231. fDerefCallbackObject = TRUE;
  232. ndisPowerStateCallbackHandle = ExRegisterCallback(ndisPowerStateCallbackObject,
  233. (PCALLBACK_FUNCTION)&ndisPowerStateCallback,
  234. (PVOID)NULL);
  235. if (ndisPowerStateCallbackHandle == NULL)
  236. {
  237. DbgPrint("Ndis: failed to register a power state Callback routine\n");
  238. }
  239. else
  240. {
  241. fDeregisterCallback = TRUE;
  242. }
  243. RtlZeroMemory(&ndisSystemBatteryState, sizeof(SYSTEM_BATTERY_STATE));
  244. //
  245. // get the current power source
  246. //
  247. NtStatus = ZwPowerInformation(SystemBatteryState,
  248. NULL,
  249. 0,
  250. &ndisSystemBatteryState,
  251. sizeof(SYSTEM_BATTERY_STATE));
  252. if (NT_SUCCESS(NtStatus))
  253. {
  254. ndisAcOnLine = (ndisSystemBatteryState.AcOnLine == TRUE) ? 1 : 0;
  255. }
  256. fDerefCallbackObject = FALSE;
  257. fDeregisterCallback = FALSE;
  258. }
  259. InitializeListHead(&ndisGlobalPacketPoolList);
  260. if (fDeregisterCallback)
  261. {
  262. ExUnregisterCallback(ndisPowerStateCallbackHandle);
  263. }
  264. if (fDerefCallbackObject)
  265. {
  266. ObDereferenceObject(ndisPowerStateCallbackObject);
  267. }
  268. INITIALIZE_MUTEX(&ndisPnPMutex);
  269. //
  270. // create an ACL for all users
  271. //
  272. AllUsersAclRead = ndisCreateAcl(TRUE, // Admins
  273. TRUE, //LocalSystem
  274. TRUE, //LocalService
  275. TRUE, //NetworkService
  276. TRUE, //NetConfigOps
  277. TRUE, //Users
  278. GENERIC_READ | WMIGUID_QUERY
  279. );
  280. ASSERT(AllUsersAclRead != NULL);
  281. AllUsersAclWrite = ndisCreateAcl(TRUE, // Admins
  282. TRUE, //LocalSystem
  283. TRUE, //LocalService
  284. TRUE, //NetworkService
  285. TRUE, //NetConfigOps
  286. TRUE, //Users
  287. GENERIC_WRITE | WMIGUID_SET
  288. );
  289. ASSERT(AllUsersAclWrite != NULL);
  290. AllUsersAclReadWrite = ndisCreateAcl(TRUE, // Admins
  291. TRUE, //LocalSystem
  292. TRUE, //LocalService
  293. TRUE, //NetworkService
  294. TRUE, //NetConfigOps
  295. TRUE, //Users
  296. GENERIC_READ | GENERIC_WRITE | WMIGUID_QUERY | WMIGUID_SET
  297. );
  298. ASSERT(AllUsersAclReadWrite != NULL);
  299. AllUsersAclNotification = ndisCreateAcl(TRUE, // Admins
  300. TRUE, //LocalSystem
  301. TRUE, //LocalService
  302. TRUE, //NetworkService
  303. TRUE, //NetConfigOps
  304. TRUE, //Users
  305. SYNCHRONIZE | WMIGUID_NOTIFICATION
  306. );
  307. ASSERT(AllUsersAclNotification != NULL);
  308. //
  309. // create an ACL for admin types
  310. //
  311. AdminsAcl = ndisCreateAcl(TRUE, // Admins
  312. TRUE, //LocalSystem
  313. TRUE, //LocalService
  314. TRUE, //NetworkService
  315. TRUE, //NetConfigOps
  316. FALSE, //Users
  317. GENERIC_READ | GENERIC_WRITE | WMIGUID_QUERY | WMIGUID_SET
  318. );
  319. ASSERT(AdminsAcl != NULL);
  320. //
  321. // Create an SD for All Users
  322. //
  323. Status = ndisCreateGenericSD(AllUsersAclRead, AllUsersReadSecurityDescriptor);
  324. ASSERT(NT_SUCCESS(Status));
  325. Status = ndisCreateGenericSD(AllUsersAclWrite, AllUsersWriteSecurityDescriptor);
  326. ASSERT(NT_SUCCESS(Status));
  327. Status = ndisCreateGenericSD(AllUsersAclReadWrite, AllUsersReadWriteSecurityDescriptor);
  328. ASSERT(NT_SUCCESS(Status));
  329. Status = ndisCreateGenericSD(AllUsersAclNotification, AllUsersNotificationSecurityDescriptor);
  330. ASSERT(NT_SUCCESS(Status));
  331. Status = ndisCreateGenericSD(AdminsAcl, AdminsSecurityDescriptor);
  332. ASSERT(NT_SUCCESS(Status));
  333. /*
  334. //
  335. // set the security descriptor for all known guids
  336. //
  337. for (i = 0; i < sizeof(ndisSupportedGuids)/sizeof(NDIS_GUID); i++)
  338. {
  339. Status = ndisSetWmiSecurity(&ndisSupportedGuids[i]);
  340. if (NT_SUCCESS(Status))
  341. {
  342. DbgPrint("Successfully added ndisSupportedGuids[%ld].\n", i);
  343. }
  344. else
  345. {
  346. DbgPrint("setting security failed for %ld\n.", i);
  347. }
  348. }
  349. for (i = 0; i < sizeof(ndisCoSupportedGuids)/sizeof(NDIS_GUID); i++)
  350. {
  351. Status = ndisSetWmiSecurity(&ndisCoSupportedGuids[i]);
  352. if (NT_SUCCESS(Status))
  353. {
  354. DbgPrint("Successfully added ndisCoSupportedGuids[%ld].\n", i);
  355. }
  356. else
  357. {
  358. DbgPrint("setting security failed for ndisCoSupportedGuids[%ld].\n", i);
  359. }
  360. }
  361. for (i = 0; i < sizeof(ndisMediaSupportedGuids)/sizeof(NDIS_GUID); i++)
  362. {
  363. Status = ndisSetWmiSecurity(&ndisMediaSupportedGuids[i]);
  364. if (NT_SUCCESS(Status))
  365. {
  366. DbgPrint("Successfully added ndisMediaSupportedGuids[%ld].\n", i);
  367. }
  368. else
  369. {
  370. DbgPrint("setting security failed for ndisMediaSupportedGuids[%ld].\n", i);
  371. }
  372. }
  373. for (i = 0; i < sizeof(ndisStatusSupportedGuids)/sizeof(NDIS_GUID); i++)
  374. {
  375. Status = ndisSetWmiSecurity(&ndisStatusSupportedGuids[i]);
  376. if (NT_SUCCESS(Status))
  377. {
  378. DbgPrint("Successfully added ndisStatusSupportedGuids[%ld].\n", i);
  379. }
  380. else
  381. {
  382. DbgPrint("setting security failed for ndisStatusSupportedGuids[%ld].\n", i);
  383. }
  384. }
  385. */
  386. return Status;
  387. }
  388. #if NDIS_UNLOAD
  389. VOID
  390. ndisUnload(
  391. IN PDRIVER_OBJECT DriverObject
  392. )
  393. /*++
  394. Routine Description:
  395. This is the unload routine for the Appletalk driver.
  396. NOTE: Unload will not be called until all the handles have been
  397. closed successfully. We just shutdown all the ports, and do
  398. misc. cleanup.
  399. Arguments:
  400. DriverObject - Pointer to driver object for this driver.
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. NTSTATUS Status;
  406. UNICODE_STRING SymbolicLinkName;
  407. UINT i;
  408. NdisFreeString(ndisBuildDate);
  409. NdisFreeString(ndisBuildTime);
  410. NdisFreeString(ndisBuiltBy);
  411. if (ndisPowerStateCallbackHandle)
  412. {
  413. ExUnregisterCallback(ndisPowerStateCallbackHandle);
  414. }
  415. if (ndisPowerStateCallbackObject)
  416. {
  417. ObDereferenceObject(ndisPowerStateCallbackObject);
  418. }
  419. ExDeleteResourceLite(&SharedMemoryResource);
  420. //
  421. // Tell the ndisWorkerThread to quit
  422. //
  423. INITIALIZE_WORK_ITEM(&ndisPoisonPill, NULL, &ndisPoisonPill);
  424. QUEUE_WORK_ITEM(&ndisPoisonPill, CriticalWorkQueue);
  425. WAIT_FOR_OBJECT(ndisThreadObject, 0);
  426. ObDereferenceObject(ndisThreadObject);
  427. RtlInitUnicodeString(&SymbolicLinkName, NDIS_SYMBOLIC_NAME);
  428. Status = IoDeleteSymbolicLink(&SymbolicLinkName);
  429. ASSERT(NT_SUCCESS(Status));
  430. IoDeleteDevice(ndisDeviceObject);
  431. //
  432. // ASSERT that all the packages are unlocked
  433. //
  434. for (i = 0; i < MAX_PKG; i++)
  435. {
  436. ASSERT(ndisPkgs[i].ReferenceCount == 0);
  437. }
  438. }
  439. #endif
  440. VOID
  441. ndisReadRegistry(
  442. VOID
  443. )
  444. {
  445. RTL_QUERY_REGISTRY_TABLE QueryTable[8];
  446. UCHAR c;
  447. ULONG DefaultZero = 0;
  448. //
  449. // First we need to initialize the processor information incase
  450. // the registry is empty.
  451. //
  452. for (c = 0; (c < NDIS_MAX_CPU_COUNT) && (c < ndisNumberOfProcessors) ; c++)
  453. {
  454. ndisValidProcessors[c] = c;
  455. }
  456. ndisCurrentProcessor = ndisMaximumProcessor = c - 1;
  457. //
  458. // 1) Switch to the MediaTypes key below the service (NDIS) key
  459. //
  460. QueryTable[0].QueryRoutine = NULL;
  461. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  462. QueryTable[0].Name = L"MediaTypes";
  463. //
  464. // Setup to enumerate the values in the registry section (shown above).
  465. // For each such value, we'll add it to the ndisMediumArray
  466. //
  467. QueryTable[1].QueryRoutine = ndisAddMediaTypeToArray;
  468. QueryTable[1].DefaultType = REG_DWORD;
  469. QueryTable[1].DefaultData = (PVOID)&DefaultZero;
  470. QueryTable[1].DefaultLength = 0;
  471. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  472. QueryTable[1].Name = NULL;
  473. //
  474. // Query terminator
  475. //
  476. QueryTable[2].QueryRoutine = NULL;
  477. QueryTable[2].Flags = 0;
  478. QueryTable[2].Name = NULL;
  479. //
  480. // The rest of the work is done in the callback routine ndisAddMediaTypeToArray.
  481. //
  482. RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  483. L"NDIS",
  484. QueryTable,
  485. (PVOID)NULL, // no context needed
  486. NULL);
  487. //
  488. // Switch to the parameters key below the service (NDIS) key and
  489. // read the parameters.
  490. //
  491. QueryTable[0].QueryRoutine = NULL;
  492. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  493. QueryTable[0].Name = L"Parameters";
  494. //
  495. // Read in the processor affinity mask.
  496. //
  497. QueryTable[1].QueryRoutine = ndisReadProcessorAffinityMask;
  498. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  499. QueryTable[1].DefaultData = (PVOID)&DefaultZero;
  500. QueryTable[1].DefaultLength = 0;
  501. QueryTable[1].DefaultType = REG_DWORD;
  502. QueryTable[1].Name = L"ProcessorAffinityMask";
  503. QueryTable[2].QueryRoutine = ndisReadRegParameters;
  504. QueryTable[2].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  505. QueryTable[2].DefaultData = (PVOID)&ndisFlags;
  506. QueryTable[2].DefaultLength = 0;
  507. QueryTable[2].DefaultType = REG_DWORD;
  508. QueryTable[2].Name = L"Flags";
  509. QueryTable[2].EntryContext = (PVOID)&ndisFlags;
  510. //1 check for an upper bound on # of stack locations.
  511. QueryTable[3].QueryRoutine = ndisReadRegParameters;
  512. QueryTable[3].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  513. QueryTable[3].DefaultData = (PVOID)&ndisPacketStackSize;
  514. QueryTable[3].DefaultLength = 0;
  515. QueryTable[3].DefaultType = REG_DWORD;
  516. QueryTable[3].Name = L"PacketStackSize";
  517. QueryTable[3].EntryContext = (PVOID)&ndisPacketStackSize;
  518. //
  519. // Query terminator
  520. //
  521. QueryTable[4].QueryRoutine = NULL;
  522. QueryTable[4].Flags = 0;
  523. QueryTable[4].Name = NULL;
  524. #if DBG
  525. #ifdef NDIS_TRACE
  526. ndisDebugBreakPoint = 1;
  527. ndisDebugLevel = 0;
  528. ndisDebugSystems = 0x3003;
  529. #else
  530. QueryTable[4].QueryRoutine = ndisReadRegParameters;
  531. QueryTable[4].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  532. QueryTable[4].Name = L"DebugBreakPoint";
  533. QueryTable[4].DefaultData = (PVOID)&ndisDebugBreakPoint;
  534. QueryTable[4].DefaultLength = 0;
  535. QueryTable[4].EntryContext = (PVOID)&ndisDebugBreakPoint;
  536. QueryTable[4].DefaultType = REG_DWORD;
  537. QueryTable[5].QueryRoutine = ndisReadRegParameters;
  538. QueryTable[5].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  539. QueryTable[5].Name = L"DebugLevel";
  540. QueryTable[5].DefaultData = (PVOID)&ndisDebugLevel;
  541. QueryTable[5].DefaultLength = 0;
  542. QueryTable[5].EntryContext = (PVOID)&ndisDebugLevel;
  543. QueryTable[5].DefaultType = REG_DWORD;
  544. QueryTable[6].QueryRoutine = ndisReadRegParameters;
  545. QueryTable[6].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  546. QueryTable[6].Name = L"DebugSystems";
  547. QueryTable[6].DefaultData = (PVOID)&ndisDebugSystems;
  548. QueryTable[6].DefaultLength = 0;
  549. QueryTable[6].EntryContext = (PVOID)&ndisDebugSystems;
  550. QueryTable[6].DefaultType = REG_DWORD;
  551. //
  552. // Query terminator
  553. //
  554. QueryTable[7].QueryRoutine = NULL;
  555. QueryTable[7].Flags = 0;
  556. QueryTable[7].Name = NULL;
  557. #endif
  558. #endif
  559. //
  560. // The rest of the work is done in the callback routines
  561. //
  562. RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  563. L"NDIS",
  564. QueryTable,
  565. (PVOID)NULL, // no context needed
  566. NULL);
  567. //
  568. // Make sure ndisPacketStackSize isn't zero
  569. //
  570. if (ndisPacketStackSize == 0)
  571. ndisPacketStackSize = 1;
  572. }
  573. NTSTATUS
  574. ndisReadRegParameters(
  575. IN PWSTR ValueName,
  576. IN ULONG ValueType,
  577. IN PVOID ValueData,
  578. IN ULONG ValueLength,
  579. IN PVOID Context,
  580. IN PVOID EntryContext
  581. )
  582. /*++
  583. Arguments:
  584. ValueName - The name of the value
  585. ValueType - The type of the value (REG_MULTI_SZ -- ignored).
  586. ValueData - The null-terminated data for the value.
  587. ValueLength - The length of ValueData.
  588. Context - Unused.
  589. EntryContext - A pointer to the pointer that holds the copied data.
  590. Return Value:
  591. STATUS_SUCCESS
  592. --*/
  593. {
  594. UNREFERENCED_PARAMETER(ValueName);
  595. UNREFERENCED_PARAMETER(ValueLength);
  596. UNREFERENCED_PARAMETER(Context);
  597. if ((ValueType != REG_DWORD) || (ValueData == NULL))
  598. return STATUS_UNSUCCESSFUL;
  599. *((PULONG)EntryContext) = *((PULONG)ValueData);
  600. return STATUS_SUCCESS;
  601. }
  602. NTSTATUS
  603. ndisReadProcessorAffinityMask(
  604. IN PWSTR ValueName,
  605. IN ULONG ValueType,
  606. IN PVOID ValueData,
  607. IN ULONG ValueLength,
  608. IN PVOID Context,
  609. IN PVOID EntryContext
  610. )
  611. /*++
  612. Routine Description:
  613. Arguments:
  614. Return Value:
  615. --*/
  616. {
  617. UNREFERENCED_PARAMETER(EntryContext);
  618. UNREFERENCED_PARAMETER(Context);
  619. UNREFERENCED_PARAMETER(ValueLength);
  620. UNREFERENCED_PARAMETER(ValueName);
  621. //
  622. // If we have valid data then build our array of valid processors
  623. // to use.... Treat the special case of 0 or default -1 to signify
  624. // that DPC affinity will follow interrupt affinity
  625. //
  626. if ((REG_DWORD == ValueType) && (ValueData != NULL))
  627. {
  628. if ((*(PULONG)ValueData == 0) ||
  629. (*(PULONG)ValueData == 0xFFFFFFFF))
  630. {
  631. ndisSkipProcessorAffinity = TRUE;
  632. }
  633. else
  634. {
  635. ULONG ProcessorAffinity;
  636. UCHAR c1, c2;
  637. //
  638. // Save the processor affinity.
  639. //
  640. ProcessorAffinity = *(PULONG)ValueData;
  641. //
  642. // Fill in the valid processor array.
  643. //
  644. for (c1 = c2 = 0;
  645. (c1 <= ndisMaximumProcessor) && (ProcessorAffinity != 0);
  646. c1++)
  647. {
  648. if (ProcessorAffinity & 1)
  649. {
  650. ndisValidProcessors[c2++] = c1;
  651. }
  652. ProcessorAffinity >>= 1;
  653. }
  654. ndisCurrentProcessor = ndisMaximumProcessor = c2 - 1;
  655. }
  656. }
  657. return STATUS_SUCCESS;
  658. }
  659. NTSTATUS
  660. ndisAddMediaTypeToArray(
  661. IN PWSTR ValueName,
  662. IN ULONG ValueType,
  663. IN PVOID ValueData,
  664. IN ULONG ValueLength,
  665. IN PVOID Context,
  666. IN PVOID EntryContext
  667. )
  668. {
  669. #if DBG
  670. NDIS_STRING Str;
  671. RtlInitUnicodeString(&Str, ValueName);
  672. #else
  673. UNREFERENCED_PARAMETER(ValueName);
  674. #endif
  675. UNREFERENCED_PARAMETER(EntryContext);
  676. UNREFERENCED_PARAMETER(Context);
  677. UNREFERENCED_PARAMETER(ValueLength);
  678. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
  679. ("ExperimentalMediaType %Z - %x\n", &Str, *(PULONG)ValueData));
  680. //
  681. // Ignore all values that we already know about. These should not be in the
  682. // registry anyway, but just in case somebody is messing with it.
  683. //
  684. if ((ValueType == REG_DWORD) && (ValueData != NULL) && (*(PULONG)ValueData > NdisMediumIrda))
  685. {
  686. NDIS_MEDIUM *pTemp;
  687. ULONG size;
  688. //
  689. // See if we have enough space to add this value. If not allocate space for the
  690. // new array, copy the old one into this (and free the old if not static).
  691. //
  692. ASSERT (ndisMediumArraySize <= ndisMediumArrayMaxSize);
  693. //
  694. // Check for duplicates. If so drop it
  695. //
  696. for (pTemp = ndisMediumArray, size = ndisMediumArraySize;
  697. size > 0; pTemp ++, size -= sizeof(NDIS_MEDIUM))
  698. {
  699. if (*(NDIS_MEDIUM *)ValueData == *pTemp)
  700. {
  701. //
  702. // Duplicate.
  703. //
  704. return STATUS_SUCCESS;
  705. }
  706. }
  707. if (ndisMediumArraySize == ndisMediumArrayMaxSize)
  708. {
  709. //
  710. // We do not have any space in the array. Need to re-alloc. Be generous.
  711. //
  712. pTemp = (NDIS_MEDIUM *)ALLOC_FROM_POOL(ndisMediumArraySize + EXPERIMENTAL_SIZE*sizeof(NDIS_MEDIUM),
  713. NDIS_TAG_MEDIA_TYPE_ARRAY);
  714. if (pTemp != NULL)
  715. {
  716. CopyMemory(pTemp, ndisMediumArray, ndisMediumArraySize);
  717. if (ndisMediumArray != ndisMediumBuffer)
  718. {
  719. FREE_POOL(ndisMediumArray);
  720. }
  721. ndisMediumArray = pTemp;
  722. }
  723. }
  724. if (ndisMediumArraySize < ndisMediumArrayMaxSize)
  725. {
  726. ndisMediumArray[ndisMediumArraySize/sizeof(NDIS_MEDIUM)] = *(NDIS_MEDIUM *)ValueData;
  727. ndisMediumArraySize += sizeof(NDIS_MEDIUM);
  728. }
  729. }
  730. return STATUS_SUCCESS;
  731. }
  732. VOID
  733. ndisWorkerThread(
  734. IN PVOID Context
  735. )
  736. /*++
  737. Routine Description:
  738. Arguments:
  739. Return Value:
  740. --*/
  741. {
  742. BOOLEAN FirstThread = (Context == NULL);
  743. PLIST_ENTRY pList;
  744. HANDLE ThreadHandle;
  745. PWORK_QUEUE_ITEM pWI;
  746. NTSTATUS Status;
  747. if (FirstThread)
  748. {
  749. ndisThreadObject = PsGetCurrentThread();
  750. ObReferenceObject(ndisThreadObject);
  751. do
  752. {
  753. //
  754. // Block here waiting for work-items to do
  755. //
  756. pList = KeRemoveQueue(&ndisWorkerQueue, KernelMode, NULL);
  757. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  758. ("ndisWorkerThread: WorkItem %p\n", pList));
  759. pWI = CONTAINING_RECORD(pList, WORK_QUEUE_ITEM, List);
  760. #if NDIS_UNLOAD
  761. //
  762. // Unload asking us to quit, comply.
  763. //
  764. if (pWI == &ndisPoisonPill)
  765. {
  766. break;
  767. }
  768. #endif
  769. Status = PsCreateSystemThread(&ThreadHandle,
  770. THREAD_ALL_ACCESS,
  771. NULL,
  772. NtCurrentProcess(),
  773. NULL,
  774. ndisWorkerThread,
  775. pWI);
  776. if (NT_SUCCESS(Status))
  777. {
  778. NtClose(ThreadHandle);
  779. }
  780. else
  781. {
  782. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  783. ("ndisWorkerThread: Failed to create a thread, using EX worker thread\n"));
  784. XQUEUE_WORK_ITEM(pWI, CriticalWorkQueue);
  785. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  786. }
  787. } while (TRUE);
  788. }
  789. else
  790. {
  791. //
  792. // Not the main thread, just do the thing and die.
  793. //
  794. LastWorkerThreadWI = *((PWORK_QUEUE_ITEM)Context);
  795. pWI = (PWORK_QUEUE_ITEM)Context;
  796. (*pWI->WorkerRoutine)(pWI->Parameter);
  797. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  798. }
  799. }
  800. NTSTATUS
  801. ndisDispatchRequest(
  802. IN PDEVICE_OBJECT pDeviceObject,
  803. IN PIRP pIrp
  804. )
  805. /*++
  806. Routine Description:
  807. Dispatcher for Irps intended for the NDIS Device.
  808. Arguments:
  809. Return Value:
  810. --*/
  811. {
  812. NTSTATUS Status = STATUS_SUCCESS;
  813. PIO_STACK_LOCATION pIrpSp;
  814. PNDIS_DEVICE_OBJECT_OPEN_CONTEXT OpenContext = NULL;
  815. NTSTATUS SecurityStatus;
  816. static LONG OpenCount = 0;
  817. UNREFERENCED_PARAMETER(pDeviceObject);
  818. PAGED_CODE( );
  819. #if defined(_WIN64)
  820. if (IoIs32bitProcess(pIrp))
  821. {
  822. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  823. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  824. return STATUS_INVALID_DEVICE_REQUEST;
  825. }
  826. #endif
  827. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  828. pIrp->IoStatus.Status = STATUS_PENDING;
  829. pIrp->IoStatus.Information = 0;
  830. PnPReferencePackage();
  831. switch (pIrpSp->MajorFunction)
  832. {
  833. case IRP_MJ_CREATE:
  834. OpenContext = (PNDIS_DEVICE_OBJECT_OPEN_CONTEXT)ALLOC_FROM_POOL(sizeof(NDIS_DEVICE_OBJECT_OPEN_CONTEXT),
  835. NDIS_TAG_OPEN_CONTEXT);
  836. if (OpenContext == NULL)
  837. {
  838. Status = STATUS_INSUFFICIENT_RESOURCES;
  839. break;
  840. }
  841. ZeroMemory(OpenContext, sizeof(NDIS_DEVICE_OBJECT_OPEN_CONTEXT));
  842. OpenContext->AdminAccessAllowed = ndisCheckAccess(pIrp,
  843. pIrpSp,
  844. &SecurityStatus,
  845. ndisSecurityDescriptor);
  846. //
  847. // save the caller's access right
  848. //
  849. pIrpSp->FileObject->FsContext = OpenContext;
  850. Increment(&OpenCount, &Lock);
  851. break;
  852. case IRP_MJ_CLEANUP:
  853. OpenContext = pIrpSp->FileObject->FsContext;
  854. ASSERT(OpenContext != NULL);
  855. pIrpSp->FileObject->FsContext = NULL;
  856. FREE_POOL(OpenContext);
  857. Decrement(&OpenCount, &Lock);
  858. break;
  859. case IRP_MJ_CLOSE:
  860. break;
  861. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  862. break;
  863. case IRP_MJ_DEVICE_CONTROL:
  864. Status = ndisHandlePnPRequest(pIrp);
  865. break;
  866. default:
  867. Status = STATUS_NOT_IMPLEMENTED;
  868. break;
  869. }
  870. ASSERT (CURRENT_IRQL < DISPATCH_LEVEL);
  871. ASSERT (Status != STATUS_PENDING);
  872. pIrp->IoStatus.Status = Status;
  873. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  874. PnPDereferencePackage();
  875. return Status;
  876. }
  877. NTSTATUS
  878. ndispConvOffsetToPointer(
  879. IN PVOID MasterBuffer,
  880. IN ULONG MasterLength,
  881. IN OUT PULONG_PTR Offset,
  882. IN ULONG Length,
  883. IN ULONG Alignment
  884. )
  885. /*++
  886. Routine Description:
  887. This function validates a buffer within an IOCTL and converts a buffer
  888. offset to a pointer.
  889. Argumens:
  890. MasterBuffer - Pointer to the start of the IOCTL buffer
  891. MasterLength - Length of the IOCTL buffer
  892. Offset - Offset of the data buffer within the IOCTL buffer
  893. Length - Length of the data buffer within the IOCTL buffer
  894. Alignment - Required alignment of the type within the data buffer
  895. Return Value:
  896. The function status is the final status of the operation.
  897. --*/
  898. {
  899. ULONG_PTR masterStart;
  900. ULONG_PTR masterEnd;
  901. ULONG_PTR bufStart;
  902. ULONG_PTR bufEnd;
  903. if (Length == 0)
  904. {
  905. //
  906. // Nothing to do.
  907. //
  908. return STATUS_SUCCESS;
  909. }
  910. masterStart = (ULONG_PTR)MasterBuffer;
  911. masterEnd = masterStart + MasterLength;
  912. bufStart = masterStart + *Offset;
  913. bufEnd = bufStart + Length;
  914. //
  915. // Ensure that neither of the buffers wrap
  916. //
  917. if (masterEnd < masterStart || bufEnd < bufStart)
  918. {
  919. return STATUS_INVALID_PARAMETER;
  920. }
  921. //
  922. // Ensure that buf is wholly contained within master
  923. //
  924. if (bufStart < masterStart || bufEnd > masterEnd)
  925. {
  926. return STATUS_INVALID_PARAMETER;
  927. }
  928. //
  929. // Make sure that buf is properly aligned
  930. //
  931. if ((bufStart & (Alignment - 1)) != 0)
  932. {
  933. return STATUS_INVALID_PARAMETER;
  934. }
  935. //
  936. // Everything looks good, perform the conversion
  937. //
  938. *Offset += masterStart;
  939. return STATUS_SUCCESS;
  940. }
  941. NTSTATUS
  942. ndispConvVar(
  943. IN PVOID MasterBuffer,
  944. IN ULONG MasterLength,
  945. IN OUT PNDIS_VAR_DATA_DESC Var
  946. )
  947. /*++
  948. Routine Description:
  949. This function validates an NDIS_VAR_DATA_DESC buffer within an IOCTL
  950. and converts its data offset to a pointer.
  951. Argumens:
  952. MasterBuffer - Pointer to the start of the IOCTL buffer
  953. MasterLength - Length of the IOCTL buffer
  954. Var - Pointer to an NDIS_VAR_DATA_DESC structure.
  955. Return Value:
  956. The function status is the final status of the operation.
  957. --*/
  958. {
  959. return ndispConvOffsetToPointer( MasterBuffer,
  960. MasterLength,
  961. &Var->Offset,
  962. Var->Length,
  963. sizeof(WCHAR) );
  964. }
  965. NTSTATUS
  966. FASTCALL
  967. ndisHandlePnPRequest(
  968. IN PIRP pIrp
  969. )
  970. /*++
  971. Routine Description:
  972. Handler for PnP ioctls.
  973. Arguments:
  974. Return Value:
  975. --*/
  976. {
  977. NTSTATUS Status = STATUS_SUCCESS;
  978. PNDIS_DEVICE_OBJECT_OPEN_CONTEXT OpenContext;
  979. PNDIS_PNP_OPERATION PnPOp;
  980. PNDIS_ENUM_INTF EnumIntf;
  981. PIO_STACK_LOCATION pIrpSp;
  982. UNICODE_STRING Device;
  983. ULONG Method;
  984. PVOID pBuf;
  985. UINT iBufLen, oBufLen;
  986. UINT OutputLength = 0;
  987. BOOLEAN AdminAccessAllowed = FALSE;
  988. PAGED_CODE( );
  989. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  990. OpenContext = pIrpSp->FileObject->FsContext;
  991. if (OpenContext == NULL)
  992. {
  993. return STATUS_NO_SUCH_FILE;
  994. }
  995. AdminAccessAllowed = OpenContext->AdminAccessAllowed;
  996. Method = pIrpSp->Parameters.DeviceIoControl.IoControlCode & 3;
  997. // Ensure that the method is buffered - we always use that.
  998. if (Method == METHOD_BUFFERED)
  999. {
  1000. // Get the output buffer and its length. Input and Output buffers are
  1001. // both pointed to by the SystemBuffer
  1002. iBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  1003. oBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  1004. pBuf = pIrp->AssociatedIrp.SystemBuffer;
  1005. }
  1006. else
  1007. {
  1008. return STATUS_INVALID_PARAMETER;
  1009. }
  1010. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  1011. {
  1012. case IOCTL_NDIS_ADD_TDI_DEVICE:
  1013. if (!AdminAccessAllowed)
  1014. {
  1015. return STATUS_ACCESS_DENIED;
  1016. }
  1017. //
  1018. // Validate the DeviceName
  1019. //
  1020. Status = STATUS_INVALID_PARAMETER;
  1021. if ((iBufLen > 0) && ((iBufLen % sizeof(WCHAR)) == 0))
  1022. {
  1023. ((PWCHAR)pBuf)[iBufLen/sizeof(WCHAR) - 1] = 0;
  1024. RtlInitUnicodeString(&Device, pBuf);
  1025. Status = ndisHandleLegacyTransport(&Device);
  1026. }
  1027. break;
  1028. case IOCTL_NDIS_DO_PNP_OPERATION:
  1029. if (!AdminAccessAllowed)
  1030. {
  1031. return STATUS_ACCESS_DENIED;
  1032. }
  1033. Status = STATUS_BUFFER_TOO_SMALL;
  1034. PnPOp = (PNDIS_PNP_OPERATION)pBuf;
  1035. //
  1036. // check to make sure the input buffer is big enough to
  1037. // have all the information that NDIS_PNP_OPERATION structure
  1038. // claims to contain.
  1039. //
  1040. if ((iBufLen < sizeof(NDIS_PNP_OPERATION)) ||
  1041. (iBufLen < (sizeof(NDIS_PNP_OPERATION) +
  1042. PnPOp->LowerComponent.MaximumLength +
  1043. PnPOp->UpperComponent.MaximumLength +
  1044. PnPOp->ReConfigBufferSize +
  1045. PnPOp->BindList.MaximumLength
  1046. )))
  1047. {
  1048. break;
  1049. }
  1050. //
  1051. // Convert the four buffer offsets within NDIS_PNP_OPERATION
  1052. // to pointers.
  1053. //
  1054. Status = ndispConvVar( PnPOp, iBufLen, &PnPOp->LowerComponent );
  1055. if (!NT_SUCCESS(Status))
  1056. {
  1057. break;
  1058. }
  1059. Status = ndispConvVar( PnPOp, iBufLen, &PnPOp->UpperComponent );
  1060. if (!NT_SUCCESS(Status))
  1061. {
  1062. break;
  1063. }
  1064. Status = ndispConvVar( PnPOp, iBufLen, &PnPOp->BindList );
  1065. if (!NT_SUCCESS(Status))
  1066. {
  1067. break;
  1068. }
  1069. Status = ndispConvOffsetToPointer( PnPOp,
  1070. iBufLen,
  1071. &PnPOp->ReConfigBufferOff,
  1072. PnPOp->ReConfigBufferSize,
  1073. sizeof(ULONG_PTR) );
  1074. if (!NT_SUCCESS(Status))
  1075. {
  1076. break;
  1077. }
  1078. Status = ndisHandleUModePnPOp(PnPOp);
  1079. break;
  1080. case IOCTL_NDIS_ENUMERATE_INTERFACES:
  1081. if (oBufLen >= sizeof(NDIS_ENUM_INTF))
  1082. {
  1083. EnumIntf = (PNDIS_ENUM_INTF)pBuf;
  1084. Status = ndisEnumerateInterfaces(pBuf, oBufLen, &OutputLength);
  1085. }
  1086. else
  1087. {
  1088. Status = STATUS_BUFFER_TOO_SMALL;
  1089. }
  1090. pIrp->IoStatus.Information = OutputLength;
  1091. break;
  1092. case IOCTL_NDIS_GET_VERSION:
  1093. if (oBufLen < sizeof(UINT))
  1094. {
  1095. Status = STATUS_BUFFER_TOO_SMALL;
  1096. }
  1097. else
  1098. {
  1099. *((PUINT)pBuf) = NdisGetVersion();
  1100. OutputLength = sizeof(UINT);
  1101. if (oBufLen >= 2 * sizeof(UINT))
  1102. {
  1103. *((PUINT)pBuf + 1) = (UINT)ndisChecked;
  1104. OutputLength += sizeof(UINT);
  1105. }
  1106. Status = STATUS_SUCCESS;
  1107. }
  1108. pIrp->IoStatus.Information = OutputLength;
  1109. break;
  1110. default:
  1111. break;
  1112. }
  1113. ASSERT (CURRENT_IRQL < DISPATCH_LEVEL);
  1114. return Status;
  1115. }
  1116. NTSTATUS
  1117. FASTCALL
  1118. ndisHandleUModePnPOp(
  1119. IN PNDIS_PNP_OPERATION PnPOp
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Arguments:
  1124. Return Value:
  1125. --*/
  1126. {
  1127. NTSTATUS Status;
  1128. PUNICODE_STRING Protocol, Device, BindList;
  1129. WAIT_FOR_OBJECT(&ndisPnPMutex, NULL);
  1130. ndisPnPMutexOwner = MODULE_NUMBER + __LINE__;
  1131. //
  1132. // Upcase the protocol and device names
  1133. //
  1134. Protocol = (PUNICODE_STRING)&PnPOp->UpperComponent;
  1135. Device = (PUNICODE_STRING)&PnPOp->LowerComponent;
  1136. BindList = (PUNICODE_STRING)&PnPOp->BindList;
  1137. if (PnPOp->Operation == BIND)
  1138. {
  1139. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1140. ("BIND (%s) %Z to %Z\n", (PnPOp->Layer == NDIS) ? "NDIS" : "TDI ", Protocol, Device));
  1141. }
  1142. else if (PnPOp->Operation == UNBIND)
  1143. {
  1144. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1145. ("UNBIND(%s) %Z to %Z\n", (PnPOp->Layer == NDIS) ? "NDIS" : "TDI ", Protocol, Device));
  1146. }
  1147. switch (PnPOp->Layer)
  1148. {
  1149. case TDI:
  1150. //
  1151. // Call into the TDI handler to do this
  1152. //
  1153. if (ndisTdiPnPHandler != NULL)
  1154. {
  1155. Status = (*ndisTdiPnPHandler)(Protocol,
  1156. Device,
  1157. BindList,
  1158. PnPOp->ReConfigBufferPtr,
  1159. PnPOp->ReConfigBufferSize,
  1160. PnPOp->Operation);
  1161. }
  1162. else
  1163. {
  1164. Status = STATUS_UNSUCCESSFUL;
  1165. }
  1166. break;
  1167. case NDIS:
  1168. switch (PnPOp->Operation)
  1169. {
  1170. case BIND:
  1171. Status = ndisHandleProtocolBindNotification(Device, Protocol);
  1172. break;
  1173. case UNBIND:
  1174. Status = ndisHandleProtocolUnbindNotification(Device, Protocol);
  1175. break;
  1176. case RECONFIGURE:
  1177. case BIND_LIST:
  1178. //1 for BIND_LIST, validate the buffer to have the correct format
  1179. Status = ndisHandleProtocolReconfigNotification(Device,
  1180. Protocol,
  1181. PnPOp->ReConfigBufferPtr,
  1182. PnPOp->ReConfigBufferSize,
  1183. PnPOp->Operation);
  1184. break;
  1185. case UNLOAD:
  1186. Status = ndisHandleProtocolUnloadNotification(Protocol);
  1187. break;
  1188. //1 check to see when this is called
  1189. case REMOVE_DEVICE:
  1190. Status = ndisHandleOrphanDevice(Device);
  1191. break;
  1192. default:
  1193. Status = STATUS_INVALID_PARAMETER;
  1194. break;
  1195. }
  1196. break;
  1197. default:
  1198. Status = STATUS_INVALID_PARAMETER;
  1199. break;
  1200. }
  1201. ndisPnPMutexOwner = 0;
  1202. RELEASE_MUTEX(&ndisPnPMutex);
  1203. return Status;
  1204. }
  1205. NTSTATUS
  1206. FASTCALL
  1207. ndisHandleProtocolBindNotification(
  1208. IN PUNICODE_STRING DeviceName,
  1209. IN PUNICODE_STRING ProtocolName
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. Given a erotocol's name and an adapter's name, this routine creates a binding between
  1214. a protocol and an adapter (assuming protocol has a BindAdapterHandler)
  1215. Arguments:
  1216. DeviceName: Adapter device name i.e. \Device\{GUID}
  1217. ProtocolName Protocols name i.e. TCPIP
  1218. Return Value:
  1219. STATUS_SUCCESS if we could call BindAdapterHandler
  1220. STATUS_UNSUCCESSFUL otherwise
  1221. Note
  1222. This routine does not return the status of attempted bind, rather if it -could- attempt to bind!
  1223. --*/
  1224. {
  1225. //1 check to see if this routine should return back the status of attempted bind
  1226. NTSTATUS Status = STATUS_SUCCESS;
  1227. PNDIS_PROTOCOL_BLOCK Protocol = NULL;
  1228. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  1229. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1230. ("==>ndisHandleProtocolBindNotification\n"));
  1231. do
  1232. {
  1233. ndisReferenceMiniportByName(DeviceName, &Miniport);
  1234. if (Miniport == NULL)
  1235. {
  1236. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1237. break;
  1238. }
  1239. //
  1240. // Map ProtocolName to the Protocol block
  1241. //
  1242. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, FALSE);
  1243. if (!NT_SUCCESS(Status))
  1244. {
  1245. Protocol = NULL;
  1246. Status = STATUS_SUCCESS;
  1247. break;
  1248. }
  1249. //
  1250. // Bind this protocols
  1251. //
  1252. ndisCheckAdapterBindings(Miniport, Protocol);
  1253. } while (FALSE);
  1254. if (Protocol != NULL)
  1255. {
  1256. ndisDereferenceProtocol(Protocol, FALSE);
  1257. }
  1258. if (Miniport != NULL)
  1259. {
  1260. MINIPORT_DECREMENT_REF(Miniport);
  1261. }
  1262. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1263. ("<==ndisHandleProtocolBindNotification\n"));
  1264. return Status;
  1265. }
  1266. NTSTATUS
  1267. FASTCALL
  1268. ndisHandleProtocolUnbindNotification(
  1269. IN PUNICODE_STRING DeviceName,
  1270. IN PUNICODE_STRING ProtocolName
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. Arguments:
  1275. Return Value:
  1276. --*/
  1277. {
  1278. NTSTATUS Status;
  1279. PNDIS_OPEN_BLOCK Open;
  1280. PNDIS_PROTOCOL_BLOCK Protocol = NULL;
  1281. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  1282. //1 change the name of fPartial variable. what this does is to keep track
  1283. //1 of whether or not we are running our partial search for the first
  1284. //1 time or not.
  1285. BOOLEAN fPartial = FALSE;
  1286. KIRQL OldIrql;
  1287. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1288. ("==>ndisHandleProtocolUnbindNotification\n"));
  1289. do
  1290. {
  1291. //
  1292. // Map ProtocolName to the Protocol block
  1293. //
  1294. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, FALSE);
  1295. if (!NT_SUCCESS(Status))
  1296. {
  1297. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1298. ("ndisHandleProtocolUnbindNotification: ndisReferenceProtocolByName failed %lx\n", Status));
  1299. Status = STATUS_SUCCESS;
  1300. Protocol = NULL;
  1301. break;
  1302. }
  1303. //1 add comments what this loop does
  1304. do
  1305. {
  1306. //1 add comments what this call does
  1307. Open = ndisMapOpenByName(DeviceName, Protocol, TRUE);
  1308. if (Open == NULL)
  1309. {
  1310. //
  1311. // There is no -active- binding between this adapter and protocol.
  1312. // This would normally be an error but we need one special case for
  1313. // TCP/IP Arp modules. We can unbind notifications for TCP/IP which
  1314. // are actually destined for the ARP module.
  1315. // We also know that either TCP/IP or ONE and ONLY ONE arp module can be
  1316. // bound to an adapter. Make use of that knowledge.
  1317. //
  1318. ndisDereferenceProtocol(Protocol, FALSE);
  1319. if (!fPartial)
  1320. {
  1321. fPartial = TRUE;
  1322. Protocol = NULL;
  1323. }
  1324. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, TRUE);
  1325. if (!NT_SUCCESS(Status))
  1326. {
  1327. break;
  1328. }
  1329. }
  1330. } while (Open == NULL);
  1331. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1332. ("ndisHandleProtocolUnbindNotification: Open %p\n", Open));
  1333. if (Open != NULL)
  1334. {
  1335. Miniport = Open->MiniportHandle;
  1336. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1337. ndisMDereferenceOpen(Open);
  1338. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1339. Status = ndisUnbindProtocol(Open, Protocol, Miniport, TRUE);
  1340. if (Status != NDIS_STATUS_SUCCESS)
  1341. {
  1342. PNDIS_OPEN_BLOCK tmpOpen;
  1343. //
  1344. // check to see if the open is still there and if it is
  1345. // clear the UNBIND flag. Note that we were the one
  1346. // setting the flag, so we can clear it ourselves
  1347. //
  1348. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1349. for (tmpOpen = Protocol->OpenQueue;
  1350. tmpOpen != NULL;
  1351. tmpOpen = tmpOpen->ProtocolNextOpen)
  1352. {
  1353. if(tmpOpen == Open)
  1354. {
  1355. ACQUIRE_SPIN_LOCK_DPC(&Open->SpinLock);
  1356. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  1357. fMINIPORT_OPEN_DONT_FREE |
  1358. fMINIPORT_OPEN_PROCESSING);
  1359. RELEASE_SPIN_LOCK_DPC(&Open->SpinLock);
  1360. break;
  1361. }
  1362. }
  1363. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1364. }
  1365. }
  1366. } while (FALSE);
  1367. if (Miniport != NULL)
  1368. {
  1369. MINIPORT_DECREMENT_REF(Miniport);
  1370. }
  1371. if (Protocol != NULL)
  1372. {
  1373. ndisDereferenceProtocol(Protocol, FALSE);
  1374. }
  1375. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1376. ("<==ndisHandleProtocolUnbindNotification: Protocol %p, Status %lx\n", Protocol, Status));
  1377. return Status;
  1378. }
  1379. NTSTATUS
  1380. ndisHandleProtocolReconfigNotification(
  1381. IN PUNICODE_STRING DeviceName,
  1382. IN PUNICODE_STRING ProtocolName,
  1383. IN PVOID ReConfigBuffer,
  1384. IN UINT ReConfigBufferSize,
  1385. IN UINT Operation
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. This routine will notify protocols of a change in their configuration -or-
  1390. their bind list.
  1391. This routine can also be called to notify protocols of a change in bind list
  1392. Arguments:
  1393. DeviceName: Adapter's name (if specified). if NULL, it means the change is global and not bind specific
  1394. ProtocolName: Protocol's name
  1395. ReConfigBuffer: information buffer
  1396. ReConfigBufferSize: Information buffer size
  1397. Operation: RECONFIGURE or BIND_LIST
  1398. Return Value:
  1399. --*/
  1400. {
  1401. NTSTATUS Status;
  1402. KIRQL OldIrql;
  1403. PNDIS_PROTOCOL_BLOCK Protocol = NULL;
  1404. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  1405. PNDIS_OPEN_BLOCK Open = NULL;
  1406. NET_PNP_EVENT NetPnpEvent;
  1407. PNDIS_PNP_EVENT_RESERVED EventReserved;
  1408. KEVENT Event;
  1409. BOOLEAN fPartial = FALSE;
  1410. BOOLEAN DeRefOpen = FALSE;
  1411. BOOLEAN DeRefMiniport = FALSE;
  1412. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1413. ("==>ndisHandleProtocolReconfigNotification\n"));
  1414. do
  1415. {
  1416. //
  1417. // Map ProtocolName to the Protocol block
  1418. //
  1419. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, FALSE);
  1420. if (!NT_SUCCESS(Status))
  1421. {
  1422. Protocol = NULL;
  1423. break;
  1424. }
  1425. //
  1426. // We can be passed a NULL device-name which implies global reconfig and we call
  1427. // the protocol's event handler with a NULL BindingContext
  1428. //
  1429. if (DeviceName->Length != 0)
  1430. {
  1431. ASSERT(Operation == RECONFIGURE);
  1432. do
  1433. {
  1434. WAIT_FOR_PROTO_MUTEX(Protocol);
  1435. Open = ndisMapOpenByName(DeviceName, Protocol, FALSE);
  1436. if (Open == NULL)
  1437. {
  1438. RELEASE_PROT_MUTEX(Protocol);
  1439. //
  1440. // There is no -active- binding between this adapter and protocol.
  1441. // This would normally be an error but we need one special case for
  1442. // TCP/IP Arp modules. We can unbind notifications for TCP/IP which
  1443. // are actually destined for the ARP module.
  1444. // We also know that either TCP/IP or ONE and ONLY ONE arp module can be
  1445. // bound to an adapter. Make use of that knowledge.
  1446. //
  1447. ndisDereferenceProtocol(Protocol, FALSE);
  1448. if (!fPartial)
  1449. {
  1450. fPartial = TRUE;
  1451. Protocol = NULL;
  1452. }
  1453. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, TRUE);
  1454. if (!NT_SUCCESS(Status))
  1455. {
  1456. break;
  1457. }
  1458. }
  1459. else
  1460. {
  1461. DeRefOpen = TRUE;
  1462. DeRefMiniport = TRUE;
  1463. Miniport = Open->MiniportHandle;
  1464. }
  1465. } while (Open == NULL);
  1466. if (Open == NULL)
  1467. {
  1468. //
  1469. // if Open == NULL we are not holding the protocol mutex
  1470. //
  1471. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1472. break;
  1473. }
  1474. else if (Protocol->ProtocolCharacteristics.PnPEventHandler == NULL)
  1475. {
  1476. //
  1477. // Open is not NULL, we -are- holding the protocol mutex. release
  1478. // it before breaking out
  1479. //
  1480. RELEASE_PROT_MUTEX(Protocol);
  1481. Status = STATUS_UNSUCCESSFUL;
  1482. break;
  1483. }
  1484. }
  1485. else
  1486. {
  1487. //
  1488. // the device is NULL, just grab the protocol mutex
  1489. //
  1490. if (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL)
  1491. {
  1492. WAIT_FOR_PROTO_MUTEX(Protocol);
  1493. }
  1494. else
  1495. {
  1496. Status = STATUS_UNSUCCESSFUL;
  1497. break;
  1498. }
  1499. }
  1500. //
  1501. // Setup the PnPEvent buffer
  1502. //
  1503. NdisZeroMemory(&NetPnpEvent, sizeof(NetPnpEvent));
  1504. Status = STATUS_SUCCESS;
  1505. switch (Operation)
  1506. {
  1507. case RECONFIGURE:
  1508. NetPnpEvent.NetEvent = NetEventReconfigure;
  1509. break;
  1510. case BIND_LIST:
  1511. NetPnpEvent.NetEvent = NetEventBindList;
  1512. break;
  1513. default:
  1514. ASSERT(FALSE);
  1515. Status = STATUS_INVALID_DEVICE_REQUEST;
  1516. break;
  1517. }
  1518. if (Status == STATUS_INVALID_DEVICE_REQUEST)
  1519. {
  1520. break;
  1521. }
  1522. NetPnpEvent.Buffer = ReConfigBuffer;
  1523. NetPnpEvent.BufferLength = ReConfigBufferSize;
  1524. //
  1525. // Get a pointer to the NDIS reserved are in the PnP event.
  1526. //
  1527. EventReserved = PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent);
  1528. INITIALIZE_EVENT(&Event);
  1529. EventReserved->pEvent = &Event;
  1530. //
  1531. // Notify the protocol now
  1532. //
  1533. Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(
  1534. (Open != NULL) ? Open->ProtocolBindingContext : NULL,
  1535. &NetPnpEvent);
  1536. if (Status == NDIS_STATUS_PENDING)
  1537. {
  1538. //
  1539. // Wait for completion.
  1540. //
  1541. WAIT_FOR_PROTOCOL(Protocol, &Event);
  1542. //
  1543. // Get the completion status.
  1544. //
  1545. Status = EventReserved->Status;
  1546. }
  1547. //
  1548. // IPX may return NDIS_STATUS_NOT_ACCEPTED to ask NDIS to
  1549. // Unbind/Bind the adapter. In this case, Open cannot be NULL.
  1550. //
  1551. if (Status != NDIS_STATUS_NOT_ACCEPTED)
  1552. {
  1553. if (Open)
  1554. {
  1555. ACQUIRE_SPIN_LOCK(&Open->SpinLock, &OldIrql);
  1556. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_PROCESSING);
  1557. RELEASE_SPIN_LOCK(&Open->SpinLock, OldIrql);
  1558. }
  1559. RELEASE_PROT_MUTEX(Protocol);
  1560. break;
  1561. }
  1562. RELEASE_PROT_MUTEX(Protocol);
  1563. ASSERT(DeRefOpen);
  1564. //
  1565. // Ndis need to Unbind/Bind the adapter for the protocol(Especially for IPX)
  1566. //
  1567. ACQUIRE_SPIN_LOCK(&Open->SpinLock, &OldIrql);
  1568. //
  1569. // If the open has gotten a unbind anyway, just return success and don't
  1570. // need to unbind/bind.
  1571. //
  1572. if (OPEN_TEST_FLAG(Open, fMINIPORT_OPEN_UNBINDING | fMINIPORT_OPEN_CLOSING))
  1573. {
  1574. RELEASE_SPIN_LOCK(&Open->SpinLock, OldIrql);
  1575. Status = NDIS_STATUS_SUCCESS;
  1576. break;
  1577. }
  1578. //
  1579. // Going to Unbind the adaper
  1580. //
  1581. OPEN_SET_FLAG(Open, fMINIPORT_OPEN_UNBINDING | fMINIPORT_OPEN_DONT_FREE);
  1582. RELEASE_SPIN_LOCK(&Open->SpinLock, OldIrql);
  1583. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1584. ndisMDereferenceOpen(Open);
  1585. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1586. DeRefOpen = FALSE;
  1587. Status = ndisUnbindProtocol(Open, Protocol, Miniport, FALSE);
  1588. //
  1589. // If cannot unbind the adapter
  1590. //
  1591. if (Status != NDIS_STATUS_SUCCESS)
  1592. {
  1593. PNDIS_OPEN_BLOCK tmpOpen;
  1594. //
  1595. // check to see if the open is still there and if it is
  1596. // clear the UNBIND flag. Note that we were the one
  1597. // setting the flag, so we can clear it ourselves
  1598. //
  1599. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1600. for (tmpOpen = Protocol->OpenQueue;
  1601. tmpOpen != NULL;
  1602. tmpOpen = tmpOpen->ProtocolNextOpen)
  1603. {
  1604. if(tmpOpen == Open)
  1605. {
  1606. ACQUIRE_SPIN_LOCK_DPC(&Open->SpinLock);
  1607. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  1608. fMINIPORT_OPEN_DONT_FREE |
  1609. fMINIPORT_OPEN_PROCESSING);
  1610. RELEASE_SPIN_LOCK_DPC(&Open->SpinLock);
  1611. break;
  1612. }
  1613. }
  1614. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1615. break;
  1616. }
  1617. //
  1618. // Then bind the adapter again.
  1619. //
  1620. ndisCheckAdapterBindings(Miniport, Protocol);
  1621. } while (FALSE);
  1622. if (DeRefOpen)
  1623. {
  1624. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1625. ndisMDereferenceOpen(Open);
  1626. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1627. }
  1628. if (Protocol != NULL)
  1629. {
  1630. ndisDereferenceProtocol(Protocol, FALSE);
  1631. }
  1632. if (DeRefMiniport)
  1633. {
  1634. MINIPORT_DECREMENT_REF(Miniport);
  1635. }
  1636. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1637. ("<==ndisHandleProtocolReconfigNotification\n"));
  1638. return Status;
  1639. }
  1640. NTSTATUS
  1641. FASTCALL
  1642. ndisHandleProtocolUnloadNotification(
  1643. IN PUNICODE_STRING ProtocolName
  1644. )
  1645. /*++
  1646. Routine Description:
  1647. Arguments:
  1648. Return Value:
  1649. --*/
  1650. {
  1651. NTSTATUS Status;
  1652. PNDIS_PROTOCOL_BLOCK Protocol = NULL;
  1653. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1654. ("==>ndisHandleProtocolUnloadNotification\n"));
  1655. //
  1656. // Map ProtocolName to the Protocol block
  1657. //
  1658. Status = ndisReferenceProtocolByName(ProtocolName, &Protocol, FALSE);
  1659. if (NT_SUCCESS(Status))
  1660. {
  1661. ndisDereferenceProtocol(Protocol, FALSE);
  1662. if (Protocol->ProtocolCharacteristics.UnloadHandler != NULL)
  1663. {
  1664. //1 investigate if this can be called with open bindings
  1665. (Protocol->ProtocolCharacteristics.UnloadHandler)();
  1666. }
  1667. else
  1668. {
  1669. Status = STATUS_UNSUCCESSFUL;
  1670. }
  1671. }
  1672. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1673. ("<==ndisHandleProtocolUnloadNotification\n"));
  1674. return Status;
  1675. }
  1676. //1 when do we hit this?
  1677. NTSTATUS
  1678. FASTCALL
  1679. ndisHandleOrphanDevice(
  1680. IN PUNICODE_STRING pDevice
  1681. )
  1682. /*++
  1683. Routine Description:
  1684. Arguments:
  1685. Return Value:
  1686. --*/
  1687. {
  1688. NTSTATUS Status;
  1689. KIRQL OldIrql;
  1690. BOOLEAN fFound = FALSE;
  1691. PNDIS_M_DRIVER_BLOCK MiniBlock;
  1692. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  1693. UNICODE_STRING UpcaseDevice;
  1694. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1695. ("==>ndisHandleOrphanDevice\n"));
  1696. UpcaseDevice.Length = pDevice->Length;
  1697. UpcaseDevice.MaximumLength = pDevice->Length + sizeof(WCHAR);
  1698. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  1699. if (UpcaseDevice.Buffer == NULL)
  1700. {
  1701. return STATUS_INSUFFICIENT_RESOURCES;
  1702. }
  1703. Status = RtlUpcaseUnicodeString(&UpcaseDevice, pDevice, FALSE);
  1704. ASSERT (NT_SUCCESS(Status));
  1705. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  1706. for (MiniBlock = ndisMiniDriverList;
  1707. (MiniBlock != NULL) && !fFound;
  1708. MiniBlock = MiniBlock->NextDriver)
  1709. {
  1710. ACQUIRE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  1711. for (Miniport = MiniBlock->MiniportQueue;
  1712. Miniport != NULL;
  1713. Miniport = Miniport->NextMiniport)
  1714. {
  1715. if (NDIS_EQUAL_UNICODE_STRING(&UpcaseDevice, &Miniport->MiniportName))
  1716. {
  1717. fFound = TRUE;
  1718. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1719. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_ORPHANED);
  1720. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1721. break;
  1722. }
  1723. }
  1724. RELEASE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  1725. }
  1726. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  1727. FREE_POOL(UpcaseDevice.Buffer);
  1728. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1729. ("<==ndisHandleOrphanDevice\n"));
  1730. return STATUS_SUCCESS;
  1731. }
  1732. NTSTATUS
  1733. FASTCALL
  1734. ndisEnumerateInterfaces(
  1735. IN PNDIS_ENUM_INTF EnumIntf,
  1736. IN UINT BufferLength,
  1737. IN PUINT OutputLength
  1738. )
  1739. {
  1740. PNDIS_MINIPORT_BLOCK Miniport;
  1741. PNDIS_M_DRIVER_BLOCK MiniBlock;
  1742. PNDIS_INTERFACE Interface;
  1743. UINT SpaceLeft;
  1744. UINT SpaceNeeded;
  1745. PUCHAR pBuf;
  1746. NTSTATUS Status = STATUS_SUCCESS;
  1747. KIRQL OldIrql;
  1748. do
  1749. {
  1750. *OutputLength = 0;
  1751. if (BufferLength < sizeof(NDIS_ENUM_INTF))
  1752. {
  1753. Status = STATUS_BUFFER_TOO_SMALL;
  1754. break;
  1755. }
  1756. SpaceLeft = BufferLength - sizeof(NDIS_ENUM_INTF);
  1757. NdisZeroMemory(EnumIntf, BufferLength);
  1758. Interface = &EnumIntf->Interface[0];
  1759. pBuf = (PUCHAR)EnumIntf + BufferLength;
  1760. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  1761. for (MiniBlock = ndisMiniDriverList;
  1762. MiniBlock != NULL;
  1763. MiniBlock = MiniBlock->NextDriver)
  1764. {
  1765. ACQUIRE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  1766. for (Miniport = MiniBlock->MiniportQueue;
  1767. Miniport != NULL;
  1768. Miniport = Miniport->NextMiniport)
  1769. {
  1770. if (Miniport->PnPDeviceState != NdisPnPDeviceStarted)
  1771. {
  1772. continue;
  1773. }
  1774. EnumIntf->AvailableInterfaces ++;
  1775. SpaceNeeded = sizeof(NDIS_INTERFACE) +
  1776. Miniport->MiniportName.Length +
  1777. Miniport->pAdapterInstanceName->Length;
  1778. EnumIntf->BytesNeeded += SpaceNeeded;
  1779. if (SpaceLeft >= SpaceNeeded)
  1780. {
  1781. EnumIntf->TotalInterfaces ++;
  1782. SpaceLeft -= SpaceNeeded;
  1783. pBuf -= Miniport->MiniportName.Length;
  1784. Interface->DeviceName.Buffer = (PWSTR)pBuf;
  1785. Interface->DeviceName.MaximumLength =
  1786. Interface->DeviceName.Length = Miniport->MiniportName.Length;
  1787. CopyMemory(pBuf, Miniport->MiniportName.Buffer, Interface->DeviceName.Length);
  1788. POINTER_TO_OFFSET(Interface->DeviceName.Buffer, EnumIntf);
  1789. pBuf -= Miniport->pAdapterInstanceName->Length;
  1790. Interface->DeviceDescription.Buffer = (PWSTR)pBuf;
  1791. Interface->DeviceDescription.MaximumLength =
  1792. Interface->DeviceDescription.Length = Miniport->pAdapterInstanceName->Length;
  1793. CopyMemory(pBuf, Miniport->pAdapterInstanceName->Buffer, Interface->DeviceDescription.Length);
  1794. POINTER_TO_OFFSET(Interface->DeviceDescription.Buffer, EnumIntf);
  1795. Interface ++;
  1796. }
  1797. #if 0
  1798. else
  1799. {
  1800. //
  1801. // we should report the cases that buffer was too small
  1802. //
  1803. //1 for .NET leave the behavior as before (return success)
  1804. //1 because some apps do not handle this properly
  1805. Status = STATUS_BUFFER_TOO_SMALL;
  1806. break;
  1807. }
  1808. #endif
  1809. }
  1810. RELEASE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  1811. if (Status != STATUS_SUCCESS)
  1812. {
  1813. //
  1814. // if we failed, get out
  1815. //
  1816. break;
  1817. }
  1818. }
  1819. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  1820. //
  1821. // since we zero'ed out the entire output buffer and started
  1822. // writing to it from the end, this should be the original output buffer
  1823. // length
  1824. //
  1825. *OutputLength = BufferLength;
  1826. }while (FALSE);
  1827. return Status;
  1828. }
  1829. NTSTATUS
  1830. ndisUnbindProtocol(
  1831. IN PNDIS_OPEN_BLOCK Open,
  1832. IN PNDIS_PROTOCOL_BLOCK Protocol,
  1833. IN PNDIS_MINIPORT_BLOCK Miniport,
  1834. IN BOOLEAN Notify
  1835. )
  1836. /*+++
  1837. Routine Description:
  1838. Arguments:
  1839. Return Value:
  1840. None
  1841. ---*/
  1842. {
  1843. NDIS_STATUS Status = STATUS_SUCCESS;
  1844. NDIS_BIND_CONTEXT UnbindContext;
  1845. PKEVENT CloseCompleteEvent = NULL;
  1846. PNDIS_OPEN_BLOCK TmpOpen = NULL;
  1847. KIRQL OldIrql;
  1848. BOOLEAN fDerefProtocol = FALSE;
  1849. BOOLEAN FreeOpen = FALSE;
  1850. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1851. ("==>ndisUnbindProtocol: Open %p, Notify %d\n", Open, Notify));
  1852. PnPReferencePackage();
  1853. //
  1854. // if this is called outside the context of the protocol deregistering, increment
  1855. // the ref count to make sure the protocol deregisteration does not go through
  1856. // otherwise make note of the fact that we could not increment the ref count and avoid
  1857. // deref at the end
  1858. //
  1859. if (ndisReferenceProtocol(Protocol))
  1860. {
  1861. fDerefProtocol = TRUE;
  1862. }
  1863. WAIT_FOR_PROTO_MUTEX(Protocol);
  1864. do
  1865. {
  1866. //
  1867. // make sure the open didn't go away while we were waiting for
  1868. // protocol mutex.
  1869. //
  1870. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1871. for (TmpOpen = Protocol->OpenQueue;
  1872. TmpOpen != NULL;
  1873. TmpOpen = TmpOpen->ProtocolNextOpen)
  1874. {
  1875. if (TmpOpen == Open)
  1876. break;
  1877. }
  1878. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1879. if (TmpOpen == NULL)
  1880. {
  1881. //
  1882. // open went away while we were trying to get the protocol mutex
  1883. // return right away
  1884. //
  1885. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1886. ("ndisUnbindProtocol: Open %p, Flags %lx was closed while we were waiting for the protocol mutex.\n", Open, Open->Flags));
  1887. break;
  1888. }
  1889. ASSERT(OPEN_TEST_FLAG(Open, fMINIPORT_OPEN_UNBINDING));
  1890. CloseCompleteEvent = Open->CloseCompleteEvent;
  1891. //
  1892. // wait for all AF notifications to go through
  1893. //
  1894. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1895. {
  1896. KEVENT AfNotifyCompleteEvent;
  1897. INITIALIZE_EVENT(&AfNotifyCompleteEvent);
  1898. //1 check to see if we need to get the Open Spinlock here
  1899. Open->AfNotifyCompleteEvent = &AfNotifyCompleteEvent;
  1900. if (Open->PendingAfNotifications != 0)
  1901. {
  1902. WAIT_FOR_OBJECT(Open->AfNotifyCompleteEvent , 0);
  1903. }
  1904. Open->AfNotifyCompleteEvent = NULL;
  1905. }
  1906. //
  1907. // Do a query-remove here first
  1908. //
  1909. if (Notify && (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL))
  1910. {
  1911. NET_PNP_EVENT NetPnpEvent;
  1912. PNDIS_PNP_EVENT_RESERVED EventReserved;
  1913. KEVENT Event;
  1914. RtlZeroMemory(&NetPnpEvent, sizeof(NET_PNP_EVENT));
  1915. INITIALIZE_EVENT(&Event);
  1916. EventReserved = PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent);
  1917. NetPnpEvent.NetEvent = NetEventQueryRemoveDevice;
  1918. NetPnpEvent.Buffer = NULL;
  1919. NetPnpEvent.BufferLength = 0;
  1920. EventReserved->pEvent = &Event;
  1921. //
  1922. // Indicate the event to the protocol.
  1923. //
  1924. Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(
  1925. Open->ProtocolBindingContext,
  1926. &NetPnpEvent);
  1927. if (NDIS_STATUS_PENDING == Status)
  1928. {
  1929. //
  1930. // Wait for completion.
  1931. //
  1932. WAIT_FOR_PROTOCOL(Protocol, &Event);
  1933. //
  1934. // Get the completion status.
  1935. //
  1936. Status = EventReserved->Status;
  1937. }
  1938. //
  1939. // Is the status OK?
  1940. //
  1941. if (Status != NDIS_STATUS_SUCCESS)
  1942. {
  1943. break;
  1944. }
  1945. }
  1946. if (CloseCompleteEvent != NULL)
  1947. {
  1948. INITIALIZE_EVENT(CloseCompleteEvent);
  1949. }
  1950. //
  1951. // Protocol ok with remove so now do it.
  1952. //
  1953. INITIALIZE_EVENT(&UnbindContext.Event);
  1954. Status = NDIS_STATUS_SUCCESS;
  1955. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  1956. (*Protocol->ProtocolCharacteristics.UnbindAdapterHandler)(
  1957. &Status,
  1958. Open->ProtocolBindingContext,
  1959. &UnbindContext);
  1960. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  1961. if (Status == NDIS_STATUS_PENDING)
  1962. {
  1963. WAIT_FOR_PROTOCOL(Protocol, &UnbindContext.Event);
  1964. Status = UnbindContext.BindStatus;
  1965. }
  1966. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1967. ndisNotifyWmiBindUnbind(Miniport, Protocol, FALSE);
  1968. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  1969. if (CloseCompleteEvent != NULL)
  1970. {
  1971. //
  1972. // make sure the open is gone
  1973. //
  1974. WAIT_FOR_PROTOCOL(Protocol, CloseCompleteEvent);
  1975. }
  1976. } while (FALSE);
  1977. RELEASE_PROT_MUTEX(Protocol);
  1978. if (TmpOpen != NULL)
  1979. {
  1980. ACQUIRE_SPIN_LOCK(&Open->SpinLock, &OldIrql);
  1981. //
  1982. // did the close routine get our message not to free the open structure?
  1983. //
  1984. if (OPEN_TEST_FLAG(Open, fMINIPORT_OPEN_CLOSE_COMPLETE))
  1985. {
  1986. //
  1987. // we have to get rid of open ourselves
  1988. //
  1989. FreeOpen = TRUE;
  1990. }
  1991. else
  1992. {
  1993. //
  1994. // for some reason, unbind did not go through or close is
  1995. // still in progress
  1996. //
  1997. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  1998. fMINIPORT_OPEN_DONT_FREE |
  1999. fMINIPORT_OPEN_PROCESSING);
  2000. FreeOpen = FALSE;
  2001. }
  2002. RELEASE_SPIN_LOCK(&Open->SpinLock, OldIrql);
  2003. }
  2004. PnPDereferencePackage();
  2005. if (FreeOpen)
  2006. {
  2007. ndisRemoveOpenFromGlobalList(Open);
  2008. FREE_POOL(Open);
  2009. }
  2010. if (fDerefProtocol)
  2011. {
  2012. ndisDereferenceProtocol(Protocol, FALSE);
  2013. }
  2014. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2015. ("<==ndisUnbindProtocol: Open %p, Notify %d, Status %lx\n", Open, Notify, Status));
  2016. return(Status);
  2017. }
  2018. VOID
  2019. ndisReferenceMiniportByName(
  2020. IN PUNICODE_STRING DeviceName,
  2021. OUT PNDIS_MINIPORT_BLOCK * pMiniport
  2022. )
  2023. {
  2024. KIRQL OldIrql;
  2025. PNDIS_M_DRIVER_BLOCK MiniBlock;
  2026. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  2027. UNICODE_STRING UpcaseDevice;
  2028. UINT Depth = 1;
  2029. DBGPRINT_RAW(DBG_COMP_REF, DBG_LEVEL_INFO,
  2030. ("==>ndisReferenceMiniportByName\n"));
  2031. *pMiniport = NULL;
  2032. UpcaseDevice.Length = DeviceName->Length;
  2033. UpcaseDevice.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  2034. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  2035. if (UpcaseDevice.Buffer == NULL)
  2036. {
  2037. return;
  2038. }
  2039. RtlUpcaseUnicodeString(&UpcaseDevice, DeviceName, FALSE);
  2040. do
  2041. {
  2042. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  2043. for (MiniBlock = ndisMiniDriverList;
  2044. MiniBlock != NULL;
  2045. MiniBlock = MiniBlock->NextDriver)
  2046. {
  2047. ACQUIRE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  2048. for (Miniport = MiniBlock->MiniportQueue;
  2049. Miniport != NULL;
  2050. Miniport = Miniport->NextMiniport)
  2051. {
  2052. if (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_ORPHANED) &&
  2053. (Miniport->BindPaths != NULL) &&
  2054. (Miniport->BindPaths->Number >= Depth) &&
  2055. NDIS_EQUAL_UNICODE_STRING(&UpcaseDevice, &Miniport->BindPaths->Paths[0]))
  2056. {
  2057. if (*pMiniport != NULL)
  2058. {
  2059. MINIPORT_DECREMENT_REF(*pMiniport);
  2060. *pMiniport = NULL;
  2061. }
  2062. Depth = Miniport->BindPaths->Number;
  2063. if (MINIPORT_INCREMENT_REF(Miniport))
  2064. {
  2065. *pMiniport = Miniport;
  2066. }
  2067. break;
  2068. }
  2069. }
  2070. RELEASE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  2071. }
  2072. } while (FALSE);
  2073. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  2074. FREE_POOL(UpcaseDevice.Buffer);
  2075. DBGPRINT_RAW(DBG_COMP_REF, DBG_LEVEL_INFO,
  2076. ("<==ndisReferenceMiniportByName\n"));
  2077. }
  2078. PNDIS_OPEN_BLOCK
  2079. FASTCALL
  2080. ndisMapOpenByName(
  2081. IN PUNICODE_STRING DeviceName,
  2082. IN PNDIS_PROTOCOL_BLOCK Protocol,
  2083. IN BOOLEAN fUnbinding
  2084. )
  2085. /*
  2086. Routine Description:
  2087. ndisMapOpenByName searches a protocol's open queue and tries to find an
  2088. open block that its RootDevice name matches Devicename passed to this function.
  2089. if the Open is found, miniport for that open is referenced. if we are -not-
  2090. trying to unbind the open, we will reference it.
  2091. Arguments:
  2092. DeviceName: RootDevice name of the open.
  2093. Protocol: protocol block to search.
  2094. fUnbinding: whether we are searching for the open so we can close it. if that is
  2095. the case, then some additional checks will be perfomred and the some flags on open
  2096. will be set.
  2097. Return Value:
  2098. Open block or NULL.
  2099. */
  2100. {
  2101. UNICODE_STRING UpcaseDevice;
  2102. PNDIS_OPEN_BLOCK Open, tmpOpen;
  2103. PNDIS_MINIPORT_BLOCK Miniport;
  2104. KIRQL OldIrql;
  2105. BOOLEAN DeRefOpen = FALSE;
  2106. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2107. ("==>ndisReferenceOpenByName, DeviceName %p, Protocol %p, fUnbinding %d\n",
  2108. DeviceName, Protocol, fUnbinding));
  2109. Open = NULL;
  2110. UpcaseDevice.Length = DeviceName->Length;
  2111. UpcaseDevice.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  2112. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  2113. if (UpcaseDevice.Buffer == NULL)
  2114. {
  2115. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2116. ("<==ndisReferenceOpenByName: failed to allocate memory.\n"));
  2117. return NULL;
  2118. }
  2119. RtlUpcaseUnicodeString(&UpcaseDevice, DeviceName, FALSE);
  2120. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  2121. //
  2122. // Now walk the open list and get to the open representing the DeviceName
  2123. //
  2124. for (Open = Protocol->OpenQueue;
  2125. Open != NULL;
  2126. Open = Open->ProtocolNextOpen)
  2127. {
  2128. if (NDIS_EQUAL_UNICODE_STRING(&UpcaseDevice, Open->RootDeviceName))
  2129. {
  2130. tmpOpen = Open;
  2131. ACQUIRE_SPIN_LOCK_DPC(&tmpOpen->SpinLock);
  2132. if (fUnbinding)
  2133. {
  2134. if (OPEN_TEST_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  2135. fMINIPORT_OPEN_CLOSING |
  2136. fMINIPORT_OPEN_PROCESSING))
  2137. {
  2138. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2139. ("ndisReferenceOpenByName: Open %p is already getting unbind\n", Open));
  2140. Open = NULL;
  2141. }
  2142. else
  2143. {
  2144. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  2145. OPEN_SET_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  2146. fMINIPORT_OPEN_DONT_FREE |
  2147. fMINIPORT_OPEN_PROCESSING);
  2148. }
  2149. }
  2150. else
  2151. {
  2152. if (OPEN_TEST_FLAG(Open, fMINIPORT_OPEN_PROCESSING))
  2153. {
  2154. Open = NULL;
  2155. }
  2156. else
  2157. {
  2158. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  2159. OPEN_SET_FLAG(Open, fMINIPORT_OPEN_PROCESSING);
  2160. }
  2161. }
  2162. RELEASE_SPIN_LOCK_DPC(&tmpOpen->SpinLock);
  2163. break;
  2164. }
  2165. }
  2166. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  2167. if (Open != NULL)
  2168. {
  2169. Miniport = Open->MiniportHandle;
  2170. if (!MINIPORT_INCREMENT_REF(Miniport))
  2171. {
  2172. if (fUnbinding)
  2173. {
  2174. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_UNBINDING |
  2175. fMINIPORT_OPEN_PROCESSING |
  2176. fMINIPORT_OPEN_DONT_FREE);
  2177. }
  2178. else
  2179. {
  2180. OPEN_CLEAR_FLAG(Open, fMINIPORT_OPEN_PROCESSING);
  2181. }
  2182. DeRefOpen = TRUE;
  2183. }
  2184. else
  2185. {
  2186. DeRefOpen = FALSE;
  2187. }
  2188. }
  2189. FREE_POOL(UpcaseDevice.Buffer);
  2190. if (DeRefOpen)
  2191. {
  2192. Miniport = Open->MiniportHandle;
  2193. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2194. ndisMDereferenceOpen(Open);
  2195. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2196. Open = NULL;
  2197. }
  2198. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2199. ("<==ndisReferenceOpenByName: Open %p\n", Open ));
  2200. return(Open);
  2201. }
  2202. NTSTATUS
  2203. FASTCALL
  2204. ndisHandleLegacyTransport(
  2205. IN PUNICODE_STRING pDevice
  2206. )
  2207. {
  2208. NTSTATUS Status = STATUS_SUCCESS;
  2209. RTL_QUERY_REGISTRY_TABLE LinkQueryTable[3];
  2210. PWSTR Export = NULL;
  2211. HANDLE TdiHandle;
  2212. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  2213. ("==>ndisHandleLegacyTransport\n"));
  2214. if (ndisTdiRegisterCallback == NULL)
  2215. {
  2216. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  2217. ("<==ndisHandleLegacyTransport\n"));
  2218. return STATUS_UNSUCCESSFUL;
  2219. }
  2220. //
  2221. // Set up LinkQueryTable to do the following:
  2222. //
  2223. //
  2224. // 1) Switch to the Linkage key below the xports registry key
  2225. //
  2226. LinkQueryTable[0].QueryRoutine = NULL;
  2227. LinkQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  2228. LinkQueryTable[0].Name = L"Linkage";
  2229. //
  2230. // 2) Call ndisReadParameter for "Export" (as a single multi-string),
  2231. // which will allocate storage and save the data in Export.
  2232. //
  2233. LinkQueryTable[1].QueryRoutine = ndisReadParameter;
  2234. LinkQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  2235. LinkQueryTable[1].Name = L"Export";
  2236. LinkQueryTable[1].EntryContext = (PVOID)&Export;
  2237. LinkQueryTable[1].DefaultType = REG_NONE;
  2238. //
  2239. // 3) Stop
  2240. //
  2241. LinkQueryTable[2].QueryRoutine = NULL;
  2242. LinkQueryTable[2].Flags = 0;
  2243. LinkQueryTable[2].Name = NULL;
  2244. do
  2245. {
  2246. UNICODE_STRING Us;
  2247. PWSTR CurExport;
  2248. //1 Context parameter probably should be use to verify data type
  2249. Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  2250. pDevice->Buffer,
  2251. LinkQueryTable,
  2252. (PVOID)NULL, // no context needed
  2253. NULL);
  2254. if (!NT_SUCCESS(Status))
  2255. {
  2256. //
  2257. // Do not complain about TDI drivers which do not
  2258. // have any linkages
  2259. //
  2260. if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  2261. {
  2262. Status = STATUS_SUCCESS;
  2263. }
  2264. break;
  2265. }
  2266. //
  2267. // Walk the list of exports and call TdiRegisterDevice for each
  2268. //
  2269. for (CurExport = Export;
  2270. *CurExport != 0;
  2271. CurExport = (PWCHAR)((PUCHAR)CurExport + Us.MaximumLength))
  2272. {
  2273. RtlInitUnicodeString (&Us, CurExport);
  2274. Status = (*ndisTdiRegisterCallback)(&Us, &TdiHandle);
  2275. if (!NT_SUCCESS(Status))
  2276. {
  2277. break;
  2278. }
  2279. }
  2280. } while (FALSE);
  2281. if (Export != NULL)
  2282. FREE_POOL(Export);
  2283. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  2284. ("<==ndisHandleLegacyTransport\n"));
  2285. return(Status);
  2286. }
  2287. VOID
  2288. FASTCALL
  2289. ndisInitializeBinding(
  2290. IN PNDIS_MINIPORT_BLOCK Miniport,
  2291. IN PNDIS_PROTOCOL_BLOCK Protocol
  2292. )
  2293. {
  2294. PUNICODE_STRING ExportName;
  2295. NDIS_BIND_CONTEXT BindContext;
  2296. PDEVICE_OBJECT PhysicalDeviceObject;
  2297. NDIS_STATUS BindStatus;
  2298. UNICODE_STRING ProtocolSection;
  2299. UNICODE_STRING DerivedBaseName, Parms;
  2300. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2301. ("==>ndisInitializeBinding\n"));
  2302. //
  2303. // Call the protocol to bind to the Miniport
  2304. //
  2305. WAIT_FOR_PROTO_MUTEX(Protocol);
  2306. do
  2307. {
  2308. //
  2309. // once we grabbed the protocol mutex, check again to see if
  2310. // the adapter is still there
  2311. //
  2312. if (!ndisIsMiniportStarted(Miniport) ||
  2313. ((Miniport->PnPDeviceState != NdisPnPDeviceStarted) &&
  2314. (Miniport->PnPDeviceState != NdisPnPDeviceQueryStopped) &&
  2315. (Miniport->PnPDeviceState != NdisPnPDeviceQueryRemoved)))
  2316. {
  2317. break;
  2318. }
  2319. if (TRUE == ndisProtocolAlreadyBound(Protocol, Miniport))
  2320. {
  2321. //
  2322. // these two are already bound. just return
  2323. //
  2324. break;
  2325. }
  2326. ExportName = &Miniport->BindPaths->Paths[0];
  2327. Protocol->BindDeviceName = &Miniport->MiniportName;
  2328. Protocol->RootDeviceName = ExportName;
  2329. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  2330. if (ndisReferenceProtocol(Protocol) == FALSE)
  2331. {
  2332. break;
  2333. }
  2334. RtlInitUnicodeString(&Parms, L"\\Parameters\\Adapters\\");
  2335. DerivedBaseName = *ExportName;
  2336. DerivedBaseName.Length -= ndisDeviceStr.Length;
  2337. DerivedBaseName.MaximumLength -= ndisDeviceStr.Length;
  2338. (PUCHAR)(DerivedBaseName.Buffer) += ndisDeviceStr.Length;
  2339. ProtocolSection.MaximumLength = Protocol->ProtocolCharacteristics.Name.Length + // "tcpip"
  2340. Parms.Length + // "\Parameters\Adapters\"
  2341. ExportName->Length - ndisDeviceStr.Length + // "{GUID}"
  2342. sizeof(WCHAR);
  2343. ProtocolSection.Length = 0;
  2344. ProtocolSection.Buffer = (PWSTR)ALLOC_FROM_POOL(ProtocolSection.MaximumLength,
  2345. NDIS_TAG_DEFAULT);
  2346. if (ProtocolSection.Buffer != NULL)
  2347. {
  2348. ZeroMemory(ProtocolSection.Buffer, ProtocolSection.MaximumLength);
  2349. RtlCopyUnicodeString(&ProtocolSection,
  2350. &Protocol->ProtocolCharacteristics.Name);
  2351. RtlAppendUnicodeStringToString(&ProtocolSection,
  2352. &Parms);
  2353. RtlAppendUnicodeStringToString(&ProtocolSection,
  2354. &DerivedBaseName);
  2355. }
  2356. else
  2357. {
  2358. ndisDereferenceProtocol(Protocol, FALSE);
  2359. break;
  2360. }
  2361. BindContext.Next = NULL;
  2362. BindContext.Protocol = Protocol;
  2363. BindContext.Miniport = Miniport;
  2364. BindContext.ProtocolSection = ProtocolSection;
  2365. BindContext.DeviceName = ExportName;
  2366. INITIALIZE_EVENT(&BindContext.Event);
  2367. if (!Protocol->Ref.Closing)
  2368. {
  2369. BindStatus = NDIS_STATUS_SUCCESS;
  2370. Protocol->BindingAdapter = Miniport;
  2371. (*Protocol->ProtocolCharacteristics.BindAdapterHandler)(&BindStatus,
  2372. &BindContext,
  2373. ExportName,
  2374. &ProtocolSection,
  2375. (PVOID)PhysicalDeviceObject);
  2376. if (BindStatus == NDIS_STATUS_PENDING)
  2377. {
  2378. WAIT_FOR_PROTOCOL(Protocol, &BindContext.Event);
  2379. BindStatus = BindContext.BindStatus;
  2380. }
  2381. Protocol->BindingAdapter = NULL;
  2382. if (BindStatus == NDIS_STATUS_SUCCESS)
  2383. {
  2384. ndisNotifyWmiBindUnbind(Miniport, Protocol, TRUE);
  2385. }
  2386. #if DBG
  2387. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2388. (" ndisInitializeBinding\n"));
  2389. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2390. (" Protocol: "));
  2391. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2392. &Protocol->ProtocolCharacteristics.Name);
  2393. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2394. ("\n Adapter: "));
  2395. if (Miniport->pAdapterInstanceName)
  2396. {
  2397. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2398. Miniport->pAdapterInstanceName);
  2399. }
  2400. else
  2401. {
  2402. DBGPRINT_UNICODE(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2403. &Miniport->BaseName);
  2404. }
  2405. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2406. ("\n Result: %lx\n", BindStatus));
  2407. #endif
  2408. }
  2409. FREE_POOL(ProtocolSection.Buffer);
  2410. Protocol->BindDeviceName = NULL;
  2411. ndisDereferenceProtocol(Protocol, FALSE);
  2412. } while (FALSE);
  2413. RELEASE_PROT_MUTEX(Protocol);
  2414. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2415. ("<==ndisInitializeBinding\n"));
  2416. }
  2417. VOID
  2418. NdisCompleteBindAdapter(
  2419. IN NDIS_HANDLE BindAdapterContext,
  2420. IN NDIS_STATUS Status,
  2421. IN NDIS_STATUS OpenStatus
  2422. )
  2423. /*++
  2424. Routine Description:
  2425. Arguments:
  2426. Return Value:
  2427. --*/
  2428. {
  2429. PNDIS_BIND_CONTEXT pContext = (PNDIS_BIND_CONTEXT)BindAdapterContext;
  2430. UNREFERENCED_PARAMETER(OpenStatus);
  2431. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2432. ("==>NdisCompleteBindAdapter\n"));
  2433. pContext->BindStatus = Status;
  2434. SET_EVENT(&pContext->Event);
  2435. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2436. ("<==NdisCompleteBindAdapter\n"));
  2437. }
  2438. VOID
  2439. NdisCompleteUnbindAdapter(
  2440. IN NDIS_HANDLE UnbindAdapterContext,
  2441. IN NDIS_STATUS Status
  2442. )
  2443. /*++
  2444. Routine Description:
  2445. Arguments:
  2446. Return Value:
  2447. --*/
  2448. {
  2449. PNDIS_BIND_CONTEXT pContext = (PNDIS_BIND_CONTEXT)UnbindAdapterContext;
  2450. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2451. ("==>NdisCompleteUnbindAdapter\n"));
  2452. pContext->BindStatus = Status;
  2453. SET_EVENT(&pContext->Event);
  2454. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  2455. ("<==NdisCompleteUnbindAdapter\n"));
  2456. }
  2457. VOID
  2458. NdisRegisterTdiCallBack(
  2459. IN TDI_REGISTER_CALLBACK RegisterCallback,
  2460. IN TDI_PNP_HANDLER PnPHandler
  2461. )
  2462. /*++
  2463. Routine Description:
  2464. Arguments:
  2465. Return Value:
  2466. --*/
  2467. {
  2468. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2469. ("==>NdisRegisterTdiCallBack\n"));
  2470. if (ndisTdiRegisterCallback == NULL)
  2471. {
  2472. ndisTdiRegisterCallback = RegisterCallback;
  2473. }
  2474. if (ndisTdiPnPHandler == NULL)
  2475. {
  2476. ndisTdiPnPHandler = PnPHandler;
  2477. }
  2478. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2479. ("<==NdisRegisterTdiCallBack\n"));
  2480. }
  2481. VOID
  2482. NdisDeregisterTdiCallBack(
  2483. VOID
  2484. )
  2485. {
  2486. ndisTdiRegisterCallback = NULL;
  2487. ndisTdiPnPHandler = NULL;
  2488. }
  2489. VOID
  2490. ndisFindRootDevice(
  2491. IN PNDIS_STRING DeviceName,
  2492. IN BOOLEAN fTester,
  2493. OUT PNDIS_STRING * pBindDevice,
  2494. OUT PNDIS_STRING * pRootDevice,
  2495. OUT PNDIS_MINIPORT_BLOCK * pAdapter
  2496. )
  2497. /*++
  2498. Routine Description:
  2499. Find the Miniport which is the highest level filter given the target root name.
  2500. Arguments:
  2501. Return Value:
  2502. --*/
  2503. {
  2504. KIRQL OldIrql;
  2505. PNDIS_M_DRIVER_BLOCK MiniBlock;
  2506. PNDIS_MINIPORT_BLOCK Miniport;
  2507. PNDIS_STRING RootDevice = NULL, BindDevice = NULL;
  2508. NDIS_STRING UpcaseDevice;
  2509. PWSTR pwch;
  2510. UINT Depth = 1;
  2511. BOOLEAN Found = FALSE;
  2512. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2513. ("==>ndisFindRootDevice\n"));
  2514. *pBindDevice = NULL;
  2515. *pRootDevice = NULL;
  2516. *pAdapter = NULL;
  2517. //
  2518. // First we need to upcase the device-name before checking
  2519. //
  2520. UpcaseDevice.Length = DeviceName->Length;
  2521. UpcaseDevice.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  2522. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  2523. if ((pwch = UpcaseDevice.Buffer) == NULL)
  2524. {
  2525. return;
  2526. }
  2527. RtlUpcaseUnicodeString(&UpcaseDevice, DeviceName, FALSE);
  2528. BindDevice = &UpcaseDevice;
  2529. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  2530. PnPReferencePackage();
  2531. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  2532. for (MiniBlock = ndisMiniDriverList;
  2533. MiniBlock != NULL;
  2534. MiniBlock = MiniBlock->NextDriver)
  2535. {
  2536. ACQUIRE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  2537. for (Miniport = MiniBlock->MiniportQueue;
  2538. Miniport != NULL;
  2539. Miniport = Miniport->NextMiniport)
  2540. {
  2541. if (fTester)
  2542. {
  2543. if (NDIS_EQUAL_UNICODE_STRING(BindDevice, &Miniport->MiniportName))
  2544. {
  2545. BindDevice = &Miniport->MiniportName;
  2546. RootDevice = &Miniport->MiniportName;
  2547. *pAdapter = Miniport;
  2548. Found = TRUE;
  2549. break;
  2550. }
  2551. }
  2552. else if ((Miniport->BindPaths->Number >= Depth) &&
  2553. NDIS_EQUAL_UNICODE_STRING(BindDevice, &Miniport->BindPaths->Paths[0]))
  2554. {
  2555. RootDevice = &Miniport->BindPaths->Paths[0];
  2556. BindDevice = &Miniport->MiniportName;
  2557. *pAdapter = Miniport;
  2558. Depth = Miniport->BindPaths->Number;
  2559. Found = TRUE;
  2560. }
  2561. }
  2562. RELEASE_SPIN_LOCK_DPC(&MiniBlock->Ref.SpinLock);
  2563. if (fTester && Found)
  2564. {
  2565. break;
  2566. }
  2567. }
  2568. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  2569. PnPDereferencePackage();
  2570. FREE_POOL(pwch);
  2571. if (Found)
  2572. {
  2573. *pBindDevice = BindDevice;
  2574. *pRootDevice = RootDevice;
  2575. }
  2576. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2577. ("<==ndisFindRootDevice\n"));
  2578. }
  2579. VOID
  2580. ndisNotifyWmiBindUnbind(
  2581. PNDIS_MINIPORT_BLOCK Miniport,
  2582. PNDIS_PROTOCOL_BLOCK Protocol,
  2583. BOOLEAN fBind
  2584. )
  2585. /*++
  2586. Routine Description:
  2587. Notify WMI that either a bind or an unbind has occured.
  2588. Arguments:
  2589. Return Value:
  2590. --*/
  2591. {
  2592. PWNODE_SINGLE_INSTANCE wnode;
  2593. PUCHAR ptmp;
  2594. NTSTATUS NtStatus;
  2595. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2596. ("==>ndisNotifyWmiBindUnbind: Miniport %p, Protocol %p, fBind %lx\n", Miniport, Protocol, fBind));
  2597. ndisSetupWmiNode(Miniport,
  2598. Miniport->pAdapterInstanceName,
  2599. Miniport->BindPaths->Paths[0].Length + sizeof(WCHAR) +
  2600. Protocol->ProtocolCharacteristics.Name.Length + sizeof(WCHAR),
  2601. fBind ? (PVOID)&GUID_NDIS_NOTIFY_BIND : (PVOID)&GUID_NDIS_NOTIFY_UNBIND,
  2602. &wnode);
  2603. if (wnode != NULL)
  2604. {
  2605. //
  2606. // Save the number of elements in the first ULONG.
  2607. //
  2608. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  2609. //
  2610. // Copy the data which is the protocol name + the miniport name in the data field
  2611. // Protocol<NULL>MiniportName<NULL>
  2612. //
  2613. RtlCopyMemory(ptmp,
  2614. Protocol->ProtocolCharacteristics.Name.Buffer,
  2615. Protocol->ProtocolCharacteristics.Name.Length);
  2616. RtlCopyMemory(ptmp + Protocol->ProtocolCharacteristics.Name.Length + sizeof(WCHAR),
  2617. Miniport->BindPaths->Paths[0].Buffer,
  2618. Miniport->BindPaths->Paths[0].Length);
  2619. //
  2620. // notify kernel mode components who have registered for Ndis BindUnbind event
  2621. //
  2622. if (ndisBindUnbindCallbackObject != NULL)
  2623. {
  2624. ExNotifyCallback(ndisBindUnbindCallbackObject,
  2625. (PVOID)wnode,
  2626. NULL);
  2627. }
  2628. //
  2629. // Indicate the event to WMI. WMI will take care of freeing
  2630. // the WMI struct back to pool.
  2631. //
  2632. NtStatus = IoWMIWriteEvent(wnode);
  2633. if (!NT_SUCCESS(NtStatus))
  2634. {
  2635. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2636. ("IoWMIWriteEvent failed %lx\n", NtStatus));
  2637. FREE_POOL(wnode);
  2638. }
  2639. }
  2640. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2641. ("<==ndisNotifyWmiBindUnbind: Miniport %p, Protocol %p, fBind %lx\n", Miniport, Protocol, fBind));
  2642. return;
  2643. }
  2644. VOID
  2645. ndisNotifyDevicePowerStateChange(
  2646. PNDIS_MINIPORT_BLOCK Miniport,
  2647. NDIS_DEVICE_POWER_STATE PowerState
  2648. )
  2649. /*++
  2650. Routine Description:
  2651. Notify WMI that that the power state of a NIC is changed.
  2652. Arguments:
  2653. Return Value:
  2654. --*/
  2655. {
  2656. PWNODE_SINGLE_INSTANCE wnode;
  2657. PUCHAR ptmp;
  2658. NTSTATUS NtStatus;
  2659. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2660. ("==>ndisNotifyDevicePowerStateChange: Miniport %p, PowerState %lx\n", Miniport, PowerState));
  2661. ndisSetupWmiNode(Miniport,
  2662. Miniport->pAdapterInstanceName,
  2663. Miniport->MiniportName.Length + sizeof(WCHAR),
  2664. (PowerState == NdisDeviceStateD0) ? (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_ON : (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_OFF,
  2665. &wnode);
  2666. if (wnode != NULL)
  2667. {
  2668. //
  2669. // Save the number of elements in the first ULONG.
  2670. //
  2671. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  2672. RtlCopyMemory(ptmp,
  2673. Miniport->MiniportName.Buffer,
  2674. Miniport->MiniportName.Length);
  2675. //
  2676. // Indicate the event to WMI. WMI will take care of freeing
  2677. // the WMI struct back to pool.
  2678. //
  2679. NtStatus = IoWMIWriteEvent(wnode);
  2680. if (!NT_SUCCESS(NtStatus))
  2681. {
  2682. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2683. ("IoWMIWriteEvent failed %lx\n", NtStatus));
  2684. FREE_POOL(wnode);
  2685. }
  2686. }
  2687. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2688. ("<==ndisNotifyDevicePowerStateChange: Miniport %p, PowerState %lx\n", Miniport, PowerState));
  2689. return;
  2690. }
  2691. BOOLEAN
  2692. NdisMatchPdoWithPacket(
  2693. IN PNDIS_PACKET Packet,
  2694. IN PVOID Pdo
  2695. )
  2696. {
  2697. PNDIS_STACK_RESERVED NSR;
  2698. PNDIS_MINIPORT_BLOCK Miniport;
  2699. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  2700. Miniport = NSR->Miniport;
  2701. return (Pdo == Miniport->PhysicalDeviceObject);
  2702. }
  2703. VOID
  2704. ndisPowerStateCallback(
  2705. PVOID CallBackContext,
  2706. PVOID Argument1,
  2707. PVOID Argument2
  2708. )
  2709. {
  2710. ULONG Action = (ULONG)((ULONG_PTR)Argument1);
  2711. ULONG State = (ULONG)((ULONG_PTR)Argument2);
  2712. NDIS_POWER_PROFILE PowerProfile;
  2713. UNREFERENCED_PARAMETER(CallBackContext);
  2714. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2715. ("==>ndisPowerStateCallback: Action %lx, State %lx\n", Action, State));
  2716. if (Action == PO_CB_AC_STATUS)
  2717. {
  2718. ndisAcOnLine = State;
  2719. PowerProfile = ((BOOLEAN)ndisAcOnLine == TRUE) ? NdisPowerProfileAcOnLine : NdisPowerProfileBattery;
  2720. ndisNotifyMiniports((PNDIS_MINIPORT_BLOCK)NULL,
  2721. NdisDevicePnPEventPowerProfileChanged,
  2722. &PowerProfile,
  2723. sizeof(NDIS_POWER_PROFILE));
  2724. }
  2725. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2726. ("<==ndisPowerStateCallback: Action %lx, State %lx\n", Action, State));
  2727. }
  2728. VOID
  2729. ndisNotifyMiniports(
  2730. IN PNDIS_MINIPORT_BLOCK Miniport OPTIONAL,
  2731. IN NDIS_DEVICE_PNP_EVENT DevicePnPEvent,
  2732. IN PVOID Buffer,
  2733. IN ULONG Length
  2734. )
  2735. {
  2736. PNDIS_M_DRIVER_BLOCK MiniBlock, NextMiniBlock;
  2737. PNDIS_MINIPORT_BLOCK CurMiniport;
  2738. KIRQL OldIrql;
  2739. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2740. ("==>ndisNotifyMiniportsPowerProfileChange: Miniport %p, Event %lx, Buffer %p\n",
  2741. Miniport,
  2742. DevicePnPEvent,
  2743. Buffer));
  2744. PnPReferencePackage();
  2745. do
  2746. {
  2747. if (Miniport)
  2748. {
  2749. if(Miniport->DriverHandle->MiniportCharacteristics.PnPEventNotifyHandler != NULL)
  2750. {
  2751. //
  2752. // if Miniport has been specified, the caller is responsible to make sure it is valid and appropriate
  2753. // to call the miniport
  2754. //
  2755. Miniport->DriverHandle->MiniportCharacteristics.PnPEventNotifyHandler(Miniport->MiniportAdapterContext,
  2756. DevicePnPEvent,
  2757. Buffer,
  2758. Length);
  2759. }
  2760. break;
  2761. }
  2762. //
  2763. // notification is for all the miniports
  2764. //
  2765. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  2766. for (MiniBlock = ndisMiniDriverList;
  2767. MiniBlock != NULL;
  2768. MiniBlock = NextMiniBlock)
  2769. {
  2770. if (ndisReferenceDriver(MiniBlock))
  2771. {
  2772. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  2773. while ((CurMiniport = ndisReferenceNextUnprocessedMiniport(MiniBlock)) != NULL)
  2774. {
  2775. if (CurMiniport->DriverHandle->MiniportCharacteristics.PnPEventNotifyHandler != NULL)
  2776. {
  2777. CurMiniport->DriverHandle->MiniportCharacteristics.PnPEventNotifyHandler(CurMiniport->MiniportAdapterContext,
  2778. NdisDevicePnPEventPowerProfileChanged,
  2779. Buffer,
  2780. Length);
  2781. }
  2782. }
  2783. ndisUnprocessAllMiniports(MiniBlock);
  2784. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  2785. NextMiniBlock = MiniBlock->NextDriver;
  2786. ndisDereferenceDriver(MiniBlock, TRUE);
  2787. }
  2788. else
  2789. {
  2790. NextMiniBlock = MiniBlock->NextDriver;
  2791. }
  2792. }
  2793. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  2794. } while (FALSE);
  2795. PnPDereferencePackage();
  2796. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2797. ("<==>ndisNotifyMiniportsPowerProfileChange: Miniport %p\n", Miniport));
  2798. return;
  2799. }
  2800. PNDIS_MINIPORT_BLOCK
  2801. ndisReferenceNextUnprocessedMiniport(
  2802. IN PNDIS_M_DRIVER_BLOCK MiniBlock
  2803. )
  2804. {
  2805. PNDIS_MINIPORT_BLOCK Miniport;
  2806. KIRQL OldIrql;
  2807. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2808. ("==>ndisReferenceNextUnprocessedMiniport: MiniBlock %p\n", MiniBlock));
  2809. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  2810. for (Miniport = MiniBlock->MiniportQueue;
  2811. Miniport != NULL;
  2812. Miniport = Miniport->NextMiniport)
  2813. {
  2814. if (!MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_DEREGISTERED_INTERRUPT |
  2815. fMINIPORT_RESET_IN_PROGRESS |
  2816. fMINIPORT_PM_HALTING)) &&
  2817. !MINIPORT_PNP_TEST_FLAG(Miniport, (fMINIPORT_REMOVE_IN_PROGRESS |
  2818. fMINIPORT_DEVICE_FAILED |
  2819. fMINIPORT_PM_HALTED |
  2820. fMINIPORT_HALTING |
  2821. fMINIPORT_SHUTTING_DOWN |
  2822. fMINIPORT_PROCESSING)) &&
  2823. (Miniport->PnPDeviceState == NdisPnPDeviceStarted) &&
  2824. (Miniport->CurrentDevicePowerState == PowerDeviceD0) &&
  2825. MINIPORT_INCREMENT_REF(Miniport))
  2826. {
  2827. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_PROCESSING);
  2828. break;
  2829. }
  2830. }
  2831. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  2832. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2833. ("<==ndisReferenceNextUnprocessedMiniport: MiniBlock %p\n", MiniBlock));
  2834. return(Miniport);
  2835. }
  2836. VOID
  2837. ndisUnprocessAllMiniports(
  2838. IN PNDIS_M_DRIVER_BLOCK MiniBlock
  2839. )
  2840. {
  2841. PNDIS_MINIPORT_BLOCK Miniport;
  2842. KIRQL OldIrql;
  2843. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2844. ("==>ndisUnprocessAllMiniports: MiniBlock %p\n", MiniBlock));
  2845. while (TRUE)
  2846. {
  2847. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  2848. //
  2849. // find the first miniport that is being proccessed. clear the flag, dereference the
  2850. // miniport and go through the whole process again.
  2851. //
  2852. for (Miniport = MiniBlock->MiniportQueue;
  2853. Miniport != NULL;
  2854. Miniport = Miniport->NextMiniport)
  2855. {
  2856. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PROCESSING))
  2857. {
  2858. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_PROCESSING);
  2859. break;
  2860. }
  2861. }
  2862. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  2863. if (Miniport == NULL)
  2864. break;
  2865. //
  2866. // dereferencing the miniport could make it to go away
  2867. //
  2868. MINIPORT_DECREMENT_REF(Miniport);
  2869. }
  2870. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2871. ("<==ndisUnprocessAllMiniports: MiniBlock %p\n", MiniBlock));
  2872. }
  2873. //1 add function header
  2874. PVOID
  2875. NdisGetRoutineAddress(
  2876. IN PNDIS_STRING NdisRoutineName
  2877. )
  2878. {
  2879. PVOID Address;
  2880. ANSI_STRING AnsiString;
  2881. NTSTATUS Status;
  2882. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  2883. Status = RtlUnicodeStringToAnsiString(&AnsiString,
  2884. (PUNICODE_STRING)NdisRoutineName,
  2885. TRUE);
  2886. if (!NT_SUCCESS(Status))
  2887. {
  2888. return NULL;
  2889. }
  2890. Address = FindExportedRoutineByName(ndisDriverObject->DriverStart, &AnsiString);
  2891. RtlFreeAnsiString (&AnsiString);
  2892. return Address;
  2893. }
  2894. PVOID
  2895. FindExportedRoutineByName (
  2896. IN PVOID DllBase,
  2897. IN PANSI_STRING AnsiImageRoutineName
  2898. )
  2899. /*++
  2900. Routine Description:
  2901. This function searches the argument module looking for the requested
  2902. exported function name.
  2903. Arguments:
  2904. DllBase - Supplies the base address of the requested module.
  2905. AnsiImageRoutineName - Supplies the ANSI routine name being searched for.
  2906. Return Value:
  2907. The virtual address of the requested routine or NULL if not found.
  2908. --*/
  2909. {
  2910. USHORT OrdinalNumber;
  2911. PULONG NameTableBase;
  2912. PUSHORT NameOrdinalTableBase;
  2913. PULONG Addr;
  2914. ULONG High;
  2915. ULONG Low;
  2916. ULONG Middle;
  2917. LONG Result;
  2918. ULONG ExportSize;
  2919. PVOID FunctionAddress;
  2920. PIMAGE_EXPORT_DIRECTORY ExportDirectory;
  2921. PAGED_CODE();
  2922. FunctionAddress = NULL;
  2923. ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
  2924. DllBase,
  2925. TRUE,
  2926. IMAGE_DIRECTORY_ENTRY_EXPORT,
  2927. &ExportSize
  2928. );
  2929. if (ExportDirectory == NULL) {
  2930. return NULL;
  2931. }
  2932. //
  2933. // Initialize the pointer to the array of RVA-based ansi export strings.
  2934. //
  2935. NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
  2936. //
  2937. // Initialize the pointer to the array of USHORT ordinal numbers.
  2938. //
  2939. NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
  2940. //
  2941. // Lookup the desired name in the name table using a binary search.
  2942. //
  2943. Low = 0;
  2944. High = ExportDirectory->NumberOfNames - 1;
  2945. //
  2946. // Initializing Middle is not needed for correctness, but without it
  2947. // the compiler cannot compile this code W4 to check for use of
  2948. // uninitialized variables.
  2949. //
  2950. Middle = 0;
  2951. while (High >= Low && (LONG)High >= 0) {
  2952. //
  2953. // Compute the next probe index and compare the import name
  2954. // with the export name entry.
  2955. //
  2956. Middle = (Low + High) >> 1;
  2957. //1 investigate using strncmp
  2958. Result = strcmp (AnsiImageRoutineName->Buffer,
  2959. (PCHAR)DllBase + NameTableBase[Middle]);
  2960. if (Result < 0) {
  2961. High = Middle - 1;
  2962. }
  2963. else if (Result > 0) {
  2964. Low = Middle + 1;
  2965. }
  2966. else {
  2967. break;
  2968. }
  2969. }
  2970. //
  2971. // If the high index is less than the low index, then a matching
  2972. // table entry was not found. Otherwise, get the ordinal number
  2973. // from the ordinal table.
  2974. //
  2975. if ((LONG)High < (LONG)Low) {
  2976. return NULL;
  2977. }
  2978. OrdinalNumber = NameOrdinalTableBase[Middle];
  2979. //
  2980. // If the OrdinalNumber is not within the Export Address Table,
  2981. // then this image does not implement the function. Return not found.
  2982. //
  2983. if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
  2984. return NULL;
  2985. }
  2986. //
  2987. // Index into the array of RVA export addresses by ordinal number.
  2988. //
  2989. Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
  2990. FunctionAddress = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);
  2991. //
  2992. // Forwarders are not used by the kernel and HAL to each other.
  2993. //
  2994. if ((ULONG_PTR)FunctionAddress > (ULONG_PTR)ExportDirectory &&
  2995. (ULONG_PTR)FunctionAddress < ((ULONG_PTR)ExportDirectory + ExportSize)) {
  2996. FunctionAddress = NULL;
  2997. }
  2998. return FunctionAddress;
  2999. }
  3000. UINT
  3001. NdisGetVersion(
  3002. VOID
  3003. )
  3004. {
  3005. return ((NDIS_MAJOR_VERSION << 16) | NDIS_MINOR_VERSION);
  3006. }
  3007. #if 0
  3008. VOID
  3009. ndisBindUnbindCallback(
  3010. PVOID CallBackContext,
  3011. PVOID Argument1,
  3012. PVOID Argument2
  3013. )
  3014. {
  3015. PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE)Argument1;
  3016. PUCHAR ptmp;
  3017. UNICODE_STRING ProtocolName, MiniportName;
  3018. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3019. ("==>ndisBindUnbindCallback\n"));
  3020. if (wnode != NULL)
  3021. {
  3022. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  3023. RtlInitUnicodeString(&ProtocolName, (PWCHAR)ptmp);
  3024. ptmp += ProtocolName.Length + sizeof(WCHAR);
  3025. RtlInitUnicodeString(&MiniportName, (PWCHAR)ptmp);
  3026. ndisDbgPrintUnicodeString(&ProtocolName);
  3027. DbgPrint("\n");
  3028. ndisDbgPrintUnicodeString(&MiniportName);
  3029. DbgPrint("\n");
  3030. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3031. ("<==ndisBindUnbindCallback\n"));
  3032. }
  3033. }
  3034. #endif