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.

5090 lines
142 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. driver.c
  5. Abstract:
  6. This module contains the DriverEntry and other initialization
  7. code for the IPX module of the ISN transport.
  8. Author:
  9. Adam Barr (adamba) 2-September-1993
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Sanjay Anand (SanjayAn) - 22-Sept-1995
  14. BackFill optimization changes added under #if BACK_FILL
  15. Sanjay Anand (SanjayAn) 18-Sept-1995
  16. Changes to support Plug and Play
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #define MODULE 0x60000
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. extern NDIS_HANDLE IpxNdisProtocolHandle;
  25. #ifdef _PNP_POWER_
  26. #include "ipxpnp.h"
  27. void
  28. IpxDoPnPEvent(
  29. IN CTEEvent *WorkerThreadEvent,
  30. IN PVOID Context);
  31. #endif //_PNP_POWER_
  32. //
  33. // Local Function prototypes
  34. //
  35. PWSTR IpxDeviceNameString = L"\\Device\\Nwlnkipx";
  36. VOID
  37. IpxDelayedFreeBindingsArray(
  38. IN PVOID Param
  39. );
  40. VOID
  41. IpxPnPCompletionHandler(
  42. IN PNET_PNP_EVENT pnp,
  43. IN NTSTATUS status
  44. );
  45. //********** Pageable Routine Declarations *****
  46. //************************* PAGEIPX **********************************
  47. #ifdef ALLOC_PRAGMA
  48. #pragma alloc_text(PAGEIPX, IpxDelayedFreeBindingsArray )
  49. #endif
  50. //********** Pageable Routine Declarations *****
  51. PDEVICE IpxDevice = NULL;
  52. PIPX_PADDING_BUFFER IpxPaddingBuffer = NULL;
  53. #if DBG
  54. UCHAR IpxTempDebugBuffer[300];
  55. ULONG IpxDebug = 0x0;
  56. ULONG IpxMemoryDebug = 0xffffffd3;
  57. UCHAR IpxDebugMemory[IPX_MEMORY_LOG_SIZE][192];
  58. PUCHAR IpxDebugMemoryLoc = IpxDebugMemory[0];
  59. PUCHAR IpxDebugMemoryEnd = IpxDebugMemory[IPX_MEMORY_LOG_SIZE];
  60. VOID
  61. IpxDebugMemoryLog(
  62. IN PUCHAR FormatString,
  63. ...
  64. )
  65. {
  66. INT ArgLen;
  67. va_list ArgumentPointer;
  68. va_start(ArgumentPointer, FormatString);
  69. //
  70. // To avoid any overflows, copy this in a temp buffer first.
  71. RtlZeroMemory (IpxTempDebugBuffer, 300);
  72. ArgLen = vsprintf(IpxTempDebugBuffer, FormatString, ArgumentPointer);
  73. va_end(ArgumentPointer);
  74. if ( ArgLen > 192 ) {
  75. CTEAssert( FALSE );
  76. } else {
  77. RtlZeroMemory (IpxDebugMemoryLoc, 192);
  78. RtlCopyMemory( IpxDebugMemoryLoc, IpxTempDebugBuffer, ArgLen );
  79. IpxDebugMemoryLoc += 192;
  80. if (IpxDebugMemoryLoc >= IpxDebugMemoryEnd) {
  81. IpxDebugMemoryLoc = IpxDebugMemory[0];
  82. }
  83. }
  84. }
  85. DEFINE_LOCK_STRUCTURE(IpxMemoryInterlock);
  86. MEMORY_TAG IpxMemoryTag[MEMORY_MAX];
  87. #endif
  88. DEFINE_LOCK_STRUCTURE(IpxGlobalInterlock);
  89. #if DBG
  90. //
  91. // Use for debug printouts
  92. //
  93. PUCHAR FrameTypeNames[5] = { "Ethernet II", "802.3", "802.2", "SNAP", "Arcnet" };
  94. #define OutputFrameType(_Binding) \
  95. (((_Binding)->Adapter->MacInfo.MediumType == NdisMediumArcnet878_2) ? \
  96. FrameTypeNames[4] : \
  97. FrameTypeNames[(_Binding)->FrameType])
  98. #endif
  99. #ifdef IPX_PACKET_LOG
  100. ULONG IpxPacketLogDebug = IPX_PACKET_LOG_RCV_OTHER | IPX_PACKET_LOG_SEND_OTHER;
  101. USHORT IpxPacketLogSocket = 0;
  102. DEFINE_LOCK_STRUCTURE(IpxPacketLogLock);
  103. IPX_PACKET_LOG_ENTRY IpxPacketLog[IPX_PACKET_LOG_LENGTH];
  104. PIPX_PACKET_LOG_ENTRY IpxPacketLogLoc = IpxPacketLog;
  105. PIPX_PACKET_LOG_ENTRY IpxPacketLogEnd = &IpxPacketLog[IPX_PACKET_LOG_LENGTH];
  106. VOID
  107. IpxLogPacket(
  108. IN BOOLEAN Send,
  109. IN PUCHAR DestMac,
  110. IN PUCHAR SrcMac,
  111. IN USHORT Length,
  112. IN PVOID IpxHeader,
  113. IN PVOID Data
  114. )
  115. {
  116. CTELockHandle LockHandle;
  117. PIPX_PACKET_LOG_ENTRY PacketLog;
  118. LARGE_INTEGER TickCount;
  119. ULONG DataLength;
  120. CTEGetLock (&IpxPacketLogLock, &LockHandle);
  121. PacketLog = IpxPacketLogLoc;
  122. ++IpxPacketLogLoc;
  123. if (IpxPacketLogLoc >= IpxPacketLogEnd) {
  124. IpxPacketLogLoc = IpxPacketLog;
  125. }
  126. *(UNALIGNED ULONG *)IpxPacketLogLoc->TimeStamp = 0x3e3d3d3d; // "===>"
  127. CTEFreeLock (&IpxPacketLogLock, LockHandle);
  128. RtlZeroMemory (PacketLog, sizeof(IPX_PACKET_LOG_ENTRY));
  129. PacketLog->SendReceive = Send ? '>' : '<';
  130. KeQueryTickCount(&TickCount);
  131. _itoa (TickCount.LowPart % 100000, PacketLog->TimeStamp, 10);
  132. RtlCopyMemory(PacketLog->DestMac, DestMac, 6);
  133. RtlCopyMemory(PacketLog->SrcMac, SrcMac, 6);
  134. PacketLog->Length[0] = Length / 256;
  135. PacketLog->Length[1] = Length % 256;
  136. if (Length < sizeof(IPX_HEADER)) {
  137. RtlCopyMemory(&PacketLog->IpxHeader, IpxHeader, Length);
  138. } else {
  139. RtlCopyMemory(&PacketLog->IpxHeader, IpxHeader, sizeof(IPX_HEADER));
  140. }
  141. DataLength = Length - sizeof(IPX_HEADER);
  142. if (DataLength < 14) {
  143. RtlCopyMemory(PacketLog->Data, Data, DataLength);
  144. } else {
  145. RtlCopyMemory(PacketLog->Data, Data, 14);
  146. }
  147. } /* IpxLogPacket */
  148. #endif // IPX_PACKET_LOG
  149. //
  150. // Forward declaration of various routines used in this module.
  151. //
  152. NTSTATUS
  153. DriverEntry(
  154. IN PDRIVER_OBJECT DriverObject,
  155. IN PUNICODE_STRING RegistryPath
  156. );
  157. //
  158. // This is now shared with other modules
  159. //
  160. VOID
  161. IpxUnload(
  162. IN PDRIVER_OBJECT DriverObject
  163. );
  164. NTSTATUS
  165. IpxDispatchDeviceControl(
  166. IN PDEVICE_OBJECT DeviceObject,
  167. IN PIRP Irp
  168. );
  169. NTSTATUS
  170. IpxDispatchOpenClose(
  171. IN PDEVICE_OBJECT DeviceObject,
  172. IN PIRP Irp
  173. );
  174. NTSTATUS
  175. IpxDispatchInternal (
  176. IN PDEVICE_OBJECT DeviceObject,
  177. IN PIRP Irp
  178. );
  179. #ifdef ALLOC_PRAGMA
  180. #pragma alloc_text(INIT,DriverEntry)
  181. //
  182. // These routines can be called at any time in case of PnP.
  183. //
  184. #endif
  185. UCHAR VirtualNode[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
  186. //
  187. // This prevents us from having a bss section.
  188. //
  189. ULONG _setjmpexused = 0;
  190. ULONG IpxFailLoad = FALSE;
  191. NTSTATUS
  192. DriverEntry(
  193. IN PDRIVER_OBJECT DriverObject,
  194. IN PUNICODE_STRING RegistryPath
  195. )
  196. /*++
  197. Routine Description:
  198. This routine performs initialization of the IPX ISN module.
  199. It creates the device objects for the transport
  200. provider and performs other driver initialization.
  201. Arguments:
  202. DriverObject - Pointer to driver object created by the system.
  203. RegistryPath - The name of IPX's node in the registry.
  204. Return Value:
  205. The function value is the final status from the initialization operation.
  206. --*/
  207. {
  208. NTSTATUS status;
  209. UINT SuccessfulOpens, ValidBindings;
  210. static const NDIS_STRING ProtocolName = NDIS_STRING_CONST("NWLNKIPX");
  211. PDEVICE Device;
  212. PBINDING Binding;
  213. PADAPTER Adapter;
  214. ULONG BindingCount, BindingIndex;
  215. PLIST_ENTRY p;
  216. ULONG AnnouncedMaxDatagram, RealMaxDatagram, MaxLookahead;
  217. ULONG LinkSpeed, MacOptions;
  218. ULONG Temp;
  219. UINT i;
  220. BOOLEAN CountedWan;
  221. PCONFIG Config = NULL;
  222. PBINDING_CONFIG ConfigBinding;
  223. #if 0
  224. DbgPrint ("IPX: FailLoad at %lx\n", &IpxFailLoad);
  225. if (IpxFailLoad) {
  226. return STATUS_UNSUCCESSFUL;
  227. }
  228. #endif
  229. // DbgBreakPoint();
  230. //
  231. // This ordering matters because we use it to quickly
  232. // determine if packets are internally generated or not.
  233. //
  234. CTEAssert (IDENTIFIER_NB < IDENTIFIER_IPX);
  235. CTEAssert (IDENTIFIER_SPX < IDENTIFIER_IPX);
  236. CTEAssert (IDENTIFIER_RIP < IDENTIFIER_IPX);
  237. CTEAssert (IDENTIFIER_RIP_INTERNAL > IDENTIFIER_IPX);
  238. //
  239. // We assume that this structure is not packet in between
  240. // the fields.
  241. //
  242. CTEAssert (FIELD_OFFSET (TDI_ADDRESS_IPX, Socket) + sizeof(USHORT) == 12);
  243. //
  244. // Initialize the Common Transport Environment.
  245. //
  246. if (CTEInitialize() == 0) {
  247. IPX_DEBUG (DEVICE, ("CTEInitialize() failed\n"));
  248. IpxWriteGeneralErrorLog(
  249. (PVOID)DriverObject,
  250. EVENT_TRANSPORT_REGISTER_FAILED,
  251. 101,
  252. STATUS_UNSUCCESSFUL,
  253. NULL,
  254. 0,
  255. NULL);
  256. return STATUS_UNSUCCESSFUL;
  257. }
  258. #if DBG
  259. CTEInitLock (&IpxGlobalInterlock);
  260. CTEInitLock (&IpxMemoryInterlock);
  261. for (i = 0; i < MEMORY_MAX; i++) {
  262. IpxMemoryTag[i].Tag = i;
  263. IpxMemoryTag[i].BytesAllocated = 0;
  264. }
  265. #endif
  266. #ifdef IPX_PACKET_LOG
  267. CTEInitLock (&IpxPacketLogLock);
  268. #endif
  269. #ifdef IPX_OWN_PACKETS
  270. CTEAssert (NDIS_PACKET_SIZE == FIELD_OFFSET(NDIS_PACKET, ProtocolReserved[0]));
  271. #endif
  272. IPX_DEBUG (DEVICE, ("IPX loaded\n"));
  273. //
  274. // This allocates the CONFIG structure and returns
  275. // it in Config.
  276. //
  277. status = IpxGetConfiguration(DriverObject, RegistryPath, &Config);
  278. if (!NT_SUCCESS (status)) {
  279. //
  280. // If it failed, it logged an error.
  281. //
  282. PANIC (" Failed to initialize transport, IPX initialization failed.\n");
  283. return status;
  284. }
  285. //
  286. // Initialize the TDI layer.
  287. //
  288. TdiInitialize();
  289. //
  290. // Initialize the driver object with this driver's entry points.
  291. //
  292. DriverObject->MajorFunction [IRP_MJ_CREATE] = IpxDispatchOpenClose;
  293. DriverObject->MajorFunction [IRP_MJ_CLOSE] = IpxDispatchOpenClose;
  294. DriverObject->MajorFunction [IRP_MJ_CLEANUP] = IpxDispatchOpenClose;
  295. DriverObject->MajorFunction [IRP_MJ_PNP] = IpxDispatchOpenClose;
  296. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = IpxDispatchInternal;
  297. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = IpxDispatchDeviceControl;
  298. DriverObject->DriverUnload = IpxUnload;
  299. SuccessfulOpens = 0;
  300. status = IpxCreateDevice(
  301. DriverObject,
  302. &Config->DeviceName,
  303. Config->Parameters[CONFIG_RIP_TABLE_SIZE],
  304. &Device);
  305. if (!NT_SUCCESS (status)) {
  306. IpxWriteGeneralErrorLog(
  307. (PVOID)DriverObject,
  308. EVENT_IPX_CREATE_DEVICE,
  309. 801,
  310. status,
  311. NULL,
  312. 0,
  313. NULL);
  314. IpxFreeConfiguration(Config);
  315. IpxDeregisterProtocol();
  316. return status;
  317. }
  318. IpxDevice = Device;
  319. RtlInitUnicodeString(&IpxDeviceName, IpxDeviceNameString);
  320. //
  321. // Initialize and keep track of the Init Time Adapters and such.
  322. //
  323. IpxDevice->InitTimeAdapters = 1;
  324. IpxDevice->NoMoreInitAdapters = FALSE;
  325. status = TdiRegisterProvider(&IpxDeviceName, &IpxDevice->TdiProviderReadyHandle);
  326. if (!NT_SUCCESS(status))
  327. {
  328. IpxFreeConfiguration(Config);
  329. IpxDeregisterProtocol();
  330. return status;
  331. }
  332. //
  333. // Save the relevant configuration parameters.
  334. //
  335. Device->DedicatedRouter = (BOOLEAN)(Config->Parameters[CONFIG_DEDICATED_ROUTER] != 0);
  336. Device->InitDatagrams = Config->Parameters[CONFIG_INIT_DATAGRAMS];
  337. Device->MaxDatagrams = Config->Parameters[CONFIG_MAX_DATAGRAMS];
  338. Device->RipAgeTime = Config->Parameters[CONFIG_RIP_AGE_TIME];
  339. Device->RipCount = Config->Parameters[CONFIG_RIP_COUNT];
  340. Device->RipTimeout =
  341. ((Config->Parameters[CONFIG_RIP_TIMEOUT] * 500) + (RIP_GRANULARITY/2)) /
  342. RIP_GRANULARITY;
  343. Device->RipUsageTime = Config->Parameters[CONFIG_RIP_USAGE_TIME];
  344. Device->SourceRouteUsageTime = Config->Parameters[CONFIG_ROUTE_USAGE_TIME];
  345. Device->SocketUniqueness = Config->Parameters[CONFIG_SOCKET_UNIQUENESS];
  346. Device->SocketStart = (USHORT)Config->Parameters[CONFIG_SOCKET_START];
  347. Device->SocketEnd = (USHORT)Config->Parameters[CONFIG_SOCKET_END];
  348. Device->MemoryLimit = Config->Parameters[CONFIG_MAX_MEMORY_USAGE];
  349. Device->VerifySourceAddress = (BOOLEAN)(Config->Parameters[CONFIG_VERIFY_SOURCE_ADDRESS] != 0);
  350. Device->InitReceivePackets = (Device->InitDatagrams + 1) / 2;
  351. Device->InitReceiveBuffers = (Device->InitDatagrams + 1) / 2;
  352. Device->MaxReceivePackets = 10;
  353. Device->MaxReceiveBuffers = 10;
  354. InitializeListHead(&Device->NicNtfQueue);
  355. InitializeListHead(&Device->NicNtfComplQueue);
  356. Device->InitBindings = 5;
  357. //
  358. // RAS max is 240 (?) + 10 max LAN
  359. //
  360. Device->MaxPoolBindings = 250;
  361. #ifdef SNMP
  362. IPX_MIB_ENTRY(Device, SysConfigSockets) = (Device->SocketEnd - Device->SocketStart)
  363. / ((Device->SocketUniqueness > 1) ? Device->SocketUniqueness : 1);
  364. ;
  365. #endif SNMP
  366. //
  367. // Have to reverse this.
  368. //
  369. Device->VirtualNetworkOptional = (BOOLEAN)(Config->Parameters[CONFIG_VIRTUAL_OPTIONAL] != 0);
  370. Device->CurrentSocket = Device->SocketStart;
  371. Device->EthernetPadToEven = (BOOLEAN)(Config->Parameters[CONFIG_ETHERNET_PAD] != 0);
  372. Device->EthernetExtraPadding = (Config->Parameters[CONFIG_ETHERNET_LENGTH] & 0xfffffffe) + 1;
  373. Device->SingleNetworkActive = (BOOLEAN)(Config->Parameters[CONFIG_SINGLE_NETWORK] != 0);
  374. Device->DisableDialoutSap = (BOOLEAN)(Config->Parameters[CONFIG_DISABLE_DIALOUT_SAP] != 0);
  375. Device->DisableDialinNetbios = (UCHAR)(Config->Parameters[CONFIG_DISABLE_DIALIN_NB]);
  376. //
  377. // Used later to access the registry.
  378. //
  379. Device->RegistryPathBuffer = Config->RegistryPathBuffer;
  380. Device->RegistryPath.Length = RegistryPath->Length;
  381. Device->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
  382. Device->RegistryPath.Buffer = Device->RegistryPathBuffer;
  383. //
  384. // Initialize the BroadcastCount now and so, we dont have to
  385. // init this field per adapter [MS]
  386. //
  387. Device->EnableBroadcastCount = 0;
  388. //
  389. // ActiveNetworkWan will start as FALSE, which is correct.
  390. //
  391. //
  392. // Allocate our initial packet pool. We do not allocate
  393. // receive and receive buffer pools until we need them,
  394. // because in many cases we never do.
  395. //
  396. #if BACK_FILL
  397. IpxAllocateBackFillPool (Device);
  398. #endif
  399. IpxAllocateSendPool (Device);
  400. IpxAllocateBindingPool (Device);
  401. //
  402. // Allocate one 1-byte buffer for odd length packets.
  403. //
  404. IpxPaddingBuffer = IpxAllocatePaddingBuffer(Device);
  405. if ( IpxPaddingBuffer == (PIPX_PADDING_BUFFER)NULL ) {
  406. IpxWriteGeneralErrorLog(
  407. (PVOID)DriverObject,
  408. EVENT_TRANSPORT_RESOURCE_POOL,
  409. 801,
  410. STATUS_INSUFFICIENT_RESOURCES,
  411. NULL,
  412. 0,
  413. NULL);
  414. TdiDeregisterProvider(IpxDevice->TdiProviderReadyHandle);
  415. IpxFreeConfiguration(Config);
  416. IpxDeregisterProtocol();
  417. return STATUS_INSUFFICIENT_RESOURCES;
  418. }
  419. //
  420. // Initialize the loopback structures
  421. //
  422. IpxInitLoopback();
  423. // NIC_HANDLE
  424. // All this will be done on appearance of adapters.
  425. //
  426. {
  427. PBIND_ARRAY_ELEM BindingArray;
  428. PTA_ADDRESS TdiRegistrationAddress;
  429. //
  430. // Pre-allocate the binding array
  431. // Later, we will allocate the LAN/WAN and SLAVE bindings separately
  432. // Read the array size from registry?
  433. //
  434. BindingArray = (PBIND_ARRAY_ELEM)IpxAllocateMemory (
  435. MAX_BINDINGS * sizeof(BIND_ARRAY_ELEM),
  436. MEMORY_BINDING,
  437. "Binding array");
  438. if (BindingArray == NULL) {
  439. IpxWriteGeneralErrorLog(
  440. (PVOID)DriverObject,
  441. EVENT_IPX_NO_ADAPTERS,
  442. 802,
  443. STATUS_DEVICE_DOES_NOT_EXIST,
  444. NULL,
  445. 0,
  446. NULL);
  447. TdiDeregisterProvider(IpxDevice->TdiProviderReadyHandle);
  448. IpxDereferenceDevice (Device, DREF_CREATE);
  449. return STATUS_DEVICE_DOES_NOT_EXIST;
  450. }
  451. Device->MaxBindings = MAX_BINDINGS - EXTRA_BINDINGS;
  452. //
  453. // Allocate the TA_ADDRESS structure - this will be used in all TdiRegisterNetAddress
  454. // notifications.
  455. //
  456. TdiRegistrationAddress = (PTA_ADDRESS)IpxAllocateMemory (
  457. (2 * sizeof(USHORT) + sizeof(TDI_ADDRESS_IPX)),
  458. MEMORY_ADDRESS,
  459. "Tdi Address");
  460. if (TdiRegistrationAddress == NULL) {
  461. IpxWriteGeneralErrorLog(
  462. (PVOID)DriverObject,
  463. EVENT_IPX_NO_ADAPTERS,
  464. 802,
  465. STATUS_DEVICE_DOES_NOT_EXIST,
  466. NULL,
  467. 0,
  468. NULL);
  469. TdiDeregisterProvider(IpxDevice->TdiProviderReadyHandle);
  470. IpxFreeMemory(BindingArray, sizeof(BindingArray), MEMORY_BINDING, "Binding Array");
  471. IpxDereferenceDevice (Device, DREF_CREATE);
  472. return STATUS_DEVICE_DOES_NOT_EXIST;
  473. }
  474. RtlZeroMemory (BindingArray, MAX_BINDINGS * sizeof(BIND_ARRAY_ELEM));
  475. RtlZeroMemory (TdiRegistrationAddress, 2 * sizeof(USHORT) + sizeof(TDI_ADDRESS_IPX));
  476. //
  477. // We keep BindingArray[-1] as a placeholder for demand dial bindings.
  478. // This NicId is returned by the Fwd when a FindRoute is done on a demand
  479. // dial Nic. At the time of the InternalSend, the true Nic is returned.
  480. // We create a placeholder here to avoid special checks in the critical send path.
  481. //
  482. // NOTE: we need to free this demand dial binding as well as ensure that the
  483. // true binding array pointer is freed at Device Destroy time.
  484. //
  485. //
  486. // Increment beyond the first pointer - we will refer to the just incremented
  487. // one as Device->Bindings[-1].
  488. //
  489. BindingArray += EXTRA_BINDINGS;
  490. Device->Bindings = BindingArray;
  491. TdiRegistrationAddress->AddressLength = sizeof(TDI_ADDRESS_IPX);
  492. TdiRegistrationAddress->AddressType = TDI_ADDRESS_TYPE_IPX;
  493. //
  494. // Store the pointer in the Device.
  495. //
  496. Device->TdiRegistrationAddress = TdiRegistrationAddress;
  497. //
  498. // Device state is loaded, but not opened. It is opened when at least
  499. // one adapter has appeared.
  500. //
  501. Device->State = DEVICE_STATE_LOADED;
  502. Device->FirstLanNicId = Device->FirstWanNicId = (USHORT)1; // will be changed later
  503. IpxFreeConfiguration(Config);
  504. //
  505. // We use this event when unloading to signal that we
  506. // can proceed...initialize it here so we know it is
  507. // ready to go when unload is called.
  508. //
  509. KeInitializeEvent(
  510. &IpxDevice->UnloadEvent,
  511. NotificationEvent,
  512. FALSE
  513. );
  514. KeInitializeEvent(
  515. &IpxDevice->NbEvent,
  516. NotificationEvent,
  517. FALSE
  518. );
  519. //
  520. // Create a loopback adapter right here. [NtBug - 110010]
  521. //
  522. status = IpxBindLoopbackAdapter();
  523. if (status != STATUS_SUCCESS) {
  524. PANIC ("IpxCreateLoopback adapter failed!\n");
  525. IpxWriteGeneralErrorLog(
  526. (PVOID)DriverObject,
  527. EVENT_TRANSPORT_REGISTER_FAILED,
  528. 607,
  529. status,
  530. NULL,
  531. 0,
  532. NULL);
  533. TdiDeregisterProvider(IpxDevice->TdiProviderReadyHandle);
  534. return status;
  535. } else {
  536. IPX_DEBUG(DEVICE, ("Created LOOPBACK ADAPTER!\n"));
  537. }
  538. //
  539. // make ourselves known to the NDIS wrapper.
  540. //
  541. status = IpxRegisterProtocol ((PNDIS_STRING)&ProtocolName);
  542. if (!NT_SUCCESS (status)) {
  543. IpxFreeConfiguration(Config);
  544. DbgPrint ("IpxInitialize: RegisterProtocol failed with status %x!\n", status);
  545. IpxWriteGeneralErrorLog(
  546. (PVOID)DriverObject,
  547. EVENT_TRANSPORT_REGISTER_FAILED,
  548. 607,
  549. status,
  550. NULL,
  551. 0,
  552. NULL);
  553. return status;
  554. }
  555. return STATUS_SUCCESS;
  556. }
  557. } /* DriverEntry */
  558. ULONG
  559. IpxResolveAutoDetect(
  560. IN PDEVICE Device,
  561. IN ULONG ValidBindings,
  562. IN CTELockHandle *LockHandle1,
  563. IN PUNICODE_STRING RegistryPath,
  564. IN PADAPTER Adapter
  565. )
  566. /*++
  567. Routine Description:
  568. This routine is called for auto-detect bindings to
  569. remove any bindings that were not successfully found.
  570. It also updates "DefaultAutoDetectType" in the registry
  571. if needed.
  572. Arguments:
  573. Device - The IPX device object.
  574. ValidBindings - The total number of bindings present.
  575. RegistryPath - The path to the ipx registry, used if we have
  576. to write a value back.
  577. Return Value:
  578. The updated number of bindings.
  579. --*/
  580. {
  581. PBINDING Binding, TmpBinding;
  582. UINT i, j;
  583. //
  584. // Get rid of any auto-detect devices which we
  585. // could not find nets for. We also remove any
  586. // devices which are not the first ones
  587. // auto-detected on a particular adapter.
  588. //
  589. for (i = FIRST_REAL_BINDING; i <= ValidBindings; i++) {
  590. Binding = NIC_ID_TO_BINDING(Device, i);
  591. if (!Binding) {
  592. continue;
  593. }
  594. //
  595. // If this was auto-detected and was not the default,
  596. // or it was the default, but nothing was detected for
  597. // it *and* something else *was* detected (which means
  598. // we will use that frame type when we get to it),
  599. // we may need to remove this binding.
  600. //
  601. // TINGCAI: If users do not set DefaultAutoDetectType in the
  602. // registry, the default is 802.2. For 802.3,
  603. if (Binding->AutoDetect &&
  604. (!Binding->DefaultAutoDetect ||
  605. (Binding->DefaultAutoDetect &&
  606. (Binding->LocalAddress.NetworkAddress == 0) &&
  607. Binding->Adapter->AutoDetectResponse))) {
  608. if ((Binding->LocalAddress.NetworkAddress == 0) ||
  609. (Binding->Adapter->AutoDetectFoundOnBinding &&
  610. Binding->Adapter->AutoDetectFoundOnBinding != Binding)) {
  611. //
  612. // Remove this binding.
  613. //
  614. if (Binding->LocalAddress.NetworkAddress == 0) {
  615. IPX_DEBUG (AUTO_DETECT, ("Binding %d (%d) no net found\n",
  616. i, Binding->FrameType));
  617. } else {
  618. IPX_DEBUG (AUTO_DETECT, ("Binding %d (%d) adapter already auto-detected\n",
  619. i, Binding->FrameType));
  620. }
  621. CTEAssert (Binding->NicId == i);
  622. CTEAssert (!Binding->Adapter->MacInfo.MediumAsync);
  623. //
  624. // Remove any routes through this NIC, and
  625. // adjust any NIC ID's above this one in the
  626. // database down by one.
  627. //
  628. RipAdjustForBindingChange (Binding->NicId, 0, IpxBindingDeleted);
  629. Binding->Adapter->Bindings[Binding->FrameType] = NULL;
  630. for (j = i+1; j <= ValidBindings; j++) {
  631. TmpBinding = NIC_ID_TO_BINDING(Device, j);
  632. INSERT_BINDING(Device, j-1, TmpBinding);
  633. if (TmpBinding) {
  634. if ((TmpBinding->Adapter->MacInfo.MediumAsync) &&
  635. (TmpBinding->Adapter->FirstWanNicId == TmpBinding->NicId)) {
  636. --TmpBinding->Adapter->FirstWanNicId;
  637. --TmpBinding->Adapter->LastWanNicId;
  638. }
  639. --TmpBinding->NicId;
  640. }
  641. }
  642. INSERT_BINDING(Device, ValidBindings, NULL);
  643. --Binding->Adapter->BindingCount;
  644. --ValidBindings;
  645. --i; // so we check the binding that was just moved.
  646. //
  647. // Wait 100 ms before freeing the binding,
  648. // in case an indication is using it.
  649. //
  650. KeStallExecutionProcessor(100000);
  651. IpxDestroyBinding (Binding);
  652. } else {
  653. IPX_DEBUG (AUTO_DETECT, ("Binding %d (%d) auto-detected OK\n",
  654. i, Binding->FrameType));
  655. #if DBG
  656. DbgPrint ("IPX: Auto-detected non-default frame type %s, net %lx\n",
  657. OutputFrameType(Binding),
  658. REORDER_ULONG (Binding->LocalAddress.NetworkAddress));
  659. #endif
  660. //
  661. // Save it in the registry for the next boot.
  662. //
  663. //
  664. // This cannot be done at DPC, so, drop the IRQL
  665. //
  666. IPX_FREE_LOCK1(&Device->BindAccessLock, *LockHandle1);
  667. IpxWriteDefaultAutoDetectType(
  668. RegistryPath,
  669. Binding->Adapter,
  670. Binding->FrameType);
  671. IPX_GET_LOCK1(&Device->BindAccessLock, LockHandle1);
  672. //
  673. // Now, we know for sure that NB needs to be told of this.
  674. // Set to TRUE in IpxBindToAdapter line 1491
  675. if (Binding->Adapter == Adapter) {
  676. Binding->IsnInformed[IDENTIFIER_NB] = FALSE;
  677. Binding->IsnInformed[IDENTIFIER_SPX] = FALSE;
  678. }
  679. Binding->Adapter->AutoDetectFoundOnBinding = Binding;
  680. }
  681. } else {
  682. if (Binding->AutoDetect) {
  683. IPX_DEBUG (AUTO_DETECT, ("Binding %d (%d) auto-detect default\n",
  684. i, Binding->FrameType));
  685. #if DBG
  686. if (Binding->LocalAddress.NetworkAddress != 0) {
  687. IPX_DEBUG (AUTO_DETECT, ("IPX: Auto-detected default frame type %s, net %lx\n",
  688. OutputFrameType(Binding),
  689. REORDER_ULONG (Binding->LocalAddress.NetworkAddress)));
  690. } else {
  691. IPX_DEBUG (AUTO_DETECT, ("IPX: Using default auto-detect frame type %s\n",
  692. OutputFrameType(Binding)));
  693. }
  694. #endif
  695. Binding->Adapter->AutoDetectFoundOnBinding = Binding;
  696. } else {
  697. IPX_DEBUG (AUTO_DETECT, ("Binding %d (%d) not auto-detected\n",
  698. i, Binding->FrameType));
  699. }
  700. //
  701. // Now, we know for sure that NB needs to be told of this.
  702. //
  703. if (Binding->Adapter == Adapter) {
  704. Binding->IsnInformed[IDENTIFIER_NB] = FALSE;
  705. Binding->IsnInformed[IDENTIFIER_SPX] = FALSE;
  706. }
  707. }
  708. }
  709. for (i = 1; i <= ValidBindings; i++) {
  710. if (Binding = NIC_ID_TO_BINDING(Device, i)) {
  711. CTEAssert (Binding->NicId == i);
  712. IPX_DEBUG (AUTO_DETECT, ("Binding %lx, type %d, auto %d\n",
  713. Binding, Binding->FrameType, Binding->AutoDetect));
  714. }
  715. }
  716. return ValidBindings;
  717. } /* IpxResolveAutoDetect */
  718. VOID
  719. IpxResolveBindingSets(
  720. IN PDEVICE Device,
  721. IN ULONG ValidBindings
  722. )
  723. /*++
  724. Routine Description:
  725. This routine is called to determine if we have any
  726. binding sets and rearrange the bindings the way we
  727. like. The order is as follows:
  728. - First comes the first binding to each LAN network
  729. - Following that are all WAN bindings
  730. - Following that are any duplicate bindings to LAN networks
  731. (the others in the "binding set").
  732. If "global wan net" is true we will advertise up to
  733. and including the first wan binding as the highest nic
  734. id; otherwise we advertise up to and including the last
  735. wan binding. In all cases the duplicate bindings are
  736. hidden.
  737. Arguments:
  738. Device - The IPX device object.
  739. ValidBindings - The total number of bindings present.
  740. Return Value:
  741. None.
  742. --*/
  743. {
  744. PBINDING Binding, MasterBinding, TmpBinding;
  745. UINT i, j;
  746. ULONG WanCount, DuplicateCount;
  747. //
  748. // First loop through and push all the wan bindings
  749. // to the end.
  750. //
  751. WanCount = Device->HighestExternalNicId - Device->HighestLanNicId;
  752. //
  753. // Now go through and find the LAN duplicates and
  754. // create binding sets from them.
  755. //
  756. DuplicateCount = 0;
  757. for (i = FIRST_REAL_BINDING; i <= (ValidBindings-(WanCount+DuplicateCount)); ) {
  758. Binding = NIC_ID_TO_BINDING(Device, i);
  759. CTEAssert (Binding != NULL); // because we are only looking at LAN bindings
  760. CTEAssert (!Binding->Adapter->MacInfo.MediumAsync);
  761. if (Binding->LocalAddress.NetworkAddress == 0) {
  762. i++;
  763. continue;
  764. }
  765. //
  766. // See if any previous bindings match the
  767. // frame type, medium type, and number of
  768. // this network (for the moment we match on
  769. // frame type and medium type too so that we
  770. // don't have to worry about different frame
  771. // formats and header offsets within a set).
  772. //
  773. for (j = FIRST_REAL_BINDING; j < i; j++) {
  774. MasterBinding = NIC_ID_TO_BINDING(Device, j);
  775. if ((MasterBinding->LocalAddress.NetworkAddress == Binding->LocalAddress.NetworkAddress) &&
  776. (MasterBinding->FrameType == Binding->FrameType) &&
  777. (MasterBinding->Adapter->MacInfo.MediumType == Binding->Adapter->MacInfo.MediumType)) {
  778. break;
  779. }
  780. }
  781. if (j == i) {
  782. i++;
  783. continue;
  784. }
  785. //
  786. // We have a duplicate. First slide it down to the
  787. // end. Note that we change any router entries that
  788. // use our real NicId to use the real NicId of the
  789. // master (there should be no entries in the rip
  790. // database that have the NicId of a binding slave).
  791. //
  792. RipAdjustForBindingChange (Binding->NicId, MasterBinding->NicId, IpxBindingMoved);
  793. for (j = i+1; j <= ValidBindings; j++) {
  794. TmpBinding = NIC_ID_TO_BINDING(Device, j);
  795. INSERT_BINDING(Device, j-1, TmpBinding);
  796. if (TmpBinding) {
  797. if ((TmpBinding->Adapter->MacInfo.MediumAsync) &&
  798. (TmpBinding->Adapter->FirstWanNicId == TmpBinding->NicId)) {
  799. --TmpBinding->Adapter->FirstWanNicId;
  800. --TmpBinding->Adapter->LastWanNicId;
  801. }
  802. --TmpBinding->NicId;
  803. }
  804. }
  805. INSERT_BINDING(Device, ValidBindings, Binding);
  806. Binding->NicId = (USHORT)ValidBindings;
  807. ++DuplicateCount;
  808. if (Binding->TdiRegistrationHandle != NULL) {
  809. NTSTATUS ntStatus;
  810. ntStatus = TdiDeregisterNetAddress(Binding->TdiRegistrationHandle);
  811. if (ntStatus != STATUS_SUCCESS) {
  812. IPX_DEBUG(PNP, ("TdiDeRegisterNetAddress failed: %lx", ntStatus));
  813. } else {
  814. Binding->TdiRegistrationHandle = NULL;
  815. }
  816. }
  817. //
  818. // Now make MasterBinding the head of a binding set.
  819. //
  820. if (MasterBinding->BindingSetMember) {
  821. //
  822. // Just insert ourselves in the chain.
  823. //
  824. #if DBG
  825. DbgPrint ("IPX: %lx is also on network %lx\n",
  826. Binding->Adapter->AdapterName,
  827. REORDER_ULONG (Binding->LocalAddress.NetworkAddress));
  828. #endif
  829. IPX_DEBUG (AUTO_DETECT, ("Add %lx to binding set of %lx\n", Binding, MasterBinding));
  830. CTEAssert (MasterBinding->CurrentSendBinding);
  831. Binding->NextBinding = MasterBinding->NextBinding;
  832. } else {
  833. //
  834. // Start the chain with the two bindings in it.
  835. //
  836. #if DBG
  837. DbgPrint ("IPX: %lx and %lx are on the same network %lx, will load balance\n",
  838. MasterBinding->Adapter->AdapterName, Binding->Adapter->AdapterName,
  839. REORDER_ULONG (Binding->LocalAddress.NetworkAddress));
  840. #endif
  841. IPX_DEBUG (AUTO_DETECT, ("Create new %lx in binding set of %lx\n", Binding, MasterBinding));
  842. MasterBinding->BindingSetMember = TRUE;
  843. MasterBinding->CurrentSendBinding = MasterBinding;
  844. MasterBinding->MasterBinding = MasterBinding;
  845. Binding->NextBinding = MasterBinding;
  846. }
  847. MasterBinding->NextBinding = Binding;
  848. Binding->BindingSetMember = TRUE;
  849. Binding->ReceiveBroadcast = FALSE;
  850. Binding->CurrentSendBinding = NULL;
  851. Binding->MasterBinding = MasterBinding;
  852. //
  853. // Since the master binding looks like all members of
  854. // the binding set to people querying from above, we have
  855. // to make it the worst-case of all the elements. Generally
  856. // these will be equal since the frame type and media is
  857. // the same.
  858. //
  859. if (Binding->MaxLookaheadData > MasterBinding->MaxLookaheadData) {
  860. MasterBinding->MaxLookaheadData = Binding->MaxLookaheadData;
  861. }
  862. if (Binding->AnnouncedMaxDatagramSize < MasterBinding->AnnouncedMaxDatagramSize) {
  863. MasterBinding->AnnouncedMaxDatagramSize = Binding->AnnouncedMaxDatagramSize;
  864. }
  865. if (Binding->RealMaxDatagramSize < MasterBinding->RealMaxDatagramSize) {
  866. MasterBinding->RealMaxDatagramSize = Binding->RealMaxDatagramSize;
  867. }
  868. if (Binding->MediumSpeed < MasterBinding->MediumSpeed) {
  869. MasterBinding->MediumSpeed = Binding->MediumSpeed;
  870. }
  871. //
  872. // Keep i the same, to check the new binding at
  873. // this position.
  874. //
  875. }
  876. Device->HighestLanNicId -= (USHORT)DuplicateCount;
  877. if (Device->HighestLanNicId == 0) {
  878. CTEAssert(FALSE);
  879. }
  880. Device->HighestExternalNicId -= (USHORT)DuplicateCount;
  881. Device->HighestType20NicId -= (USHORT)DuplicateCount;
  882. Device->SapNicCount -= (USHORT)DuplicateCount;
  883. } /* IpxResolveBindingSets */
  884. NTSTATUS
  885. IpxBindToAdapter(
  886. IN PDEVICE Device,
  887. IN PBINDING_CONFIG ConfigBinding,
  888. IN PADAPTER *AdapterPtr,
  889. IN ULONG FrameTypeIndex
  890. )
  891. /*++
  892. Routine Description:
  893. This routine handles binding the transport to a new
  894. adapter. It can be called at any point during the life
  895. of the transport.
  896. Arguments:
  897. Device - The IPX device object.
  898. ConfigBinding - The configuration info for this binding.
  899. AdapterPtr - pointer to the adapter to bind to in case of PnP.
  900. FrameTypeIndex - The index into ConfigBinding's array of frame
  901. types for this adapter. The routine is called once for
  902. every valid frame type.
  903. Return Value:
  904. The function value is the final status from the initialization operation.
  905. --*/
  906. {
  907. NTSTATUS status;
  908. PADAPTER Adapter = *AdapterPtr;
  909. PBINDING Binding, OldBinding;
  910. ULONG FrameType, MappedFrameType;
  911. PLIST_ENTRY p;
  912. //
  913. // We can't bind more than one adapter unless we have a
  914. // virtual network configured or we are allowed to run
  915. // with a virtual network of 0.
  916. //
  917. if (Device->BindingCount == 1) {
  918. if ((Device->VirtualNetworkNumber == 0) &&
  919. (!Device->VirtualNetworkOptional)) {
  920. IPX_DEBUG (ADAPTER, ("Cannot bind to more than one adapter\n"));
  921. DbgPrint ("IPX: Disallowing multiple bind ==> VirtualNetwork is 0\n");
  922. IpxWriteGeneralErrorLog(
  923. Device->DeviceObject,
  924. EVENT_TRANSPORT_BINDING_FAILED,
  925. 666,
  926. STATUS_NOT_SUPPORTED,
  927. ConfigBinding->AdapterName.Buffer,
  928. 0,
  929. NULL);
  930. return STATUS_NOT_SUPPORTED;
  931. }
  932. }
  933. //
  934. // First allocate the memory for the binding.
  935. //
  936. status = IpxCreateBinding(
  937. Device,
  938. ConfigBinding,
  939. FrameTypeIndex,
  940. ConfigBinding->AdapterName.Buffer,
  941. &Binding);
  942. if (status != STATUS_SUCCESS) {
  943. IpxWriteGeneralErrorLog(
  944. (PVOID)IpxDevice->DeviceObject,
  945. EVENT_TRANSPORT_RESOURCE_POOL,
  946. 812,
  947. status,
  948. L"IpxBindToAdapter: failed to create binding",
  949. 0,
  950. NULL);
  951. DbgPrint("IPX: IpxCreateBinding failed with status %x\n.",status);
  952. return status;
  953. }
  954. FrameType = ConfigBinding->FrameType[FrameTypeIndex];
  955. //
  956. // In PnP case, we dont need to check for existing adapters since
  957. // we supply a NULL adapter in the parameters if it needs to be created
  958. //
  959. if (Adapter == NULL) {
  960. //
  961. // No binding to this adapter exists, so create a
  962. // new one.
  963. //
  964. status = IpxCreateAdapter(
  965. Device,
  966. &ConfigBinding->AdapterName,
  967. &Adapter);
  968. if (status != STATUS_SUCCESS) {
  969. IpxDestroyBinding(Binding);
  970. return status;
  971. }
  972. //
  973. // Save these now (they will be the same for all bindings
  974. // on this adapter).
  975. //
  976. Adapter->ConfigMaxPacketSize = ConfigBinding->Parameters[BINDING_MAX_PKT_SIZE];
  977. Adapter->SourceRouting = (BOOLEAN)ConfigBinding->Parameters[BINDING_SOURCE_ROUTE];
  978. Adapter->EnableFunctionalAddress = (BOOLEAN)ConfigBinding->Parameters[BINDING_ENABLE_FUNC_ADDR];
  979. Adapter->EnableWanRouter = (BOOLEAN)ConfigBinding->Parameters[BINDING_ENABLE_WAN];
  980. Adapter->BindSap = (USHORT)ConfigBinding->Parameters[BINDING_BIND_SAP];
  981. Adapter->BindSapNetworkOrder = REORDER_USHORT(Adapter->BindSap);
  982. CTEAssert (Adapter->BindSap == 0x8137);
  983. CTEAssert (Adapter->BindSapNetworkOrder == 0x3781);
  984. //
  985. // Now fire up NDIS so this adapter talks
  986. //
  987. status = IpxInitializeNdis(
  988. Adapter,
  989. ConfigBinding);
  990. if (!NT_SUCCESS (status)) {
  991. //
  992. // Log an error.
  993. //
  994. IpxWriteGeneralErrorLog(
  995. Device->DeviceObject,
  996. EVENT_TRANSPORT_BINDING_FAILED,
  997. 601,
  998. status,
  999. ConfigBinding->AdapterName.Buffer,
  1000. 0,
  1001. NULL);
  1002. IpxDereferenceAdapter1(Adapter,ADAP_REF_CREATE);
  1003. IpxDestroyAdapter (Adapter);
  1004. IpxDestroyBinding (Binding);
  1005. //
  1006. // Returning this status informs the caller to not
  1007. // try any more frame types on this adapter.
  1008. //
  1009. return STATUS_DEVICE_DOES_NOT_EXIST;
  1010. }
  1011. //
  1012. // For 802.5 bindings we need to start the source routing
  1013. // timer to time out old entries.
  1014. //
  1015. if ((Adapter->MacInfo.MediumType == NdisMedium802_5) &&
  1016. (Adapter->SourceRouting)) {
  1017. if (!Device->SourceRoutingUsed) {
  1018. Device->SourceRoutingUsed = TRUE;
  1019. IpxReferenceDevice (Device, DREF_SR_TIMER);
  1020. CTEStartTimer(
  1021. &Device->SourceRoutingTimer,
  1022. 60000, // one minute timeout
  1023. MacSourceRoutingTimeout,
  1024. (PVOID)Device);
  1025. }
  1026. }
  1027. MacMapFrameType(
  1028. Adapter->MacInfo.RealMediumType,
  1029. FrameType,
  1030. &MappedFrameType);
  1031. IPX_DEBUG (ADAPTER, ("Create new bind to adapter %ws, type %d\n",
  1032. ConfigBinding->AdapterName.Buffer,
  1033. MappedFrameType));
  1034. IpxAllocateReceiveBufferPool (Adapter);
  1035. *AdapterPtr = Adapter;
  1036. }
  1037. else {
  1038. //
  1039. // get the mapped frame type
  1040. //
  1041. MacMapFrameType(
  1042. Adapter->MacInfo.RealMediumType,
  1043. FrameType,
  1044. &MappedFrameType);
  1045. if (Adapter->Bindings[MappedFrameType] != NULL) {
  1046. IPX_DEBUG (ADAPTER, ("Bind to adapter %ws, type %d exists\n",
  1047. Adapter->AdapterName,
  1048. MappedFrameType));
  1049. //
  1050. // If this was the auto-detect default for this
  1051. // adapter and it failed, we need to make the
  1052. // previous one the default, so that at least
  1053. // one binding will stick around.
  1054. //
  1055. if (ConfigBinding->DefaultAutoDetect[FrameTypeIndex]) {
  1056. IPX_DEBUG (ADAPTER, ("Default auto-detect changed from %d to %d\n",
  1057. FrameType, MappedFrameType));
  1058. Adapter->Bindings[MappedFrameType]->DefaultAutoDetect = TRUE;
  1059. }
  1060. IpxDestroyBinding (Binding);
  1061. return STATUS_NOT_SUPPORTED;
  1062. }
  1063. IPX_DEBUG (ADAPTER, ("Using existing bind to adapter %ws, type %d\n",
  1064. Adapter->AdapterName,
  1065. MappedFrameType));
  1066. }
  1067. //
  1068. // The local node address starts out the same as the
  1069. // MAC address of the adapter (on WAN this will change).
  1070. // The local MAC address can also change for WAN.
  1071. //
  1072. RtlCopyMemory (Binding->LocalAddress.NodeAddress, Adapter->LocalMacAddress.Address, 6);
  1073. RtlCopyMemory (Binding->LocalMacAddress.Address, Adapter->LocalMacAddress.Address, 6);
  1074. //
  1075. // Save the send handler.
  1076. //
  1077. Binding->SendFrameHandler = NULL;
  1078. Binding->FrameType = MappedFrameType;
  1079. //
  1080. // Put this in InitializeBindingInfo.
  1081. //
  1082. switch (Adapter->MacInfo.RealMediumType) {
  1083. case NdisMedium802_3:
  1084. switch (MappedFrameType) {
  1085. case ISN_FRAME_TYPE_802_3: Binding->SendFrameHandler = IpxSendFrame802_3802_3; break;
  1086. case ISN_FRAME_TYPE_802_2: Binding->SendFrameHandler = IpxSendFrame802_3802_2; break;
  1087. case ISN_FRAME_TYPE_ETHERNET_II: Binding->SendFrameHandler = IpxSendFrame802_3EthernetII; break;
  1088. case ISN_FRAME_TYPE_SNAP: Binding->SendFrameHandler = IpxSendFrame802_3Snap; break;
  1089. }
  1090. break;
  1091. case NdisMedium802_5:
  1092. switch (MappedFrameType) {
  1093. case ISN_FRAME_TYPE_802_2: Binding->SendFrameHandler = IpxSendFrame802_5802_2; break;
  1094. case ISN_FRAME_TYPE_SNAP: Binding->SendFrameHandler = IpxSendFrame802_5Snap; break;
  1095. }
  1096. break;
  1097. case NdisMediumFddi:
  1098. switch (MappedFrameType) {
  1099. case ISN_FRAME_TYPE_802_3: Binding->SendFrameHandler = IpxSendFrameFddi802_3; break;
  1100. case ISN_FRAME_TYPE_802_2: Binding->SendFrameHandler = IpxSendFrameFddi802_2; break;
  1101. case ISN_FRAME_TYPE_SNAP: Binding->SendFrameHandler = IpxSendFrameFddiSnap; break;
  1102. }
  1103. break;
  1104. case NdisMediumArcnet878_2:
  1105. switch (MappedFrameType) {
  1106. case ISN_FRAME_TYPE_802_3: Binding->SendFrameHandler = IpxSendFrameArcnet878_2; break;
  1107. }
  1108. break;
  1109. case NdisMediumWan:
  1110. switch (MappedFrameType) {
  1111. case ISN_FRAME_TYPE_ETHERNET_II: Binding->SendFrameHandler = IpxSendFrameWanEthernetII; break;
  1112. }
  1113. break;
  1114. }
  1115. if (Binding->SendFrameHandler == NULL) {
  1116. DbgPrint ("SendFrameHandler is NULL\n");
  1117. }
  1118. Adapter->Bindings[MappedFrameType] = Binding;
  1119. ++Adapter->BindingCount;
  1120. Binding->Adapter = Adapter;
  1121. //
  1122. // NicId and ExternalNicId will be filled in later when the binding
  1123. // is assigned a spot in the Device->Bindings array.
  1124. //
  1125. //
  1126. // Initialize the per-binding MAC information
  1127. //
  1128. if ((Adapter->ConfigMaxPacketSize == 0) ||
  1129. (Adapter->MaxSendPacketSize < Adapter->ConfigMaxPacketSize)) {
  1130. Binding->MaxSendPacketSize = Adapter->MaxSendPacketSize;
  1131. } else {
  1132. Binding->MaxSendPacketSize = Adapter->ConfigMaxPacketSize;
  1133. }
  1134. Binding->MediumSpeed = Adapter->MediumSpeed;
  1135. if (Adapter->MacInfo.MediumAsync) {
  1136. Binding->LineUp = FALSE;
  1137. } else {
  1138. //
  1139. // Lets do this until we know for sure that we are done with autodetect.
  1140. // [ShreeM]
  1141. //
  1142. // Only for LAN as we don't do auto detect for WAN lines. 276128
  1143. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  1144. Binding->IsnInformed[IDENTIFIER_SPX] = TRUE;
  1145. Binding->LineUp = TRUE;
  1146. }
  1147. MacInitializeBindingInfo(
  1148. Binding,
  1149. Adapter);
  1150. return STATUS_SUCCESS;
  1151. } /* IpxBindToAdapter */
  1152. BOOLEAN
  1153. IpxIsAddressLocal(
  1154. IN TDI_ADDRESS_IPX UNALIGNED * SourceAddress
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. This routine returns TRUE if the specified SourceAddress indicates
  1159. the packet was sent by us, and FALSE otherwise.
  1160. Arguments:
  1161. SourceAddress - The source IPX address.
  1162. Return Value:
  1163. TRUE if the address is local.
  1164. --*/
  1165. {
  1166. PBINDING Binding;
  1167. UINT i;
  1168. PDEVICE Device = IpxDevice;
  1169. CTELockHandle LockHandle;
  1170. CTEGetLock (&Device->Lock, &LockHandle);
  1171. //
  1172. // First see if it is a virtual network address or not.
  1173. //
  1174. if (RtlEqualMemory (VirtualNode, SourceAddress->NodeAddress, 6)) {
  1175. //
  1176. // This is us if we have a virtual network configured.
  1177. // If we don't have a virtual node, we fall through to the
  1178. // other check -- an arcnet card configured as node 1 will
  1179. // have what we think of as the "virtual node" as its
  1180. // real node address.
  1181. //
  1182. if ((IpxDevice->VirtualNetwork) &&
  1183. (IpxDevice->VirtualNetworkNumber == SourceAddress->NetworkAddress)) {
  1184. CTEFreeLock (&Device->Lock, LockHandle);
  1185. return TRUE;
  1186. }
  1187. }
  1188. //
  1189. // Check through our list of adapters to see if one of
  1190. // them is the source node.
  1191. //
  1192. {
  1193. ULONG Index = MIN (IpxDevice->MaxBindings, IpxDevice->ValidBindings);
  1194. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  1195. if (((Binding = NIC_ID_TO_BINDING(IpxDevice, i)) != NULL) &&
  1196. (RtlEqualMemory (Binding->LocalAddress.NodeAddress, SourceAddress->NodeAddress, 6))) {
  1197. CTEFreeLock (&Device->Lock, LockHandle);
  1198. return TRUE;
  1199. }
  1200. }
  1201. }
  1202. CTEFreeLock (&Device->Lock, LockHandle);
  1203. return FALSE;
  1204. } /* IpxIsAddressLocal */
  1205. NTSTATUS
  1206. IpxUnBindFromAdapter(
  1207. IN PBINDING Binding
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This routine handles unbinding the transport from an
  1212. adapter. It can be called at any point during the life
  1213. of the transport.
  1214. Arguments:
  1215. Binding - The adapter to unbind.
  1216. Return Value:
  1217. The function value is the final status from the initialization operation.
  1218. --*/
  1219. {
  1220. PADAPTER Adapter = Binding->Adapter;
  1221. IpxDereferenceBinding (Binding, BREF_BOUND);
  1222. if (NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID) != Binding) {
  1223. Adapter->Bindings[Binding->FrameType] = NULL;
  1224. --Adapter->BindingCount;
  1225. } else {
  1226. IPX_DEBUG(PNP, ("Loopback Binding : dont decrement adapter's bindingcount, just return\n"));
  1227. return STATUS_SUCCESS;
  1228. }
  1229. if (Adapter->BindingCount == 0) {
  1230. //
  1231. // DereferenceAdapter is a NULL macro for load-only.
  1232. //
  1233. #ifdef _PNP_LATER
  1234. //
  1235. // Take away the creation reference. When the in-use ref is taken off,
  1236. // we destroy this adapter.
  1237. //
  1238. IpxDereferenceAdapter(Adapter);
  1239. #else
  1240. IpxDestroyAdapter (Adapter);
  1241. #endif
  1242. }
  1243. return STATUS_SUCCESS;
  1244. } /* IpxUnBindFromAdapter */
  1245. VOID
  1246. IpxNdisUnload() {
  1247. PBINDING Loopback=NULL;
  1248. NTSTATUS ntStatus = STATUS_SUCCESS;
  1249. NDIS_STATUS ndisStatus;
  1250. IPX_PNP_INFO IpxPnPInfo;
  1251. PREQUEST Request;
  1252. PLIST_ENTRY p;
  1253. KIRQL irql;
  1254. NDIS_HANDLE LocalNdisProtocolHandle;
  1255. IPX_DEBUG(PNP, ("IpxNdisUnload is being called\n"));
  1256. IpxDevice->State = DEVICE_STATE_STOPPING;
  1257. LocalNdisProtocolHandle = InterlockedExchangePointer(&IpxNdisProtocolHandle, NULL);
  1258. if (LocalNdisProtocolHandle != (NDIS_HANDLE)NULL) {
  1259. NdisDeregisterProtocol (&ndisStatus, LocalNdisProtocolHandle);
  1260. ASSERT(ndisStatus == NDIS_STATUS_SUCCESS);
  1261. }
  1262. //
  1263. // Complete any pending address notify requests.
  1264. //
  1265. while ((p = ExInterlockedRemoveHeadList(
  1266. &IpxDevice->AddressNotifyQueue,
  1267. &IpxDevice->Lock)) != NULL) {
  1268. Request = LIST_ENTRY_TO_REQUEST(p);
  1269. REQUEST_STATUS(Request) = STATUS_DEVICE_NOT_READY;
  1270. // AcquireCancelSpinLock to force the cancel routine to release the lock if it was
  1271. // fired after we remove it from the queue
  1272. IoAcquireCancelSpinLock( &irql );
  1273. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1274. IoReleaseCancelSpinLock( irql );
  1275. IpxCompleteRequest (Request);
  1276. IpxFreeRequest (IpxDevice, Request);
  1277. IpxDereferenceDevice (IpxDevice, DREF_ADDRESS_NOTIFY);
  1278. }
  1279. Loopback = NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID);
  1280. if (Loopback != NULL) {
  1281. if (Loopback->TdiRegistrationHandle) {
  1282. if ((ntStatus = TdiDeregisterNetAddress(Loopback->TdiRegistrationHandle)) != STATUS_SUCCESS) {
  1283. DbgPrint("IPX: IpxNdisUnload: TdiDeRegisterNetAddress failed: %lx\n", ntStatus);
  1284. } else {
  1285. IPX_DEBUG(PNP, ("TdiDeRegisterNetAddress Loopback Address: %lx\n", Loopback->LocalAddress.NetworkAddress));
  1286. Loopback->TdiRegistrationHandle = NULL;
  1287. }
  1288. }
  1289. }
  1290. //
  1291. // Inform TDI clients about the close of our device object.
  1292. //
  1293. // If TdiRegisterDeviceObject failed, the handle would be null.
  1294. if (IpxDevice->TdiRegistrationHandle != NULL) {
  1295. if (IpxDevice->TdiRegistrationHandle == (PVOID) TDI_DEREGISTERED_COOKIE) {
  1296. DbgPrint("IPX: IpxNdisUnload: NDIS is calling us AGAIN (%p) !!!!\n, IpxDevice->TdiRegistrationHandle");
  1297. DbgBreakPoint();
  1298. } else {
  1299. ntStatus = TdiDeregisterDeviceObject(IpxDevice->TdiRegistrationHandle);
  1300. if (ntStatus != STATUS_SUCCESS) {
  1301. DbgPrint("IPX: TdiDeRegisterDeviceObject failed: %lx\n", ntStatus);
  1302. } else {
  1303. IpxDevice->TdiRegistrationHandle = (HANDLE) TDI_DEREGISTERED_COOKIE;
  1304. }
  1305. }
  1306. }
  1307. IpxPnPInfo.LineInfo.LinkSpeed = IpxDevice->LinkSpeed;
  1308. IpxPnPInfo.LineInfo.MaximumPacketSize =
  1309. IpxDevice->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  1310. IpxPnPInfo.LineInfo.MaximumSendSize =
  1311. IpxDevice->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  1312. IpxPnPInfo.LineInfo.MacOptions = IpxDevice->MacOptions;
  1313. IpxPnPInfo.FirstORLastDevice = TRUE;
  1314. if (Loopback != NULL) {
  1315. if (IpxDevice->UpperDriverBound[IDENTIFIER_SPX] && (*IpxDevice->UpperDrivers[IDENTIFIER_SPX].PnPHandler)) {
  1316. if (Loopback->IsnInformed[IDENTIFIER_SPX]) {
  1317. (*IpxDevice->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  1318. IPX_PNP_DELETE_DEVICE,
  1319. &IpxPnPInfo);
  1320. Loopback->IsnInformed[IDENTIFIER_SPX] = FALSE;
  1321. }
  1322. }
  1323. if (IpxDevice->UpperDriverBound[IDENTIFIER_NB] && (*IpxDevice->UpperDrivers[IDENTIFIER_NB].PnPHandler)) {
  1324. if (Loopback->IsnInformed[IDENTIFIER_NB]) {
  1325. (*IpxDevice->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  1326. IPX_PNP_DELETE_DEVICE,
  1327. &IpxPnPInfo);
  1328. Loopback->IsnInformed[IDENTIFIER_NB] = FALSE;
  1329. IPX_DEBUG(PNP,("Indicate to NB IPX_PNP_DELETE_DEVICE with FirstORLastDevice = (%d)",IpxPnPInfo.FirstORLastDevice));
  1330. }
  1331. }
  1332. }
  1333. }
  1334. VOID
  1335. IpxUnload(
  1336. IN PDRIVER_OBJECT DriverObject
  1337. )
  1338. /*++
  1339. Routine Description:
  1340. This routine unloads the sample transport driver.
  1341. It unbinds from any NDIS drivers that are open and frees all resources
  1342. associated with the transport. The I/O system will not call us until
  1343. nobody above has IPX open.
  1344. Arguments:
  1345. DriverObject - Pointer to driver object created by the system.
  1346. Return Value:
  1347. None. When the function returns, the driver is unloaded.
  1348. --*/
  1349. {
  1350. PBINDING Binding, Loopback=NULL;
  1351. UINT i;
  1352. NTSTATUS ntStatus = STATUS_SUCCESS;
  1353. LARGE_INTEGER Delay;
  1354. CTELockHandle LockHandle;
  1355. UNREFERENCED_PARAMETER (DriverObject);
  1356. //
  1357. // Cancel the source routing timer if used.
  1358. //
  1359. if (IpxDevice->SourceRoutingUsed) {
  1360. IpxDevice->SourceRoutingUsed = FALSE;
  1361. if (CTEStopTimer (&IpxDevice->SourceRoutingTimer)) {
  1362. IpxDereferenceDevice (IpxDevice, DREF_SR_TIMER);
  1363. }
  1364. }
  1365. //
  1366. // Cancel the RIP long timer, and if we do that then
  1367. // send a RIP DOWN message if needed.
  1368. //
  1369. if (CTEStopTimer (&IpxDevice->RipLongTimer)) {
  1370. if (IpxDevice->RipResponder) {
  1371. if (RipQueueRequest (IpxDevice->VirtualNetworkNumber, RIP_DOWN) == STATUS_PENDING) {
  1372. //
  1373. // If we queue a request, it will stop the timer.
  1374. //
  1375. KeWaitForSingleObject(
  1376. &IpxDevice->UnloadEvent,
  1377. Executive,
  1378. KernelMode,
  1379. TRUE,
  1380. (PLARGE_INTEGER)NULL
  1381. );
  1382. }
  1383. }
  1384. IpxDereferenceDevice (IpxDevice, DREF_LONG_TIMER);
  1385. } else {
  1386. //
  1387. // We couldn't stop the timer, which means it is running,
  1388. // so we need to wait for the event that is kicked when
  1389. // the RIP DOWN messages are done.
  1390. //
  1391. if (IpxDevice->RipResponder) {
  1392. KeWaitForSingleObject(
  1393. &IpxDevice->UnloadEvent,
  1394. Executive,
  1395. KernelMode,
  1396. TRUE,
  1397. (PLARGE_INTEGER)NULL
  1398. );
  1399. }
  1400. }
  1401. IPX_DEBUG(PNP, ("Going back to loaded state\n"));
  1402. // Free loopback binding and adapter
  1403. IpxDereferenceAdapter1(NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID)->Adapter,ADAP_REF_CREATE);
  1404. IpxDestroyAdapter(NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID)->Adapter);
  1405. IpxDestroyBinding(NIC_ID_TO_BINDING(IpxDevice, LOOPBACK_NIC_ID));
  1406. //
  1407. // Walk the list of device contexts.
  1408. //
  1409. for (i = FIRST_REAL_BINDING; i <= IpxDevice->ValidBindings; i++) {
  1410. if ((Binding = NIC_ID_TO_BINDING(IpxDevice, i)) != NULL) {
  1411. // This function will skip NdisCloseAdapter if it has already done so.
  1412. IpxCloseNdis(Binding->Adapter);
  1413. INSERT_BINDING(IpxDevice, i, NULL);
  1414. // Deref the binding and free its adapter if the binding count goes to 0.
  1415. IpxUnBindFromAdapter (Binding);
  1416. }
  1417. }
  1418. //
  1419. // Backup the pointer to free the demand dial location.
  1420. //
  1421. IpxDevice->Bindings -= EXTRA_BINDINGS;
  1422. IpxFreeMemory ( IpxDevice->Bindings,
  1423. IpxDevice->MaxBindings * sizeof(BIND_ARRAY_ELEM),
  1424. MEMORY_BINDING,
  1425. "Binding array");
  1426. //
  1427. // Deallocate the TdiRegistrationAddress and RegistryPathBuffer.
  1428. //
  1429. IpxFreeMemory ( IpxDevice->TdiRegistrationAddress,
  1430. (2 * sizeof(USHORT) + sizeof(TDI_ADDRESS_IPX)),
  1431. MEMORY_ADDRESS,
  1432. "Tdi Address");
  1433. IpxFreeMemory ( IpxDevice->RegistryPathBuffer,
  1434. IpxDevice->RegistryPath.Length + sizeof(WCHAR),
  1435. MEMORY_CONFIG,
  1436. "RegistryPathBuffer");
  1437. KeResetEvent(&IpxDevice->UnloadEvent);
  1438. CTEGetLock (&IpxDevice->Lock, &LockHandle);
  1439. IpxDevice->UnloadWaiting = TRUE;
  1440. CTEFreeLock (&IpxDevice->Lock, LockHandle);
  1441. //
  1442. // Remove the reference for us being loaded.
  1443. //
  1444. IpxDereferenceDevice (IpxDevice, DREF_CREATE);
  1445. //
  1446. // Wait for our count to drop to zero.
  1447. //
  1448. // If KeWaitForSingleObject returns STATUS_ALERTED, we should keep waiting. [TC]
  1449. //
  1450. while (KeWaitForSingleObject(
  1451. &IpxDevice->UnloadEvent,
  1452. Executive,
  1453. KernelMode,
  1454. TRUE,
  1455. (PLARGE_INTEGER)NULL
  1456. )
  1457. == STATUS_ALERTED) {
  1458. IPX_DEBUG(DEVICE, ("KeWaitForSingleObject returned STATUS_ALERTED"));
  1459. };
  1460. // Let the thread that set the UnloadEvent exit. 269061
  1461. Delay.QuadPart = -10*1000; // One second.
  1462. KeDelayExecutionThread(
  1463. KernelMode,
  1464. FALSE,
  1465. &Delay);
  1466. //
  1467. // Now free the padding buffer.
  1468. //
  1469. IpxFreePaddingBuffer (IpxDevice);
  1470. //
  1471. // Now do the cleanup that has to happen at IRQL 0.
  1472. //
  1473. ExDeleteResourceLite (&IpxDevice->AddressResource);
  1474. IoDeleteDevice (IpxDevice->DeviceObject);
  1475. //
  1476. // Finally, remove ourselves as an NDIS protocol.
  1477. //
  1478. IpxDeregisterProtocol();
  1479. } /* IpxUnload */
  1480. NTSTATUS
  1481. IpxDispatchPnP(
  1482. IN PDEVICE_OBJECT DeviceObject,
  1483. IN PREQUEST Request
  1484. )
  1485. {
  1486. PIO_STACK_LOCATION pIrpSp;
  1487. PDEVICE_RELATIONS pDeviceRelations = NULL;
  1488. PVOID pnpDeviceContext = NULL;
  1489. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  1490. PADDRESS_FILE AddressFile;
  1491. PDEVICE Device = IpxDevice;
  1492. pIrpSp = IoGetCurrentIrpStackLocation(Request);
  1493. //
  1494. // Allocate a request to track this IRP.
  1495. //
  1496. switch(pIrpSp->MinorFunction) {
  1497. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1498. if (pIrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) {
  1499. /*
  1500. 354517 nwrdr passes neither a connection nor an address file object.
  1501. If nwrdr gives an address object,
  1502. IPX should look up which nic this address is bound to and
  1503. gives the PDO of that NIC.
  1504. */
  1505. /*
  1506. if (PtrToUlong(pIrpSp->FileObject->FsContext2) == TDI_CONNECTION_FILE) {
  1507. DbgPrint("IPX: Received IRP_MJ_PNP, Connectoin File\n");
  1508. Status = STATUS_INVALID_HANDLE;
  1509. break;
  1510. } else if ( PtrToUlong(pIrpSp->FileObject->FsContext2) == TDI_TRANSPORT_ADDRESS_FILE) {
  1511. DbgPrint("IPX: Received IRP_MJ_PNP, Address File\n");
  1512. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  1513. } else {
  1514. Status = STATUS_INVALID_HANDLE;
  1515. break;
  1516. }
  1517. //
  1518. // This creates a reference to AddressFile->Address
  1519. // which is removed by IpxCloseAddressFile.
  1520. //
  1521. Status = IpxVerifyAddressFile(AddressFile);
  1522. if (!NT_SUCCESS (Status)) {
  1523. DbgPrint("IPX: Received IRP_MJ_PNP, Invalid Address File\n");
  1524. Status = STATUS_INVALID_HANDLE;
  1525. } else {
  1526. */
  1527. PBINDING Binding = NIC_ID_TO_BINDING(Device, FIRST_REAL_BINDING);
  1528. if (Binding == NULL) {
  1529. Status = STATUS_INVALID_HANDLE;
  1530. } else {
  1531. pnpDeviceContext = Binding->Adapter->PNPContext;
  1532. pDeviceRelations = (PDEVICE_RELATIONS) IpxAllocateMemory (sizeof (DEVICE_RELATIONS),
  1533. MEMORY_ADAPTER,
  1534. "Query Device Relation");
  1535. if (pDeviceRelations != NULL) {
  1536. ObReferenceObject (pnpDeviceContext);
  1537. //
  1538. // TargetDeviceRelation allows exactly one PDO. fill it up.
  1539. //
  1540. pDeviceRelations->Count = 1;
  1541. pDeviceRelations->Objects[0] = pnpDeviceContext;
  1542. //
  1543. // invoker of this irp will free the information buffer.
  1544. //
  1545. REQUEST_INFORMATION(Request) = (ULONG_PTR) pDeviceRelations;
  1546. Status = STATUS_SUCCESS;
  1547. } else {
  1548. Status = STATUS_INSUFFICIENT_RESOURCES;
  1549. }
  1550. /*
  1551. }
  1552. IpxDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  1553. */
  1554. }
  1555. }
  1556. break;
  1557. default:
  1558. break;
  1559. }
  1560. return Status;
  1561. }
  1562. NTSTATUS
  1563. IpxDispatchOpenClose(
  1564. IN PDEVICE_OBJECT DeviceObject,
  1565. IN PIRP Irp
  1566. )
  1567. /*++
  1568. Routine Description:
  1569. This routine is the main dispatch routine for the IPX device driver.
  1570. It accepts an I/O Request Packet, performs the request, and then
  1571. returns with the appropriate status.
  1572. Arguments:
  1573. DeviceObject - Pointer to the device object for this driver.
  1574. Irp - Pointer to the request packet representing the I/O request.
  1575. Return Value:
  1576. The function value is the status of the operation.
  1577. --*/
  1578. {
  1579. CTELockHandle LockHandle;
  1580. PDEVICE Device = IpxDevice;
  1581. NTSTATUS Status;
  1582. PFILE_FULL_EA_INFORMATION openType;
  1583. BOOLEAN found;
  1584. PADDRESS_FILE AddressFile;
  1585. PREQUEST Request;
  1586. UINT i;
  1587. #ifdef SUNDOWN
  1588. ULONG_PTR Type;
  1589. #else
  1590. ULONG Type;
  1591. #endif
  1592. ASSERT( DeviceObject->DeviceExtension == IpxDevice );
  1593. // We should allow clients such as NB to CLOSE and CLEANUP even when we are stopping.
  1594. // Only disable CREATE when stopping. [TC]
  1595. if (Device->State == DEVICE_STATE_CLOSED) {
  1596. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  1597. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1598. return STATUS_INVALID_DEVICE_STATE;
  1599. }
  1600. #ifdef DBG
  1601. if (Device->State == DEVICE_STATE_STOPPING) {
  1602. IPX_DEBUG(DEVICE, ("Got IRP in STOPPING state. IRP(%p)", Irp));
  1603. }
  1604. #endif
  1605. //
  1606. // Allocate a request to track this IRP.
  1607. //
  1608. Request = IpxAllocateRequest (Device, Irp);
  1609. IF_NOT_ALLOCATED(Request) {
  1610. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  1611. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1612. return STATUS_INSUFFICIENT_RESOURCES;
  1613. }
  1614. //
  1615. // Make sure status information is consistent every time.
  1616. //
  1617. MARK_REQUEST_PENDING(Request);
  1618. REQUEST_STATUS(Request) = STATUS_PENDING;
  1619. REQUEST_INFORMATION(Request) = 0;
  1620. //
  1621. // Case on the function that is being performed by the requestor. If the
  1622. // operation is a valid one for this device, then make it look like it was
  1623. // successfully completed, where possible.
  1624. //
  1625. switch (REQUEST_MAJOR_FUNCTION(Request)) {
  1626. case IRP_MJ_PNP:
  1627. Status = IpxDispatchPnP(DeviceObject, Request);
  1628. break;
  1629. //
  1630. // The Create function opens a transport object (either address or
  1631. // connection). Access checking is performed on the specified
  1632. // address to ensure security of transport-layer addresses.
  1633. //
  1634. case IRP_MJ_CREATE:
  1635. // We should reject CREATE when we are stopping
  1636. if (Device->State == DEVICE_STATE_STOPPING) {
  1637. Status = STATUS_INVALID_DEVICE_STATE;
  1638. break;
  1639. }
  1640. openType = OPEN_REQUEST_EA_INFORMATION(Request);
  1641. if (openType != NULL) {
  1642. found = FALSE;
  1643. if (strncmp(openType->EaName, TdiTransportAddress,
  1644. openType->EaNameLength) == 0)
  1645. {
  1646. found = TRUE;
  1647. }
  1648. if (found) {
  1649. Status = IpxOpenAddress (Device, Request);
  1650. break;
  1651. }
  1652. //
  1653. // Router
  1654. //
  1655. if (strncmp(openType->EaName, ROUTER_INTERFACE,
  1656. openType->EaNameLength) == 0)
  1657. {
  1658. found = TRUE;
  1659. }
  1660. if (found) {
  1661. Status = OpenRtAddress (Device, Request);
  1662. break;
  1663. }
  1664. //
  1665. // Connection?
  1666. //
  1667. if (strncmp(openType->EaName, TdiConnectionContext,
  1668. openType->EaNameLength) == 0)
  1669. {
  1670. found = TRUE;
  1671. }
  1672. if (found) {
  1673. Status = STATUS_NOT_SUPPORTED;
  1674. break;
  1675. }
  1676. else
  1677. {
  1678. Status = STATUS_NONEXISTENT_EA_ENTRY;
  1679. }
  1680. } else {
  1681. CTEGetLock (&Device->Lock, &LockHandle);
  1682. //
  1683. // LowPart is in the OPEN_CONTEXT directly.
  1684. // HighPart goes into the upper 2 bytes of the OPEN_TYPE.
  1685. //
  1686. #ifdef _WIN64
  1687. REQUEST_OPEN_CONTEXT(Request) = (PVOID)(Device->ControlChannelIdentifier.QuadPart);
  1688. (ULONG_PTR)(REQUEST_OPEN_TYPE(Request)) = IPX_FILE_TYPE_CONTROL;
  1689. #else
  1690. REQUEST_OPEN_CONTEXT(Request) = (PVOID)(Device->ControlChannelIdentifier.LowPart);
  1691. (ULONG)(REQUEST_OPEN_TYPE(Request)) = (Device->ControlChannelIdentifier.HighPart << 16);
  1692. (ULONG)(REQUEST_OPEN_TYPE(Request)) |= IPX_FILE_TYPE_CONTROL;
  1693. #endif
  1694. ++(Device->ControlChannelIdentifier.QuadPart);
  1695. if (Device->ControlChannelIdentifier.QuadPart > MAX_CCID) {
  1696. Device->ControlChannelIdentifier.QuadPart = 1;
  1697. }
  1698. CTEFreeLock (&Device->Lock, LockHandle);
  1699. Status = STATUS_SUCCESS;
  1700. }
  1701. break;
  1702. case IRP_MJ_CLOSE:
  1703. //
  1704. // The Close function closes a transport endpoint, terminates
  1705. // all outstanding transport activity on the endpoint, and unbinds
  1706. // the endpoint from its transport address, if any. If this
  1707. // is the last transport endpoint bound to the address, then
  1708. // the address is removed from the provider.
  1709. //
  1710. #ifdef _WIN64
  1711. switch (Type = ((ULONG_PTR)(REQUEST_OPEN_TYPE(Request)))) {
  1712. #else
  1713. switch (Type = ((ULONG)(REQUEST_OPEN_TYPE(Request)) & IPX_CC_MASK)) {
  1714. #endif
  1715. default:
  1716. if ((Type >= ROUTER_ADDRESS_FILE) &&
  1717. (Type <= (ROUTER_ADDRESS_FILE + IPX_RT_MAX_ADDRESSES)))
  1718. {
  1719. CloseRtAddress(Device, Request);
  1720. }
  1721. else
  1722. {
  1723. Status = STATUS_INVALID_HANDLE;
  1724. break;
  1725. }
  1726. // fall through
  1727. case TDI_TRANSPORT_ADDRESS_FILE:
  1728. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  1729. //
  1730. // This creates a reference to AddressFile->Address
  1731. // which is removed by IpxCloseAddressFile.
  1732. //
  1733. Status = IpxVerifyAddressFile(AddressFile);
  1734. if (!NT_SUCCESS (Status)) {
  1735. Status = STATUS_INVALID_HANDLE;
  1736. } else {
  1737. Status = IpxCloseAddressFile (Device, Request);
  1738. IpxDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  1739. }
  1740. break;
  1741. case IPX_FILE_TYPE_CONTROL:
  1742. {
  1743. LARGE_INTEGER ControlChannelId;
  1744. CCID_FROM_REQUEST(ControlChannelId, Request);
  1745. //
  1746. // See if it is one of the upper driver's control channels.
  1747. //
  1748. Status = STATUS_SUCCESS;
  1749. IPX_DEBUG (DEVICE, ("CCID: (%d, %d)\n", ControlChannelId.HighPart, ControlChannelId.LowPart));
  1750. /*
  1751. // Move to IRP_MJ_CLEANUP 360966
  1752. for (i = 0; i < UPPER_DRIVER_COUNT; i++) {
  1753. if (Device->UpperDriverControlChannel[i].QuadPart ==
  1754. ControlChannelId.QuadPart) {
  1755. Status = IpxInternalUnbind (Device, i);
  1756. break;
  1757. }
  1758. }
  1759. */
  1760. break;
  1761. }
  1762. }
  1763. break;
  1764. case IRP_MJ_CLEANUP:
  1765. //
  1766. // Handle the two stage IRP for a file close operation. When the first
  1767. // stage hits, run down all activity on the object of interest. This
  1768. // do everything to it but remove the creation hold. Then, when the
  1769. // CLOSE irp hits, actually close the object.
  1770. //
  1771. #ifdef _WIN64
  1772. switch (Type = ((ULONG_PTR)REQUEST_OPEN_TYPE(Request))) {
  1773. #else
  1774. switch (Type = ((ULONG)(REQUEST_OPEN_TYPE(Request)) & IPX_CC_MASK)) {
  1775. #endif
  1776. default:
  1777. if ((Type >= ROUTER_ADDRESS_FILE) &&
  1778. (Type <= (ROUTER_ADDRESS_FILE + IPX_RT_MAX_ADDRESSES)))
  1779. {
  1780. CleanupRtAddress(Device, Request);
  1781. }
  1782. else
  1783. {
  1784. Status = STATUS_INVALID_HANDLE;
  1785. break;
  1786. }
  1787. //
  1788. // fall through
  1789. //
  1790. case TDI_TRANSPORT_ADDRESS_FILE:
  1791. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  1792. Status = IpxVerifyAddressFile(AddressFile);
  1793. if (!NT_SUCCESS (Status)) {
  1794. Status = STATUS_INVALID_HANDLE;
  1795. } else {
  1796. IpxStopAddressFile (AddressFile);
  1797. IpxDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  1798. Status = STATUS_SUCCESS;
  1799. }
  1800. break;
  1801. case IPX_FILE_TYPE_CONTROL:
  1802. {
  1803. LARGE_INTEGER ControlChannelId;
  1804. CCID_FROM_REQUEST(ControlChannelId, Request);
  1805. IPX_DEBUG (DEVICE, ("CCID: (%d, %d)\n", ControlChannelId.HighPart, ControlChannelId.LowPart));
  1806. //
  1807. // Check for any line change IRPs submitted by this
  1808. // address.
  1809. //
  1810. IpxAbortLineChanges ((PVOID)&ControlChannelId);
  1811. IpxAbortNtfChanges ((PVOID)&ControlChannelId);
  1812. Status = STATUS_SUCCESS;
  1813. for (i = 0; i < UPPER_DRIVER_COUNT; i++) {
  1814. if (Device->UpperDriverControlChannel[i].QuadPart ==
  1815. ControlChannelId.QuadPart) {
  1816. if (Irp->RequestorMode == KernelMode) {
  1817. Status = IpxInternalUnbind (Device, i);
  1818. } else {
  1819. DbgPrint("!!!! IPX:Rejected non-kernel-mode component's attemp to close handles. !!!!\n");
  1820. Status = STATUS_UNSUCCESSFUL;
  1821. }
  1822. break;
  1823. }
  1824. }
  1825. break;
  1826. }
  1827. }
  1828. break;
  1829. default:
  1830. Status = STATUS_INVALID_DEVICE_REQUEST;
  1831. } /* major function switch */
  1832. if (Status != STATUS_PENDING) {
  1833. UNMARK_REQUEST_PENDING(Request);
  1834. REQUEST_STATUS(Request) = Status;
  1835. IpxCompleteRequest (Request);
  1836. IpxFreeRequest (Device, Request);
  1837. }
  1838. //
  1839. // Return the immediate status code to the caller.
  1840. //
  1841. return Status;
  1842. } /* IpxDispatchOpenClose */
  1843. #define IOCTL_IPX_LOAD_SPX _IPX_CONTROL_CODE( 0x5678, METHOD_BUFFERED )
  1844. NTSYSAPI
  1845. NTSTATUS
  1846. NTAPI
  1847. ZwLoadDriver(
  1848. IN PUNICODE_STRING DriverServiceName
  1849. );
  1850. NTSTATUS
  1851. IpxDispatchDeviceControl(
  1852. IN PDEVICE_OBJECT DeviceObject,
  1853. IN PIRP Irp
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. This routine dispatches TDI request types to different handlers based
  1858. on the minor IOCTL function code in the IRP's current stack location.
  1859. In addition to cracking the minor function code, this routine also
  1860. reaches into the IRP and passes the packetized parameters stored there
  1861. as parameters to the various TDI request handlers so that they are
  1862. not IRP-dependent.
  1863. Arguments:
  1864. DeviceObject - Pointer to the device object for this driver.
  1865. Irp - Pointer to the request packet representing the I/O request.
  1866. Return Value:
  1867. The function value is the status of the operation.
  1868. --*/
  1869. {
  1870. NTSTATUS Status;
  1871. PDEVICE Device = IpxDevice;
  1872. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp);
  1873. static NDIS_STRING SpxServiceName = NDIS_STRING_CONST ("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\NwlnkSpx");
  1874. KPROCESSOR_MODE PreviousMode;
  1875. ASSERT( DeviceObject->DeviceExtension == IpxDevice );
  1876. //
  1877. // Branch to the appropriate request handler. Preliminary checking of
  1878. // the size of the request block is performed here so that it is known
  1879. // in the handlers that the minimum input parameters are readable. It
  1880. // is *not* determined here whether variable length input fields are
  1881. // passed correctly; this is a check which must be made within each routine.
  1882. //
  1883. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  1884. case IOCTL_TDI_QUERY_DIRECT_SENDDG_HANDLER: {
  1885. #ifdef SUNDOWN
  1886. PULONG_PTR EntryPoint;
  1887. #else
  1888. PULONG EntryPoint;
  1889. #endif
  1890. //
  1891. // This is the LanmanServer trying to get the send
  1892. // entry point.
  1893. //
  1894. IPX_DEBUG (BIND, ("Direct send entry point being returned\n"));
  1895. EntryPoint = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1896. //
  1897. // 96390: SEC PROBES [ShreeM]
  1898. //
  1899. //
  1900. // Get previous processor mode
  1901. //
  1902. PreviousMode = ExGetPreviousMode();
  1903. if (PreviousMode != KernelMode) {
  1904. try {
  1905. #ifdef SUNDOWN
  1906. ProbeForWrite( EntryPoint,
  1907. sizeof( ULONG_PTR ),
  1908. TYPE_ALIGNMENT( ULONG_PTR )
  1909. );
  1910. *EntryPoint = (ULONG_PTR)IpxTdiSendDatagram;
  1911. #else
  1912. ProbeForWrite( EntryPoint,
  1913. sizeof( ULONG ),
  1914. sizeof( ULONG )
  1915. );
  1916. *EntryPoint = (ULONG)IpxTdiSendDatagram;
  1917. #endif
  1918. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1919. Status = GetExceptionCode();
  1920. Irp->IoStatus.Status = Status;
  1921. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1922. return( Status );
  1923. }
  1924. } else {
  1925. #ifdef SUNDOWN
  1926. *EntryPoint = (ULONG_PTR)IpxTdiSendDatagram;
  1927. #else
  1928. *EntryPoint = (ULONG)IpxTdiSendDatagram;
  1929. #endif
  1930. }
  1931. Status = STATUS_SUCCESS;
  1932. Irp->IoStatus.Status = Status;
  1933. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1934. break;
  1935. }
  1936. case IOCTL_IPX_INTERNAL_BIND:
  1937. //
  1938. // This is a client trying to bind.
  1939. //
  1940. CTEAssert ((IOCTL_IPX_INTERNAL_BIND & 0x3) == METHOD_BUFFERED);
  1941. CTEAssert (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  1942. if ((Device->State == DEVICE_STATE_CLOSED) ||
  1943. (Device->State == DEVICE_STATE_STOPPING)) {
  1944. DbgPrint("IPX:IpxDispatchDeviceControl:Invalid Device state, skip internal bind\n");
  1945. Status = STATUS_INVALID_DEVICE_STATE;
  1946. } else {
  1947. PreviousMode = ExGetPreviousMode();
  1948. if (PreviousMode == KernelMode) {
  1949. Status = IpxInternalBind (Device, Irp);
  1950. } else {
  1951. DbgPrint("IPX:Caller is not in kernel mode.\n");
  1952. Status = STATUS_UNSUCCESSFUL;
  1953. }
  1954. }
  1955. CTEAssert (Status != STATUS_PENDING);
  1956. Irp->IoStatus.Status = Status;
  1957. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1958. break;
  1959. case IOCTL_IPX_LOAD_SPX:
  1960. //
  1961. // The SPX helper dll is asking us to load SPX.
  1962. //
  1963. Status = ZwLoadDriver (&SpxServiceName);
  1964. Irp->IoStatus.Status = Status;
  1965. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1966. break;
  1967. #ifdef SNMP
  1968. case IOCTL_IPX_MIB_GET: {
  1969. //
  1970. // Get the Base MIB entries out of the device. All Host-side
  1971. // entries, appearing in the MS and Novell MIBs are returned.
  1972. //
  1973. PNOVIPXMIB_BASE UserBuffer;
  1974. UserBuffer = (PNOVIPXMIB_BASE)Irp->AssociatedIrp.SystemBuffer;
  1975. Irp->IoStatus.Information = sizeof(NOVIPXMIB_BASE);
  1976. RtlCopyMemory( UserBuffer,
  1977. &Device->MibBase,
  1978. sizeof(NOVIPXMIB_BASE));
  1979. Irp->IoStatus.Status = STATUS_SUCCESS;
  1980. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1981. Status = STATUS_SUCCESS;
  1982. break;
  1983. }
  1984. #endif SNMP
  1985. case MIPX_SEND_DATAGRAM:
  1986. MARK_REQUEST_PENDING(Irp);
  1987. Status = SendIrpFromRt (Device, Irp);
  1988. if (Status == STATUS_PENDING) {
  1989. return STATUS_PENDING;
  1990. } else {
  1991. UNMARK_REQUEST_PENDING(Irp);
  1992. REQUEST_STATUS(Irp) = Status;
  1993. IpxCompleteRequest (Irp);
  1994. IpxFreeRequest (Device, Irp);
  1995. return Status;
  1996. }
  1997. break;
  1998. case MIPX_RCV_DATAGRAM:
  1999. MARK_REQUEST_PENDING(Irp);
  2000. Status = RcvIrpFromRt (Device, Irp);
  2001. if (Status == STATUS_PENDING) {
  2002. return STATUS_PENDING;
  2003. } else {
  2004. UNMARK_REQUEST_PENDING(Irp);
  2005. REQUEST_STATUS(Irp) = Status;
  2006. IpxCompleteRequest (Irp);
  2007. IpxFreeRequest (Device, Irp);
  2008. return Status;
  2009. }
  2010. break;
  2011. default:
  2012. //
  2013. // Convert the user call to the proper internal device call.
  2014. //
  2015. Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp);
  2016. if (Status == STATUS_SUCCESS) {
  2017. //
  2018. // If TdiMapUserRequest returns SUCCESS then the IRP
  2019. // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL
  2020. // IRP, so we dispatch it as usual. The IRP will
  2021. // be completed by this call.
  2022. //
  2023. Status = IpxDispatchInternal (DeviceObject, Irp);
  2024. } else {
  2025. Irp->IoStatus.Status = Status;
  2026. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  2027. }
  2028. break;
  2029. }
  2030. return Status;
  2031. } /* IpxDispatchDeviceControl */
  2032. NTSTATUS
  2033. IpxDispatchInternal (
  2034. IN PDEVICE_OBJECT DeviceObject,
  2035. IN PIRP Irp
  2036. )
  2037. /*++
  2038. Routine Description:
  2039. This routine dispatches TDI request types to different handlers based
  2040. on the minor IOCTL function code in the IRP's current stack location.
  2041. In addition to cracking the minor function code, this routine also
  2042. reaches into the IRP and passes the packetized parameters stored there
  2043. as parameters to the various TDI request handlers so that they are
  2044. not IRP-dependent.
  2045. Arguments:
  2046. DeviceObject - Pointer to the device object for this driver.
  2047. Irp - Pointer to the request packet representing the I/O request.
  2048. Return Value:
  2049. The function value is the status of the operation.
  2050. --*/
  2051. {
  2052. NTSTATUS Status;
  2053. PDEVICE Device = IpxDevice;
  2054. PREQUEST Request;
  2055. ASSERT( DeviceObject->DeviceExtension == IpxDevice );
  2056. if (Device->State == DEVICE_STATE_OPEN) {
  2057. //
  2058. // Allocate a request to track this IRP.
  2059. //
  2060. Request = IpxAllocateRequest (Device, Irp);
  2061. IF_NOT_ALLOCATED(Request) {
  2062. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  2063. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  2064. return STATUS_INSUFFICIENT_RESOURCES;
  2065. }
  2066. //
  2067. // Make sure status information is consistent every time.
  2068. //
  2069. MARK_REQUEST_PENDING(Request);
  2070. #if DBG
  2071. REQUEST_STATUS(Request) = STATUS_PENDING;
  2072. REQUEST_INFORMATION(Request) = 0;
  2073. #endif
  2074. //
  2075. // Branch to the appropriate request handler. Preliminary checking of
  2076. // the size of the request block is performed here so that it is known
  2077. // in the handlers that the minimum input parameters are readable. It
  2078. // is *not* determined here whether variable length input fields are
  2079. // passed correctly; this is a check which must be made within each routine.
  2080. //
  2081. switch (REQUEST_MINOR_FUNCTION(Request)) {
  2082. case TDI_SEND_DATAGRAM:
  2083. Status = IpxTdiSendDatagram (DeviceObject, Request);
  2084. break;
  2085. case TDI_ACTION:
  2086. Status = IpxTdiAction (Device, Request);
  2087. break;
  2088. case TDI_QUERY_INFORMATION:
  2089. Status = IpxTdiQueryInformation (Device, Request);
  2090. break;
  2091. case TDI_RECEIVE_DATAGRAM:
  2092. Status = IpxTdiReceiveDatagram (Request);
  2093. break;
  2094. case TDI_SET_EVENT_HANDLER:
  2095. Status = IpxTdiSetEventHandler (Request);
  2096. break;
  2097. case TDI_SET_INFORMATION:
  2098. Status = IpxTdiSetInformation (Device, Request);
  2099. break;
  2100. //
  2101. // Something we don't know about was submitted.
  2102. //
  2103. default:
  2104. Status = STATUS_INVALID_DEVICE_REQUEST;
  2105. }
  2106. //
  2107. // Return the immediate status code to the caller.
  2108. //
  2109. if (Status == STATUS_PENDING) {
  2110. return STATUS_PENDING;
  2111. } else {
  2112. UNMARK_REQUEST_PENDING(Request);
  2113. REQUEST_STATUS(Request) = Status;
  2114. IpxCompleteRequest (Request);
  2115. IpxFreeRequest (Device, Request);
  2116. return Status;
  2117. }
  2118. } else {
  2119. //
  2120. // The device was not open.
  2121. //
  2122. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  2123. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  2124. return STATUS_INVALID_DEVICE_STATE;
  2125. }
  2126. } /* IpxDispatchInternal */
  2127. PVOID
  2128. IpxpAllocateMemory(
  2129. IN ULONG BytesNeeded,
  2130. IN ULONG Tag,
  2131. IN BOOLEAN ChargeDevice
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. This routine allocates memory, making sure it is within
  2136. the limit allowed by the device.
  2137. Arguments:
  2138. BytesNeeded - The number of bytes to allocated.
  2139. ChargeDevice - TRUE if the device should be charged.
  2140. Return Value:
  2141. None.
  2142. --*/
  2143. {
  2144. PVOID Memory;
  2145. PDEVICE Device = IpxDevice;
  2146. if (ChargeDevice) {
  2147. if ((Device->MemoryLimit != 0) &&
  2148. (((LONG)(Device->MemoryUsage + BytesNeeded) >
  2149. Device->MemoryLimit))) {
  2150. IpxPrint1 ("IPX: Could not allocate %d: limit\n", BytesNeeded);
  2151. IpxWriteResourceErrorLog(
  2152. Device->DeviceObject,
  2153. EVENT_TRANSPORT_RESOURCE_POOL,
  2154. BytesNeeded,
  2155. Tag);
  2156. return NULL;
  2157. }
  2158. }
  2159. #if ISN_NT
  2160. Memory = ExAllocatePoolWithTag (NonPagedPool, BytesNeeded, ' XPI');
  2161. #else
  2162. Memory = CTEAllocMem (BytesNeeded);
  2163. #endif
  2164. if (Memory == NULL) {
  2165. IpxPrint1("IPX: Could not allocate %d: no pool\n", BytesNeeded);
  2166. if (ChargeDevice) {
  2167. IpxWriteResourceErrorLog(
  2168. Device->DeviceObject,
  2169. EVENT_TRANSPORT_RESOURCE_POOL,
  2170. BytesNeeded,
  2171. Tag);
  2172. }
  2173. return NULL;
  2174. }
  2175. if (ChargeDevice) {
  2176. Device->MemoryUsage += BytesNeeded;
  2177. }
  2178. return Memory;
  2179. } /* IpxpAllocateMemory */
  2180. VOID
  2181. IpxpFreeMemory(
  2182. IN PVOID Memory,
  2183. IN ULONG BytesAllocated,
  2184. IN BOOLEAN ChargeDevice
  2185. )
  2186. /*++
  2187. Routine Description:
  2188. This routine frees memory allocated with IpxpAllocateMemory.
  2189. Arguments:
  2190. Memory - The memory allocated.
  2191. BytesAllocated - The number of bytes to freed.
  2192. ChargeDevice - TRUE if the device should be charged.
  2193. Return Value:
  2194. None.
  2195. --*/
  2196. {
  2197. PDEVICE Device = IpxDevice;
  2198. #if ISN_NT
  2199. ExFreePool (Memory);
  2200. #else
  2201. CTEFreeMem (Memory);
  2202. #endif
  2203. if (ChargeDevice) {
  2204. Device->MemoryUsage -= BytesAllocated;
  2205. }
  2206. } /* IpxpFreeMemory */
  2207. #if DBG
  2208. PVOID
  2209. IpxpAllocateTaggedMemory(
  2210. IN ULONG BytesNeeded,
  2211. IN ULONG Tag,
  2212. IN PUCHAR Description
  2213. )
  2214. /*++
  2215. Routine Description:
  2216. This routine allocates memory, charging it to the device.
  2217. If it cannot allocate memory it uses the Tag and Descriptor
  2218. to log an error.
  2219. Arguments:
  2220. BytesNeeded - The number of bytes to allocated.
  2221. Tag - A unique ID used in the error log.
  2222. Description - A text description of the allocation.
  2223. Return Value:
  2224. None.
  2225. --*/
  2226. {
  2227. PVOID Memory;
  2228. UNREFERENCED_PARAMETER(Description);
  2229. Memory = IpxpAllocateMemory(BytesNeeded, Tag, (BOOLEAN)(Tag != MEMORY_CONFIG));
  2230. if (Memory) {
  2231. (VOID)IPX_ADD_ULONG(
  2232. &IpxMemoryTag[Tag].BytesAllocated,
  2233. BytesNeeded,
  2234. &IpxMemoryInterlock);
  2235. }
  2236. return Memory;
  2237. } /* IpxpAllocateTaggedMemory */
  2238. VOID
  2239. IpxpFreeTaggedMemory(
  2240. IN PVOID Memory,
  2241. IN ULONG BytesAllocated,
  2242. IN ULONG Tag,
  2243. IN PUCHAR Description
  2244. )
  2245. /*++
  2246. Routine Description:
  2247. This routine frees memory allocated with IpxpAllocateTaggedMemory.
  2248. Arguments:
  2249. Memory - The memory allocated.
  2250. BytesAllocated - The number of bytes to freed.
  2251. Tag - A unique ID used in the error log.
  2252. Description - A text description of the allocation.
  2253. Return Value:
  2254. None.
  2255. --*/
  2256. {
  2257. UNREFERENCED_PARAMETER(Description);
  2258. (VOID)IPX_ADD_ULONG(
  2259. &IpxMemoryTag[Tag].BytesAllocated,
  2260. (ULONG)(-(LONG)BytesAllocated),
  2261. &IpxMemoryInterlock);
  2262. IpxpFreeMemory (Memory, BytesAllocated, (BOOLEAN)(Tag != MEMORY_CONFIG));
  2263. } /* IpxpFreeTaggedMemory */
  2264. #endif
  2265. VOID
  2266. IpxWriteResourceErrorLog(
  2267. IN PDEVICE_OBJECT DeviceObject,
  2268. IN NTSTATUS ErrorCode,
  2269. IN ULONG BytesNeeded,
  2270. IN ULONG UniqueErrorValue
  2271. )
  2272. /*++
  2273. Routine Description:
  2274. This routine allocates and writes an error log entry which has
  2275. a %3 value that needs to be converted to a string. It is currently
  2276. used for EVENT_TRANSPORT_RESOURCE_POOL and EVENT_IPX_INTERNAL_NET_
  2277. INVALID.
  2278. Arguments:
  2279. DeviceObject - Pointer to the system device object.
  2280. ErrorCode - The transport event code.
  2281. BytesNeeded - If applicable, the number of bytes that could not
  2282. be allocated -- will be put in the dump data.
  2283. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  2284. packet and converted for use as the %3 string.
  2285. Return Value:
  2286. None.
  2287. --*/
  2288. {
  2289. PIO_ERROR_LOG_PACKET errorLogEntry;
  2290. UCHAR EntrySize;
  2291. PUCHAR StringLoc;
  2292. ULONG TempUniqueError;
  2293. PDEVICE Device = IpxDevice;
  2294. static WCHAR UniqueErrorBuffer[9] = L"00000000";
  2295. UINT CurrentDigit;
  2296. INT i;
  2297. //
  2298. // Convert the error value into a buffer.
  2299. //
  2300. TempUniqueError = UniqueErrorValue;
  2301. i = 8;
  2302. do {
  2303. CurrentDigit = TempUniqueError & 0xf;
  2304. TempUniqueError >>= 4;
  2305. i--;
  2306. if (CurrentDigit >= 0xa) {
  2307. UniqueErrorBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A');
  2308. } else {
  2309. UniqueErrorBuffer[i] = (WCHAR)(CurrentDigit + L'0');
  2310. }
  2311. } while (TempUniqueError);
  2312. // cast to UCHAR to avoid 64-bit warning.
  2313. EntrySize = (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) +
  2314. Device->DeviceNameLength +
  2315. sizeof(UniqueErrorBuffer) - (i * sizeof(WCHAR)));
  2316. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  2317. DeviceObject,
  2318. EntrySize
  2319. );
  2320. if (errorLogEntry != NULL) {
  2321. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  2322. errorLogEntry->RetryCount = (UCHAR)-1;
  2323. errorLogEntry->DumpDataSize = sizeof(ULONG);
  2324. errorLogEntry->NumberOfStrings = 2;
  2325. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
  2326. errorLogEntry->EventCategory = 0;
  2327. errorLogEntry->ErrorCode = ErrorCode;
  2328. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  2329. errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  2330. errorLogEntry->SequenceNumber = (ULONG)-1;
  2331. errorLogEntry->IoControlCode = 0;
  2332. errorLogEntry->DumpData[0] = BytesNeeded;
  2333. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  2334. // This routine may be called before IpxDevice is created.
  2335. if (Device != NULL) {
  2336. RtlCopyMemory (StringLoc, Device->DeviceName, Device->DeviceNameLength);
  2337. StringLoc += Device->DeviceNameLength;
  2338. }
  2339. RtlCopyMemory (StringLoc, UniqueErrorBuffer + i, sizeof(UniqueErrorBuffer) - (i * sizeof(WCHAR)));
  2340. IoWriteErrorLogEntry(errorLogEntry);
  2341. }
  2342. } /* IpxWriteResourceErrorLog */
  2343. VOID
  2344. IpxWriteGeneralErrorLog(
  2345. IN PDEVICE_OBJECT DeviceObject,
  2346. IN NTSTATUS ErrorCode,
  2347. IN ULONG UniqueErrorValue,
  2348. IN NTSTATUS FinalStatus,
  2349. IN PWSTR SecondString,
  2350. IN ULONG DumpDataCount,
  2351. IN ULONG DumpData[]
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. This routine allocates and writes an error log entry indicating
  2356. a general problem as indicated by the parameters. It handles
  2357. event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND,
  2358. TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these
  2359. events have messages with one or two strings in them.
  2360. Arguments:
  2361. DeviceObject - Pointer to the system device object, or this may be
  2362. a driver object instead.
  2363. ErrorCode - The transport event code.
  2364. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  2365. packet.
  2366. FinalStatus - Used as the FinalStatus in the error log packet.
  2367. SecondString - If not NULL, the string to use as the %3
  2368. value in the error log packet.
  2369. DumpDataCount - The number of ULONGs of dump data.
  2370. DumpData - Dump data for the packet.
  2371. Return Value:
  2372. None.
  2373. --*/
  2374. {
  2375. PIO_ERROR_LOG_PACKET errorLogEntry;
  2376. UCHAR EntrySize;
  2377. ULONG SecondStringSize;
  2378. PUCHAR StringLoc;
  2379. PDEVICE Device = IpxDevice;
  2380. static WCHAR DriverName[9] = L"NwlnkIpx";
  2381. #if DBG
  2382. if ((sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount * sizeof(ULONG))) > 255) {
  2383. DbgPrint("IPX: Data size is greater than the maximum size allowed by UCHAR\n");
  2384. }
  2385. #endif
  2386. EntrySize = (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) +
  2387. (DumpDataCount * sizeof(ULONG)));
  2388. if (DeviceObject->Type == IO_TYPE_DEVICE) {
  2389. EntrySize += (UCHAR)Device->DeviceNameLength;
  2390. } else {
  2391. EntrySize += sizeof(DriverName);
  2392. }
  2393. if (SecondString) {
  2394. SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
  2395. EntrySize += (UCHAR)SecondStringSize;
  2396. }
  2397. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  2398. DeviceObject,
  2399. EntrySize
  2400. );
  2401. if (errorLogEntry != NULL) {
  2402. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  2403. errorLogEntry->RetryCount = (UCHAR)-1;
  2404. errorLogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
  2405. errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2;
  2406. errorLogEntry->StringOffset = (USHORT)
  2407. (sizeof(IO_ERROR_LOG_PACKET) + ((DumpDataCount-1) * sizeof(ULONG)));
  2408. errorLogEntry->EventCategory = 0;
  2409. errorLogEntry->ErrorCode = ErrorCode;
  2410. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  2411. errorLogEntry->FinalStatus = FinalStatus;
  2412. errorLogEntry->SequenceNumber = (ULONG)-1;
  2413. errorLogEntry->IoControlCode = 0;
  2414. if (DumpDataCount) {
  2415. RtlCopyMemory(errorLogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
  2416. }
  2417. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  2418. if (DeviceObject->Type == IO_TYPE_DEVICE) {
  2419. RtlCopyMemory (StringLoc, Device->DeviceName, Device->DeviceNameLength);
  2420. StringLoc += Device->DeviceNameLength;
  2421. } else {
  2422. RtlCopyMemory (StringLoc, DriverName, sizeof(DriverName));
  2423. StringLoc += sizeof(DriverName);
  2424. }
  2425. if (SecondString) {
  2426. RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
  2427. }
  2428. IoWriteErrorLogEntry(errorLogEntry);
  2429. } else {
  2430. DbgPrint("IPX: Failed to allocate %d bytes for IO error log entry.\n", EntrySize);
  2431. }
  2432. } /* IpxWriteGeneralErrorLog */
  2433. VOID
  2434. IpxWriteOidErrorLog(
  2435. IN PDEVICE_OBJECT DeviceObject,
  2436. IN NTSTATUS ErrorCode,
  2437. IN NTSTATUS FinalStatus,
  2438. IN PWSTR AdapterString,
  2439. IN ULONG OidValue
  2440. )
  2441. /*++
  2442. Routine Description:
  2443. This routine allocates and writes an error log entry indicating
  2444. a problem querying or setting an OID on an adapter. It handles
  2445. event codes SET_OID_FAILED and QUERY_OID_FAILED.
  2446. Arguments:
  2447. DeviceObject - Pointer to the system device object.
  2448. ErrorCode - Used as the ErrorCode in the error log packet.
  2449. FinalStatus - Used as the FinalStatus in the error log packet.
  2450. AdapterString - The name of the adapter we were bound to.
  2451. OidValue - The OID which could not be set or queried.
  2452. Return Value:
  2453. None.
  2454. --*/
  2455. {
  2456. PIO_ERROR_LOG_PACKET errorLogEntry;
  2457. UCHAR EntrySize;
  2458. ULONG AdapterStringSize;
  2459. PUCHAR StringLoc;
  2460. PDEVICE Device = IpxDevice;
  2461. static WCHAR OidBuffer[9] = L"00000000";
  2462. INT i;
  2463. UINT CurrentDigit;
  2464. AdapterStringSize = (wcslen(AdapterString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
  2465. EntrySize = (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) -
  2466. sizeof(ULONG) +
  2467. Device->DeviceNameLength +
  2468. AdapterStringSize +
  2469. sizeof(OidBuffer));
  2470. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  2471. DeviceObject,
  2472. EntrySize
  2473. );
  2474. //
  2475. // Convert the OID into a buffer.
  2476. //
  2477. for (i=7; i>=0; i--) {
  2478. CurrentDigit = OidValue & 0xf;
  2479. OidValue >>= 4;
  2480. if (CurrentDigit >= 0xa) {
  2481. OidBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A');
  2482. } else {
  2483. OidBuffer[i] = (WCHAR)(CurrentDigit + L'0');
  2484. }
  2485. }
  2486. if (errorLogEntry != NULL) {
  2487. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  2488. errorLogEntry->RetryCount = (UCHAR)-1;
  2489. errorLogEntry->DumpDataSize = 0;
  2490. errorLogEntry->NumberOfStrings = 3;
  2491. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
  2492. errorLogEntry->EventCategory = 0;
  2493. errorLogEntry->ErrorCode = ErrorCode;
  2494. errorLogEntry->UniqueErrorValue = 0;
  2495. errorLogEntry->FinalStatus = FinalStatus;
  2496. errorLogEntry->SequenceNumber = (ULONG)-1;
  2497. errorLogEntry->IoControlCode = 0;
  2498. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  2499. RtlCopyMemory (StringLoc, Device->DeviceName, Device->DeviceNameLength);
  2500. StringLoc += Device->DeviceNameLength;
  2501. RtlCopyMemory (StringLoc, OidBuffer, sizeof(OidBuffer));
  2502. StringLoc += sizeof(OidBuffer);
  2503. RtlCopyMemory (StringLoc, AdapterString, AdapterStringSize);
  2504. IoWriteErrorLogEntry(errorLogEntry);
  2505. }
  2506. } /* IpxWriteOidErrorLog */
  2507. VOID
  2508. IpxPnPUpdateDevice(
  2509. IN PDEVICE Device
  2510. )
  2511. /*++
  2512. Routine Description:
  2513. Updates datagram sizes, lookahead sizes, etc. in the Device as a result
  2514. of a new binding coming in.
  2515. Arguments:
  2516. Device - The IPX device object.
  2517. Return Value:
  2518. None.
  2519. --*/
  2520. {
  2521. ULONG AnnouncedMaxDatagram = 0, RealMaxDatagram = 0, MaxLookahead = 0;
  2522. ULONG LinkSpeed = 0, MacOptions = 0;
  2523. ULONG i;
  2524. PBINDING Binding;
  2525. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2526. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle);
  2527. if (Device->ValidBindings) {
  2528. //
  2529. // Calculate some values based on all the bindings.
  2530. //
  2531. MaxLookahead = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->MaxLookaheadData; // largest binding value
  2532. AnnouncedMaxDatagram = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->AnnouncedMaxDatagramSize; // smallest binding value
  2533. RealMaxDatagram = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->RealMaxDatagramSize; // smallest binding value
  2534. if (NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->LineUp) {
  2535. LinkSpeed = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->MediumSpeed; // smallest binding value
  2536. } else {
  2537. LinkSpeed = 0xffffffff;
  2538. }
  2539. MacOptions = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->Adapter->MacInfo.MacOptions; // AND of binding values
  2540. for (i = FIRST_REAL_BINDING; i <= Device->ValidBindings; i++) {
  2541. Binding = NIC_ID_TO_BINDING_NO_ILOCK(Device, i);
  2542. if (!Binding) {
  2543. continue;
  2544. }
  2545. if (Binding->MaxLookaheadData > MaxLookahead) {
  2546. MaxLookahead = Binding->MaxLookaheadData;
  2547. }
  2548. if (Binding->AnnouncedMaxDatagramSize < AnnouncedMaxDatagram) {
  2549. AnnouncedMaxDatagram = Binding->AnnouncedMaxDatagramSize;
  2550. }
  2551. if (Binding->RealMaxDatagramSize < RealMaxDatagram) {
  2552. RealMaxDatagram = Binding->RealMaxDatagramSize;
  2553. }
  2554. if (Binding->LineUp && (Binding->MediumSpeed < LinkSpeed)) {
  2555. LinkSpeed = Binding->MediumSpeed;
  2556. }
  2557. MacOptions &= Binding->Adapter->MacInfo.MacOptions;
  2558. }
  2559. //
  2560. // If we couldn't find anything better, use the speed from
  2561. // the first binding.
  2562. //
  2563. if (LinkSpeed == 0xffffffff) {
  2564. Device->LinkSpeed = NIC_ID_TO_BINDING_NO_ILOCK(Device, 1)->MediumSpeed;
  2565. } else {
  2566. Device->LinkSpeed = LinkSpeed;
  2567. }
  2568. Device->MacOptions = MacOptions;
  2569. } else {
  2570. //
  2571. // zero bindings means LinkSpeed = 0;
  2572. //
  2573. Device->LinkSpeed = 0;
  2574. }
  2575. Device->Information.MaxDatagramSize = AnnouncedMaxDatagram;
  2576. Device->RealMaxDatagramSize = RealMaxDatagram;
  2577. Device->Information.MaximumLookaheadData = MaxLookahead;
  2578. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle);
  2579. }
  2580. VOID
  2581. IpxPnPUpdateBindingArray(
  2582. IN PDEVICE Device,
  2583. IN PADAPTER Adapter,
  2584. IN PBINDING_CONFIG ConfigBinding
  2585. )
  2586. /*++
  2587. Routine Description:
  2588. This routine is called to update the binding array to
  2589. add the new bindings that appeared in this PnP event.
  2590. The order of bindings in the array is as follows:
  2591. - First comes the first binding to each LAN network
  2592. - Following that are all WAN bindings
  2593. - Following that are any duplicate bindings to LAN networks
  2594. (the others in the "binding set").
  2595. This routine inserts the bindings while maintaining this
  2596. order by resolving binding sets.
  2597. The bindings are also inserted into the RIP database.
  2598. If "global wan net" is true we will advertise up to
  2599. and including the first wan binding as the highest nic
  2600. id; otherwise we advertise up to and including the last
  2601. wan binding. In all cases the duplicate bindings are
  2602. hidden.
  2603. Updates the SapNicCount, Device->FirstLanNicId and Device->FirstWanNicId
  2604. Arguments:
  2605. Device - The IPX device object.
  2606. Adapter - The adapter added in this PnP event
  2607. ValidBindings - the number of bindings valid for this adapter (if LAN)
  2608. Return Value:
  2609. None.
  2610. --*/
  2611. {
  2612. ULONG i, j;
  2613. PBINDING Binding, MasterBinding;
  2614. NTSTATUS status;
  2615. //
  2616. // Insert in proper place; if WAN, after all the WAN bindings
  2617. // If LAN, check for binding sets and insert in proper place
  2618. // Also, insert into the Rip Tables.
  2619. //
  2620. //
  2621. // Go thru' the bindings for this adapter, inserting into the
  2622. // binding array in place
  2623. //
  2624. for (i = 0; i < ConfigBinding->FrameTypeCount; i++) {
  2625. ULONG MappedFrameType = ISN_FRAME_TYPE_802_3;
  2626. //
  2627. // Store in the preference order.
  2628. // Map the frame types since we could have a case where the user selects a FrameType (say, EthernetII on FDDI)
  2629. // which maps to a different FrameType (802.2). Then we would fail to find the binding in the adapter array;
  2630. // we could potentialy add a binding twice (if two frame types map to the same Frame, then we would go to the
  2631. // mapped one twice). This is taken care of by purging dups from the ConfigBinding->FrameType array when we
  2632. // create the bindings off of the Adapter (see call to IpxBindToAdapter).
  2633. //
  2634. MacMapFrameType(
  2635. Adapter->MacInfo.RealMediumType,
  2636. ConfigBinding->FrameType[i],
  2637. &MappedFrameType);
  2638. Binding = Adapter->Bindings[MappedFrameType];
  2639. if (!Binding){
  2640. continue;
  2641. }
  2642. CTEAssert(Binding->FrameType == MappedFrameType);
  2643. Binding->fInfoIndicated = FALSE;
  2644. if (Adapter->MacInfo.MediumAsync) {
  2645. PBINDING DemandDialBinding;
  2646. //
  2647. // WAN: Place after the HighestExternalNicId, with space for WanLine # of bindings.
  2648. // Update the First/LastWanNicId.
  2649. //
  2650. Adapter->FirstWanNicId = (USHORT)Device->HighestExternalNicId+1;
  2651. Adapter->LastWanNicId = (USHORT)(Device->HighestExternalNicId + Adapter->WanNicIdCount);
  2652. //
  2653. // Make sure we dont overflow the array
  2654. // Re-alloc the array to fit the new bindings
  2655. //
  2656. if (Device->ValidBindings+Adapter->WanNicIdCount >= Device->MaxBindings) {
  2657. status = IpxPnPReallocateBindingArray(Device, Adapter->WanNicIdCount);
  2658. if (status != STATUS_SUCCESS) {
  2659. DbgPrint("!!!!! IpxPnPReallocateBindingArray failed with status %x !!!!!\n", status);
  2660. ASSERT(FALSE);
  2661. return;
  2662. }
  2663. }
  2664. //
  2665. // Move Slaves down by WanNicIdCount# of entries
  2666. //
  2667. for (j = Device->ValidBindings; j > Device->HighestExternalNicId; j--) {
  2668. INSERT_BINDING(Device, j+Adapter->WanNicIdCount, NIC_ID_TO_BINDING_NO_ILOCK(Device, j));
  2669. INSERT_BINDING(Device, j, NULL);
  2670. if (NIC_ID_TO_BINDING_NO_ILOCK(Device, j+Adapter->WanNicIdCount)) {
  2671. NIC_ID_TO_BINDING_NO_ILOCK(Device, j+Adapter->WanNicIdCount)->NicId += (USHORT)Adapter->WanNicIdCount;
  2672. }
  2673. }
  2674. //
  2675. // Insert the WAN binding in the place just allocated
  2676. //
  2677. INSERT_BINDING(Device, Device->HighestExternalNicId+1, Binding);
  2678. SET_VERSION(Device, Device->HighestExternalNicId+1);
  2679. Binding->NicId = (USHORT)Device->HighestExternalNicId+1;
  2680. //
  2681. // Update the indices
  2682. //
  2683. //
  2684. // We do not create WanNicIdCount number of bindings, just one!
  2685. // NDISWAN tells us that there are 1000 WAN lines by default.
  2686. // The rest will be created on WAN_LINE_UP in ndis.c [ShreeM]
  2687. //
  2688. Device->HighestExternalNicId += (USHORT)Adapter->WanNicIdCount;
  2689. Device->ValidBindings += (USHORT)Adapter->WanNicIdCount;
  2690. Device->BindingCount += (USHORT)Adapter->WanNicIdCount;
  2691. Device->SapNicCount++;
  2692. //
  2693. // Since we initialize FirstWanNicId to 1, we need to compare against that.
  2694. // In case of no LAN bindings, we are fine since we have only one WAN binding initally
  2695. // (all the other WAN lines have place holders).
  2696. //
  2697. if (Device->FirstWanNicId == (USHORT)1) {
  2698. Device->FirstWanNicId = Binding->NicId;
  2699. }
  2700. //
  2701. // Prime the DemandDial binding too.
  2702. //
  2703. //
  2704. // First allocate the memory for the binding.
  2705. //
  2706. status = IpxCreateBinding(
  2707. Device,
  2708. NULL,
  2709. 0,
  2710. Adapter->AdapterName,
  2711. &DemandDialBinding);
  2712. if (status != STATUS_SUCCESS) {
  2713. IpxWriteGeneralErrorLog(
  2714. (PVOID)IpxDevice->DeviceObject,
  2715. EVENT_TRANSPORT_RESOURCE_POOL,
  2716. 810,
  2717. status,
  2718. L"IpxPnPUpdateBindingArray: failed to create demand dial binding",
  2719. 0,
  2720. NULL);
  2721. DbgPrint("IPX: IpxCreateBinding on demand dial failed with status %x\n.",status);
  2722. } else {
  2723. //
  2724. // Copy over all the values from the first WAN binding created above.
  2725. //
  2726. RtlCopyMemory(DemandDialBinding, Binding, sizeof(BINDING));
  2727. INSERT_BINDING(Device, (SHORT)DEMAND_DIAL_ADAPTER_CONTEXT, DemandDialBinding);
  2728. DemandDialBinding->NicId = (USHORT)DEMAND_DIAL_ADAPTER_CONTEXT;
  2729. DemandDialBinding->FwdAdapterContext = INVALID_CONTEXT_VALUE;
  2730. IpxReferenceBinding(DemandDialBinding, BREF_FWDOPEN); // so it appears the FWD opened it.
  2731. }
  2732. //
  2733. // This should be done after all the auto-detect bindings have been thrown away.
  2734. //
  2735. // IpxPnPUpdateDevice(Device, Binding);
  2736. //
  2737. // Since WAN can have only one frame type, break
  2738. //
  2739. break;
  2740. } else {
  2741. Device->BindingCount++;
  2742. //
  2743. // Make sure we dont overflow the array
  2744. // Re-alloc the array to fit the new bindings
  2745. //
  2746. if (Device->ValidBindings+1 >= Device->MaxBindings) {
  2747. status = IpxPnPReallocateBindingArray(Device, 1);
  2748. CTEAssert(status == STATUS_SUCCESS);
  2749. }
  2750. //
  2751. // LAN: Figure out if it is a slave binding only for non-auto-detect bindings.
  2752. //
  2753. {
  2754. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  2755. for (j = FIRST_REAL_BINDING; j < Index; j++) {
  2756. MasterBinding = NIC_ID_TO_BINDING_NO_ILOCK(Device, j);
  2757. if (MasterBinding &&
  2758. (MasterBinding->ConfiguredNetworkNumber) &&
  2759. (MasterBinding->ConfiguredNetworkNumber == Binding->ConfiguredNetworkNumber) &&
  2760. (MasterBinding->FrameType == Binding->FrameType) &&
  2761. (MasterBinding->Adapter->MacInfo.MediumType == Binding->Adapter->MacInfo.MediumType)) {
  2762. CTEAssert(Binding->ConfiguredNetworkNumber);
  2763. break;
  2764. }
  2765. }
  2766. }
  2767. if (j < Device->HighestExternalNicId) {
  2768. //
  2769. // Slave binding
  2770. //
  2771. //
  2772. // Now make MasterBinding the head of a binding set.
  2773. //
  2774. if (MasterBinding->BindingSetMember) {
  2775. //
  2776. // Just insert ourselves in the chain.
  2777. //
  2778. #if DBG
  2779. DbgPrint ("IPX: %ws is also on network %lx\n",
  2780. Binding->Adapter->AdapterName,
  2781. REORDER_ULONG (Binding->LocalAddress.NetworkAddress));
  2782. #endif
  2783. IPX_DEBUG (AUTO_DETECT, ("Add %lx to binding set of %lx\n", Binding, MasterBinding));
  2784. CTEAssert (MasterBinding->CurrentSendBinding);
  2785. Binding->NextBinding = MasterBinding->NextBinding;
  2786. } else {
  2787. //
  2788. // Start the chain with the two bindings in it.
  2789. //
  2790. #if DBG
  2791. DbgPrint ("IPX: %lx and %lx are on the same network %lx, will load balance\n",
  2792. MasterBinding->Adapter->AdapterName, Binding->Adapter->AdapterName,
  2793. REORDER_ULONG (Binding->LocalAddress.NetworkAddress));
  2794. #endif
  2795. IPX_DEBUG (AUTO_DETECT, ("Create new %lx in binding set of %lx\n", Binding, MasterBinding));
  2796. MasterBinding->BindingSetMember = TRUE;
  2797. MasterBinding->CurrentSendBinding = MasterBinding;
  2798. MasterBinding->MasterBinding = MasterBinding;
  2799. Binding->NextBinding = MasterBinding;
  2800. }
  2801. MasterBinding->NextBinding = Binding;
  2802. Binding->BindingSetMember = TRUE;
  2803. Binding->ReceiveBroadcast = FALSE;
  2804. Binding->CurrentSendBinding = NULL;
  2805. Binding->MasterBinding = MasterBinding;
  2806. KdPrint((" %x set to FALSE\n", Binding));
  2807. //
  2808. // Since the master binding looks like all members of
  2809. // the binding set to people querying from above, we have
  2810. // to make it the worst-case of all the elements. Generally
  2811. // these will be equal since the frame type and media is
  2812. // the same.
  2813. //
  2814. if (Binding->MaxLookaheadData > MasterBinding->MaxLookaheadData) {
  2815. MasterBinding->MaxLookaheadData = Binding->MaxLookaheadData;
  2816. }
  2817. if (Binding->AnnouncedMaxDatagramSize < MasterBinding->AnnouncedMaxDatagramSize) {
  2818. MasterBinding->AnnouncedMaxDatagramSize = Binding->AnnouncedMaxDatagramSize;
  2819. }
  2820. if (Binding->RealMaxDatagramSize < MasterBinding->RealMaxDatagramSize) {
  2821. MasterBinding->RealMaxDatagramSize = Binding->RealMaxDatagramSize;
  2822. }
  2823. if (Binding->MediumSpeed < MasterBinding->MediumSpeed) {
  2824. MasterBinding->MediumSpeed = Binding->MediumSpeed;
  2825. }
  2826. //
  2827. // Place the binding after the last slave binding
  2828. //
  2829. INSERT_BINDING(Device, Device->ValidBindings+1, Binding);
  2830. SET_VERSION(Device, Device->ValidBindings+1);
  2831. Binding->NicId = (USHORT)Device->ValidBindings+1;
  2832. //
  2833. // Update the indices
  2834. //
  2835. Device->ValidBindings++;
  2836. } else {
  2837. PBINDING WanBinding=NIC_ID_TO_BINDING_NO_ILOCK(Device, Device->HighestLanNicId+1);
  2838. if (WanBinding) {
  2839. WanBinding->Adapter->LastWanNicId++;
  2840. WanBinding->Adapter->FirstWanNicId++;
  2841. }
  2842. //
  2843. // Not a binding set slave binding - just add it after the last LAN binding
  2844. //
  2845. //
  2846. // Move WAN and Slaves down by 1 entry
  2847. //
  2848. for (j = Device->ValidBindings; j > Device->HighestLanNicId; j--) {
  2849. INSERT_BINDING(Device, j+1, NIC_ID_TO_BINDING_NO_ILOCK(Device, j));
  2850. if (NIC_ID_TO_BINDING_NO_ILOCK(Device, j+1)) {
  2851. NIC_ID_TO_BINDING_NO_ILOCK(Device, j+1)->NicId++;
  2852. }
  2853. }
  2854. //
  2855. // Increment the WAN counters in the adapter.
  2856. //
  2857. //
  2858. // Insert the LAN binding in the place just allocated
  2859. //
  2860. INSERT_BINDING(Device, Device->HighestLanNicId+1, Binding);
  2861. SET_VERSION(Device, Device->HighestLanNicId+1);
  2862. Binding->NicId = (USHORT)Device->HighestLanNicId+1;
  2863. //
  2864. // Update the indices
  2865. //
  2866. Device->HighestLanNicId++;
  2867. Device->HighestExternalNicId++;
  2868. Device->ValidBindings++;
  2869. Device->HighestType20NicId++;
  2870. Device->SapNicCount++;
  2871. if (Device->FirstLanNicId == (USHORT)-1) {
  2872. Device->FirstLanNicId = Binding->NicId;
  2873. }
  2874. }
  2875. }
  2876. //
  2877. // Insert this binding in the RIP Tables
  2878. //
  2879. if (Binding->ConfiguredNetworkNumber != 0) {
  2880. status = RipInsertLocalNetwork(
  2881. Binding->ConfiguredNetworkNumber,
  2882. Binding->NicId,
  2883. Binding->Adapter->NdisBindingHandle,
  2884. (USHORT)((839 + Binding->Adapter->MediumSpeed) / Binding->Adapter->MediumSpeed));
  2885. if ((status == STATUS_SUCCESS) ||
  2886. (status == STATUS_DUPLICATE_NAME)) {
  2887. Binding->LocalAddress.NetworkAddress = Binding->ConfiguredNetworkNumber;
  2888. }
  2889. }
  2890. //
  2891. // This should be done after all the auto-detect bindings have been thrown away.
  2892. //
  2893. // IpxPnPUpdateDevice(Device, Binding);
  2894. }
  2895. } /* IpxPnPUpdateBindingArray */
  2896. VOID
  2897. IpxPnPToLoad()
  2898. /*++
  2899. Routine Description:
  2900. This routine takes the driver to LOADED state (from OPEN) when all
  2901. PnP adapters have been removed from the machine.
  2902. Arguments:
  2903. None.
  2904. Return Value:
  2905. None. When the function returns, the driver is in LOADED state.
  2906. --*/
  2907. {
  2908. PBINDING Binding;
  2909. PREQUEST Request;
  2910. PLIST_ENTRY p;
  2911. UINT i;
  2912. NTSTATUS ntStatus;
  2913. KIRQL irql;
  2914. //
  2915. // Complete any pending address notify requests.
  2916. //
  2917. while ((p = ExInterlockedRemoveHeadList(
  2918. &IpxDevice->AddressNotifyQueue,
  2919. &IpxDevice->Lock)) != NULL) {
  2920. Request = LIST_ENTRY_TO_REQUEST(p);
  2921. REQUEST_STATUS(Request) = STATUS_DEVICE_NOT_READY;
  2922. IoAcquireCancelSpinLock( &irql );
  2923. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  2924. IoReleaseCancelSpinLock( irql );
  2925. IpxCompleteRequest (Request);
  2926. IpxFreeRequest (IpxDevice, Request);
  2927. IpxDereferenceDevice (IpxDevice, DREF_ADDRESS_NOTIFY);
  2928. }
  2929. //
  2930. // Cancel the source routing timer if used.
  2931. //
  2932. if (IpxDevice->SourceRoutingUsed) {
  2933. IpxDevice->SourceRoutingUsed = FALSE;
  2934. if (CTEStopTimer (&IpxDevice->SourceRoutingTimer)) {
  2935. IpxDereferenceDevice (IpxDevice, DREF_SR_TIMER);
  2936. }
  2937. }
  2938. //
  2939. // Cancel the RIP long timer, and if we do that then
  2940. // send a RIP DOWN message if needed.
  2941. //
  2942. if (CTEStopTimer (&IpxDevice->RipLongTimer)) {
  2943. if (IpxDevice->RipResponder) {
  2944. if (RipQueueRequest (IpxDevice->VirtualNetworkNumber, RIP_DOWN) == STATUS_PENDING) {
  2945. //
  2946. // If we queue a request, it will stop the timer.
  2947. //
  2948. KeWaitForSingleObject(
  2949. &IpxDevice->UnloadEvent,
  2950. Executive,
  2951. KernelMode,
  2952. TRUE,
  2953. (PLARGE_INTEGER)NULL
  2954. );
  2955. }
  2956. }
  2957. IpxDereferenceDevice (IpxDevice, DREF_LONG_TIMER);
  2958. } else {
  2959. //
  2960. // We couldn't stop the timer, which means it is running,
  2961. // so we need to wait for the event that is kicked when
  2962. // the RIP DOWN messages are done.
  2963. //
  2964. if (IpxDevice->RipResponder) {
  2965. KeWaitForSingleObject(
  2966. &IpxDevice->UnloadEvent,
  2967. Executive,
  2968. KernelMode,
  2969. TRUE,
  2970. (PLARGE_INTEGER)NULL
  2971. );
  2972. }
  2973. }
  2974. } /* IpxPnPToLoad */
  2975. NTSTATUS
  2976. IpxPnPReallocateBindingArray(
  2977. IN PDEVICE Device,
  2978. IN ULONG Size
  2979. )
  2980. /*++
  2981. Routine Description:
  2982. This routine reallocates the binding array when the number of bindings go above
  2983. Device->MaxBindings.
  2984. Arguments:
  2985. Device - pointer to the device.
  2986. Size - the number of new entries required.
  2987. Return Value:
  2988. None.
  2989. --*/
  2990. {
  2991. PBIND_ARRAY_ELEM BindingArray;
  2992. PBIND_ARRAY_ELEM OldBindingArray;
  2993. ULONG Pad=2; // extra bindings we keep around
  2994. ULONG NewSize = Size + Pad + Device->MaxBindings;
  2995. PIPX_DELAYED_FREE_ITEM DelayedFreeItem;
  2996. CTELockHandle LockHandle;
  2997. //
  2998. // The absolute max WAN bindings.
  2999. //
  3000. CTEAssert(Size < 2048);
  3001. //
  3002. // Re-allocate the new array
  3003. //
  3004. BindingArray = (PBIND_ARRAY_ELEM)IpxAllocateMemory (
  3005. NewSize * sizeof(BIND_ARRAY_ELEM),
  3006. MEMORY_BINDING,
  3007. "Binding array");
  3008. if (BindingArray == NULL) {
  3009. IpxWriteGeneralErrorLog(
  3010. (PVOID)Device->DeviceObject,
  3011. EVENT_IPX_NO_ADAPTERS,
  3012. 802,
  3013. STATUS_DEVICE_DOES_NOT_EXIST,
  3014. NULL,
  3015. 0,
  3016. NULL);
  3017. IpxDereferenceDevice (Device, DREF_CREATE);
  3018. DbgPrint ("Failed to allocate memory in binding array expansion\n");
  3019. //
  3020. // Unload the driver here? In case of WAN, we can tolerate this failure. What about LAN?
  3021. //
  3022. return STATUS_INSUFFICIENT_RESOURCES;
  3023. }
  3024. RtlZeroMemory (BindingArray, NewSize * sizeof(BIND_ARRAY_ELEM));
  3025. //
  3026. // Backup the pointer to free the demand dial location.
  3027. //
  3028. CTEGetLock (&Device->Lock, &LockHandle);
  3029. OldBindingArray = Device->Bindings - EXTRA_BINDINGS;
  3030. //
  3031. // Copy the old array into the new one.
  3032. //
  3033. RtlCopyMemory (BindingArray, OldBindingArray, (Device->ValidBindings+1+EXTRA_BINDINGS) * sizeof(BIND_ARRAY_ELEM));
  3034. //
  3035. // Free the old one. Free it on a delayed queue so that all
  3036. // the threads inside this array would come out of it.
  3037. // allocate a work item and queue it on a delayed queue.
  3038. //
  3039. DelayedFreeItem = (PIPX_DELAYED_FREE_ITEM)IpxAllocateMemory (
  3040. sizeof(IPX_DELAYED_FREE_ITEM),
  3041. MEMORY_WORK_ITEM,
  3042. "Work Item");
  3043. if ( DelayedFreeItem ) {
  3044. DelayedFreeItem->Context = (PVOID)OldBindingArray;
  3045. DelayedFreeItem->ContextSize = (Device->MaxBindings+EXTRA_BINDINGS) * sizeof(BIND_ARRAY_ELEM);
  3046. ExInitializeWorkItem(
  3047. &DelayedFreeItem->WorkItem,
  3048. IpxDelayedFreeBindingsArray,
  3049. (PVOID)DelayedFreeItem);
  3050. IpxReferenceDevice(Device,DREF_BINDING);
  3051. ExQueueWorkItem(
  3052. &DelayedFreeItem->WorkItem,
  3053. DelayedWorkQueue);
  3054. // DbgPrint("---------- 3. Queued with IpxDelayedFreeAdapter ----------\n");
  3055. } else {
  3056. //
  3057. // oh well, tough luck. Just delay this thread and then
  3058. // destroy the binding array.
  3059. //
  3060. LARGE_INTEGER Delay;
  3061. Delay.QuadPart = -10*1000; // One second.
  3062. KeDelayExecutionThread(
  3063. KernelMode,
  3064. FALSE,
  3065. &Delay);
  3066. IpxFreeMemory ( OldBindingArray,
  3067. (Device->MaxBindings+EXTRA_BINDINGS) * sizeof(BIND_ARRAY_ELEM),
  3068. MEMORY_BINDING,
  3069. "Binding array");
  3070. }
  3071. IPX_DEBUG(PNP, ("Expand bindarr old: %lx, new: %lx, oldsize: %lx\n",
  3072. Device->Bindings, BindingArray, Device->MaxBindings));
  3073. //
  3074. // We keep BindingArray[-1] as a placeholder for demand dial bindings.
  3075. // This NicId is returned by the Fwd when a FindRoute is done on a demand
  3076. // dial Nic. At the time of the InternalSend, the true Nic is returned.
  3077. // We create a placeholder here to avoid special checks in the critical send path.
  3078. //
  3079. // NOTE: we need to free this demand dial binding as well as ensure that the
  3080. // true binding array pointer is freed at Device Destroy time.
  3081. //
  3082. //
  3083. // Increment beyond the first pointer - we will refer to the just incremented
  3084. // one as Device->Bindings[-1].
  3085. //
  3086. BindingArray += EXTRA_BINDINGS;
  3087. //
  3088. // Use interlocked exchange to assign this since we dont take the BindAccessLock anymore.
  3089. //
  3090. // Device->Bindings = BindingArray;
  3091. SET_VALUE(Device->Bindings, BindingArray);
  3092. Device->MaxBindings = (USHORT)NewSize - EXTRA_BINDINGS;
  3093. CTEFreeLock (&Device->Lock, LockHandle);
  3094. return STATUS_SUCCESS;
  3095. }
  3096. VOID
  3097. IpxDelayedFreeBindingsArray(
  3098. IN PVOID Param
  3099. )
  3100. /*++
  3101. Routine Description:
  3102. This routine frees a binding array on the delayed queue. We wait long enough
  3103. before freeing the binding array to make sure that no threads are accessing the
  3104. binding array. This allows us to access the binding array without the use of
  3105. spinlocks.
  3106. Arguments:
  3107. Param - pointer to the work item.
  3108. Return Value:
  3109. None.
  3110. --*/
  3111. {
  3112. LARGE_INTEGER Delay;
  3113. PIPX_DELAYED_FREE_ITEM DelayedFreeItem = (PIPX_DELAYED_FREE_ITEM) Param;
  3114. PDEVICE Device = IpxDevice;
  3115. Delay.QuadPart = -10*1000; // One second.
  3116. KeDelayExecutionThread(
  3117. KernelMode,
  3118. FALSE,
  3119. &Delay);
  3120. IpxFreeMemory (
  3121. DelayedFreeItem->Context,
  3122. DelayedFreeItem->ContextSize,
  3123. MEMORY_BINDING,
  3124. "Binding array");
  3125. IpxFreeMemory (
  3126. DelayedFreeItem,
  3127. sizeof (IPX_DELAYED_FREE_ITEM),
  3128. MEMORY_WORK_ITEM,
  3129. "Work Item");
  3130. IpxDereferenceDevice(Device, DREF_BINDING);
  3131. // DbgPrint("!!!!!!! 3. Done with IpxDelayedFreeBindingsArray ----------\n");
  3132. } /* IpxDelayedFreeBindingsArray */
  3133. #ifdef _PNP_POWER_
  3134. //++
  3135. // IpxPnPEventHandler
  3136. // * called from NDIS.
  3137. // * We return STATUS_PENDING and perform the work on a WorkerThread
  3138. //
  3139. // IN: ProtocolBindingContext and NetPnpEvent.
  3140. // OUT: NTSTATUS
  3141. //--
  3142. NDIS_STATUS
  3143. IpxPnPEventHandler(
  3144. IN NDIS_HANDLE ProtocolBindingContext,
  3145. IN PNET_PNP_EVENT NetPnPEvent
  3146. )
  3147. {
  3148. PNetPnPEventReserved Reserved;
  3149. CTEEvent *Event;
  3150. int i;
  3151. PVOID Temp;
  3152. Reserved = CTEAllocMem (sizeof(NetPnPEventReserved));
  3153. if (NULL == Reserved) {
  3154. return STATUS_INSUFFICIENT_RESOURCES;
  3155. }
  3156. RtlZeroMemory(Reserved, sizeof(NetPnPEventReserved));
  3157. *((PNetPnPEventReserved *)NetPnPEvent->TransportReserved) = Reserved;
  3158. Event = CTEAllocMem( sizeof(CTEEvent) );
  3159. if ( Event ) {
  3160. CTEInitEvent(Event, IpxDoPnPEvent);
  3161. Reserved->ProtocolBindingContext = ProtocolBindingContext;
  3162. Reserved->Context1 = NULL;
  3163. Reserved->Context2 = NULL;
  3164. Reserved->State = NONE_DONE;
  3165. for(i = 0; i < 3; i++) {
  3166. Reserved->Status[i] = STATUS_SUCCESS;
  3167. }
  3168. CTEScheduleEvent(Event, NetPnPEvent);
  3169. return STATUS_PENDING;
  3170. } else {
  3171. CTEFreeMem(Reserved);
  3172. return STATUS_INSUFFICIENT_RESOURCES;
  3173. }
  3174. }
  3175. //** IpxDoPnPEvent - Handles PNP/PM events.
  3176. //
  3177. // Called from the worker thread event scheduled by IPPnPEvent
  3178. // bWe take action depending on the type of the event.
  3179. //
  3180. // Entry:
  3181. // Context - This is a pointer to a NET_PNP_EVENT that describes
  3182. // the PnP indication.
  3183. //
  3184. // Exit:
  3185. // None.
  3186. //
  3187. void
  3188. IpxDoPnPEvent(
  3189. IN CTEEvent *WorkerThreadEvent,
  3190. IN PVOID Context)
  3191. {
  3192. PNET_PNP_EVENT NetPnPEvent = (PNET_PNP_EVENT) Context;
  3193. UNICODE_STRING DeviceName;
  3194. UNICODE_STRING PDO_Name, *TempStr;
  3195. NDIS_HANDLE ProtocolBindingContext;
  3196. PNetPnPEventReserved Reserved;
  3197. PDEVICE Device = IpxDevice;
  3198. INT i;
  3199. PTDI_PNP_CONTEXT Context1, Context2;
  3200. PADAPTER Adapter;
  3201. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  3202. CTEFreeMem(WorkerThreadEvent);
  3203. //
  3204. // Get the ProtocolBindingContext out
  3205. //
  3206. Reserved = *((PNetPnPEventReserved *) NetPnPEvent->TransportReserved);
  3207. ProtocolBindingContext = Reserved->ProtocolBindingContext;
  3208. Adapter = (PADAPTER)ProtocolBindingContext;
  3209. //
  3210. // Map protocol binding context to devicename
  3211. //
  3212. DeviceName.Buffer = Device->DeviceName;
  3213. DeviceName.Length = (USHORT) Device->DeviceNameLength - sizeof(WCHAR);
  3214. DeviceName.MaximumLength = (USHORT) Device->DeviceNameLength;
  3215. #ifdef _AUTO_RECONFIG_
  3216. //
  3217. // If the Event is NetEventAutoReconfig, then we call IpxNcpaChanges that
  3218. // does all the dirty work.
  3219. //
  3220. if (NetPnPEvent->NetEvent == NetEventReconfigure) {
  3221. //
  3222. // If it is Reconfigure event, just ask ndis to
  3223. // unbind/bind the the protocol
  3224. //
  3225. NDIS_STATUS ReconfigStatus = NDIS_STATUS_NOT_ACCEPTED ;
  3226. if ((ProtocolBindingContext == NULL)) {
  3227. if (TRUE == IpxNcpaChanges(NetPnPEvent)) {
  3228. IPX_DEBUG(PNP, ("IpxNcpaChanges : SUCCESS. \n"));
  3229. ReconfigStatus = STATUS_SUCCESS;
  3230. } else {
  3231. IPX_DEBUG(PNP, ("IpxNcpaChanges : FAILED!! \n"));
  3232. ReconfigStatus = STATUS_UNSUCCESSFUL;
  3233. }
  3234. }
  3235. //
  3236. // Need to unbind and bind the adapte.
  3237. //
  3238. NdisCompletePnPEvent(
  3239. ReconfigStatus,
  3240. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3241. NetPnPEvent
  3242. );
  3243. CTEFreeMem(Reserved);
  3244. return;
  3245. }
  3246. #endif _AUTO_RECONFIG_
  3247. //
  3248. // Map NDIS opcode to IPX's private OpCode for its clients.
  3249. //
  3250. IPX_DEBUG(PNP,("IPX: PNP_EVENT: %x\n", NetPnPEvent->NetEvent));
  3251. switch (NetPnPEvent->NetEvent) {
  3252. case NetEventQueryRemoveDevice:
  3253. Reserved->OpCode = IPX_PNP_QUERY_REMOVE;
  3254. break;
  3255. case NetEventCancelRemoveDevice:
  3256. Reserved->OpCode = IPX_PNP_CANCEL_REMOVE;
  3257. break;
  3258. case NetEventQueryPower:
  3259. Reserved->OpCode = IPX_PNP_QUERY_POWER;
  3260. break;
  3261. case NetEventSetPower:
  3262. Reserved->OpCode = IPX_PNP_SET_POWER;
  3263. break;
  3264. case NetEventBindsComplete:
  3265. {
  3266. BOOLEAN Ready = FALSE;
  3267. //
  3268. // That's it - no more Init time adapters are
  3269. // going to get bound to IPX.
  3270. //
  3271. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  3272. Device->NoMoreInitAdapters = TRUE;
  3273. if (0 == --Device->InitTimeAdapters) {
  3274. Ready = TRUE;
  3275. }
  3276. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  3277. if (Ready) {
  3278. NTSTATUS ntstatus;
  3279. IPX_DEBUG(PNP, ("IPX : Calling Provider Ready\n"));
  3280. ntstatus = TdiProviderReady(Device->TdiProviderReadyHandle);
  3281. //
  3282. // TdiProviderReady is guaranteed to be synch with nothing apart from success.
  3283. //
  3284. NdisCompletePnPEvent(
  3285. ntstatus,
  3286. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3287. NetPnPEvent
  3288. );
  3289. IPX_DEBUG(PNP, ("NdisComplete called with %x\n", ntstatus));
  3290. CTEFreeMem(Reserved);
  3291. return;
  3292. } else {
  3293. CTEAssert(NULL == Device->NetPnPEvent);
  3294. Device->NetPnPEvent = NetPnPEvent;
  3295. IPX_DEBUG(PNP, ("The count is %d - someone else is going to call Ndis' completion \n", Device->InitTimeAdapters));
  3296. }
  3297. return;
  3298. }
  3299. break;
  3300. default:
  3301. IPX_DEBUG(PNP,("IPX: IpxDoPnPEvent: Unhandled NETPNP_CODE!! - %x\n", NetPnPEvent->NetEvent));
  3302. NdisCompletePnPEvent(
  3303. STATUS_SUCCESS,
  3304. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3305. NetPnPEvent
  3306. );
  3307. CTEFreeMem(Reserved);
  3308. return;
  3309. }
  3310. CTEAssert(ProtocolBindingContext != NULL);
  3311. //
  3312. // We are passing in the PDO's name too
  3313. //
  3314. RtlInitUnicodeString(&PDO_Name, ((PADAPTER)ProtocolBindingContext)->AdapterName);
  3315. //
  3316. // IPX exports one device, so this is all we have to do.
  3317. //
  3318. Context1 = IpxAllocateMemory(
  3319. sizeof(TDI_PNP_CONTEXT) + sizeof (UNICODE_STRING) + PDO_Name.MaximumLength,
  3320. MEMORY_ADAPTER,
  3321. "Adapter Name"
  3322. );
  3323. if (NULL != Context1) {
  3324. Context2 = IpxAllocateMemory(
  3325. sizeof(TDI_PNP_CONTEXT),
  3326. MEMORY_ADAPTER,
  3327. "Last Adapter"
  3328. );
  3329. if (NULL != Context2) {
  3330. //
  3331. // We've gotten the resources and are now making the call
  3332. // to tdi for sure.
  3333. //
  3334. Context1->ContextType = TDI_PNP_CONTEXT_TYPE_IF_NAME;
  3335. Context1->ContextSize = sizeof(UNICODE_STRING) + PDO_Name.MaximumLength;
  3336. TempStr = (PUNICODE_STRING) Context1->ContextData;
  3337. TempStr->Length = 0;
  3338. TempStr->MaximumLength = PDO_Name.MaximumLength;
  3339. TempStr->Buffer = (PWCHAR) ((PUCHAR) Context1->ContextData) + 2 * sizeof(USHORT);
  3340. RtlCopyUnicodeString(TempStr, &PDO_Name);
  3341. Context2->ContextType = TDI_PNP_CONTEXT_TYPE_FIRST_OR_LAST_IF;
  3342. Context2->ContextSize = sizeof(UCHAR);
  3343. // Check if first or last device
  3344. if (Device->ValidBindings == 1) {
  3345. Context2->ContextData[1] = TRUE;
  3346. } else {
  3347. Context2->ContextData[1] = FALSE;
  3348. }
  3349. Reserved->Context1 = Context1;
  3350. Reserved->Context2 = Context2;
  3351. IPX_DEBUG(PNP, ("Calling Tdipnppowerrequest: Context1:%lx, Context2:%lx, Adapter:%lx\n",
  3352. Context1,
  3353. Context2,
  3354. Reserved->ProtocolBindingContext));
  3355. } else {
  3356. IpxFreeMemory (
  3357. Context1,
  3358. sizeof(TDI_PNP_CONTEXT) + sizeof (UNICODE_STRING) + PDO_Name.MaximumLength,
  3359. MEMORY_ADAPTER,
  3360. "Adapter Name"
  3361. );
  3362. NdisCompletePnPEvent(
  3363. STATUS_INSUFFICIENT_RESOURCES,
  3364. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3365. NetPnPEvent
  3366. );
  3367. CTEFreeMem(Reserved);
  3368. return ;
  3369. }
  3370. } else {
  3371. NdisCompletePnPEvent(
  3372. STATUS_INSUFFICIENT_RESOURCES,
  3373. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3374. NetPnPEvent
  3375. );
  3376. CTEFreeMem(Reserved);
  3377. return;
  3378. }
  3379. //
  3380. // First we call the three Upper Drivers bound to IPX: RIP, SPX and NB.
  3381. // The private interface with SPX, RIP and NB is synchronous.
  3382. // Then we call TDI.
  3383. //
  3384. // Nota Bene: RIP doesnt have a PNP Handler
  3385. if ((Device->UpperDriverBound[IDENTIFIER_SPX]) && (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler)) {
  3386. IPX_DEBUG(PNP,("Calling PnPEventHandler of SPX\n"));
  3387. Reserved->Status[0] = (*Device->UpperDrivers[IDENTIFIER_SPX].PnPHandler) (
  3388. Reserved->OpCode,
  3389. NetPnPEvent
  3390. );
  3391. } else {
  3392. Reserved->Status[0] = STATUS_SUCCESS;
  3393. }
  3394. if (STATUS_PENDING != Reserved->Status[0]) {
  3395. IpxPnPCompletionHandler(NetPnPEvent,
  3396. Reserved->Status[0]
  3397. );
  3398. } else {
  3399. IPX_DEBUG(PNP,("SPX PnPHandler returned STATUS_PENDING on event %p.\n", NetPnPEvent));
  3400. }
  3401. }
  3402. VOID
  3403. IpxPnPCompletionHandler(
  3404. IN PNET_PNP_EVENT NetPnPEvent,
  3405. IN NTSTATUS Status
  3406. )
  3407. {
  3408. PNetPnPEventReserved Reserved;
  3409. PDEVICE Device = IpxDevice;
  3410. INT i;
  3411. PADAPTER Adapter;
  3412. //
  3413. // Get the ProtocolBindingContext out
  3414. //
  3415. ASSERT(Status != STATUS_PENDING);
  3416. Reserved = *((PNetPnPEventReserved *) NetPnPEvent->TransportReserved);
  3417. IPX_DEBUG(PNP, ("PNP Completion Handler: State: %d Context1:%lx, Context2:%lx, Adapter:%lx\n",
  3418. Reserved->State,
  3419. Reserved->Context1,
  3420. Reserved->Context2,
  3421. Reserved->ProtocolBindingContext));
  3422. Adapter = (PADAPTER)Reserved->ProtocolBindingContext;
  3423. switch (Reserved->State) {
  3424. case NONE_DONE:
  3425. IPX_DEBUG(PNP, ("SPX is Complete\n"));
  3426. Reserved->Status[0] = Status;
  3427. Reserved->State = SPX_DONE;
  3428. IPX_DEBUG(PNP, ("PNP Completion Handler: State: %d Context1:%lx, Context2:%lx, Adapter:%lx\n",
  3429. Reserved->State,
  3430. Reserved->Context1,
  3431. Reserved->Context2,
  3432. Reserved->ProtocolBindingContext));
  3433. if ((Device->UpperDriverBound[IDENTIFIER_NB]) && (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler)) {
  3434. IPX_DEBUG(PNP,("Calling PnPEventHandler of NB\n"));
  3435. Reserved->Status[1] = (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  3436. Reserved->OpCode,
  3437. NetPnPEvent
  3438. );
  3439. if (Reserved->Status[1] == STATUS_PENDING) {
  3440. break;
  3441. } else {
  3442. Reserved->State = NB_DONE;
  3443. }
  3444. } else {
  3445. IPX_DEBUG(PNP, ("NB's handlers arent around, we jump to the next call \n"));
  3446. Reserved->Status[1] = STATUS_SUCCESS;
  3447. Reserved->State = NB_DONE;
  3448. }
  3449. // fall through
  3450. case SPX_DONE:
  3451. IPX_DEBUG(PNP,("NB is Complete\n"));
  3452. if (Reserved->State == SPX_DONE) {
  3453. // Previous NbiPnPNotification returned pending, we are here because
  3454. // Tdi is calling this completion routine.
  3455. Reserved->Status[1] = Status;
  3456. Reserved->State = NB_DONE;
  3457. }
  3458. ASSERT(Reserved->State == NB_DONE);
  3459. IPX_DEBUG(PNP,("Calling Tdipnppowerrequest: Context1:%lx, Context2:%lx, Adapter:%lx\n",
  3460. Reserved->Context1,
  3461. Reserved->Context2,
  3462. Reserved->ProtocolBindingContext));
  3463. #ifdef DBG
  3464. if (Reserved->Status[0] == STATUS_PENDING) {
  3465. DbgPrint("!!!!! Before calling TdiPnPPowerRequest: Reserved->Status[0] = STATUS_PENDING\n");
  3466. }
  3467. #endif
  3468. Reserved->Status[2] = TdiPnPPowerRequest(
  3469. &IpxDeviceName,
  3470. NetPnPEvent,
  3471. Reserved->Context1,
  3472. Reserved->Context2,
  3473. IpxPnPCompletionHandler
  3474. );
  3475. IPX_DEBUG(PNP,("Status[2] = %lx\n", Reserved->Status[2]));
  3476. if (STATUS_PENDING == Reserved->Status[2]) {
  3477. break;
  3478. } else {
  3479. IPX_DEBUG(PNP,("TDI did not return pending, so we are done\n"));
  3480. Reserved->State = ALL_DONE;
  3481. }
  3482. // fall through
  3483. case NB_DONE:
  3484. IPX_DEBUG(PNP,("NB is Done\n"));
  3485. if (Reserved->State == NB_DONE) {
  3486. Reserved->Status[2] = Status;
  3487. Reserved->State = ALL_DONE;
  3488. }
  3489. ASSERT(Reserved->State == ALL_DONE);
  3490. IPX_DEBUG(PNP,("PNP Completion Handler: State: %d Context1:%lx, Context2:%lx, Adapter:%lx\n",
  3491. Reserved->State,
  3492. Reserved->Context1,
  3493. Reserved->Context2,
  3494. Reserved->ProtocolBindingContext));
  3495. IpxFreeMemory (
  3496. Reserved->Context1,
  3497. sizeof(TDI_PNP_CONTEXT) + Reserved->Context1->ContextSize,
  3498. MEMORY_ADAPTER,
  3499. "Adapter Name"
  3500. );
  3501. IpxFreeMemory (
  3502. Reserved->Context2,
  3503. sizeof(TDI_PNP_CONTEXT),
  3504. MEMORY_ADAPTER,
  3505. "Last Adapter"
  3506. );
  3507. for (i = 0; i < 3; i++) {
  3508. if (STATUS_SUCCESS != Reserved->Status[i]) {
  3509. ASSERT(Reserved->Status[i] != STATUS_PENDING);
  3510. NdisCompletePnPEvent(
  3511. Reserved->Status[i],
  3512. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3513. NetPnPEvent
  3514. );
  3515. CTEFreeMem(Reserved);
  3516. return;
  3517. }
  3518. }
  3519. NdisCompletePnPEvent(
  3520. STATUS_SUCCESS,
  3521. (Adapter != NULL) ? Adapter->NdisBindingHandle : NULL,
  3522. NetPnPEvent
  3523. );
  3524. CTEFreeMem(Reserved);
  3525. return;
  3526. default:
  3527. //CTEAssert(FALSE);
  3528. break;
  3529. }
  3530. }
  3531. #ifdef _AUTO_RECONFIG_
  3532. //
  3533. // When IPX gets a AUTO_RECONFIG structure from NCPA (via NDIS), it
  3534. // checks if there are any changes. If there are changes, it does the
  3535. // BindAdapter shenanigan.
  3536. //
  3537. // Input: the PVOID in the NET_PNP structure
  3538. // if the protocolbindingcontext is NULL, it is global reconfig.
  3539. // Output: BOOLEAN; if the auto_reconfig was a success/failure
  3540. //
  3541. BOOLEAN
  3542. IpxNcpaChanges(
  3543. PNET_PNP_EVENT NetPnPEvent
  3544. )
  3545. {
  3546. PDEVICE Device = IpxDevice;
  3547. PRECONFIG ReconfigBuffer;
  3548. UINT ReConfigBufferLength;
  3549. BOOLEAN ReBindAdapter;
  3550. NDIS_HANDLE ProtocolBindingContext;
  3551. PNetPnPEventReserved Reserved;
  3552. PADAPTER Adapter;
  3553. NTSTATUS NtStatus;
  3554. CONFIG Config;
  3555. PBINDING Binding;
  3556. BINDING_CONFIG ConfigBinding;
  3557. INT i;
  3558. PLIST_ENTRY p = NULL;
  3559. PREQUEST Request = NULL;
  3560. void * PNPContext;
  3561. IPX_DEFINE_LOCK_HANDLE (OldIrq)
  3562. CTEAssert(NetPnPEvent != NULL);
  3563. //
  3564. // Get the ProtocolBindingContext out
  3565. //
  3566. Reserved = *((PNetPnPEventReserved *) NetPnPEvent->TransportReserved);
  3567. ProtocolBindingContext = Reserved->ProtocolBindingContext;
  3568. Adapter = (PADAPTER) ProtocolBindingContext;
  3569. //
  3570. // Get the Buffer out
  3571. //
  3572. Device = IpxDevice;
  3573. ReconfigBuffer = (RECONFIG *) NetPnPEvent->Buffer;
  3574. ReConfigBufferLength = NetPnPEvent->BufferLength;
  3575. //
  3576. // Bug 96509, NCPA might give us NULL reconfig buffers (NOPs)
  3577. //
  3578. if ((ReConfigBufferLength == 0) || (NULL == ReconfigBuffer)) {
  3579. IPX_DEBUG(PNP, ("The Reconfig Buffer is NULL!\n"));
  3580. return TRUE;
  3581. }
  3582. //
  3583. // We know where to lookup the parameters.
  3584. //
  3585. Config.DriverObject = (PDRIVER_OBJECT)Device->DeviceObject;
  3586. Config.RegistryPathBuffer = Device->RegistryPathBuffer;
  3587. //
  3588. // Could be global reconfig.
  3589. // For IPX, this means that our Internal Network Number has changed.
  3590. //
  3591. if (NULL == ProtocolBindingContext) {
  3592. if (ReconfigBuffer->VirtualNetworkNumber) {
  3593. //
  3594. // Read the registry to see if a virtual network number ap
  3595. //
  3596. NtStatus = IpxPnPGetVirtualNetworkNumber(&Config);
  3597. if (Config.Parameters[CONFIG_VIRTUAL_NETWORK] == REORDER_ULONG(Device->VirtualNetworkNumber)) {
  3598. IPX_DEBUG(PNP, ("The Net Number is the same!!\n"));
  3599. } else { // The net number has changed. do something special if it is zero ?
  3600. IPX_DEBUG(PNP, ("The Net Numbers are different: %x <-> %x\n", Config.Parameters[CONFIG_VIRTUAL_NETWORK], REORDER_ULONG(Device->VirtualNetworkNumber) ));
  3601. Device->VirtualNetworkNumber = REORDER_ULONG(Config.Parameters[CONFIG_VIRTUAL_NETWORK]);
  3602. if (IpxNewVirtualNetwork(Device, TRUE)) {
  3603. IPX_DEBUG(PNP, ("SPX has been informed about the change in Network Number\n"));
  3604. } else {
  3605. IPX_DEBUG(PNP, ("SPX has NOT been informed about the change in Network Number\n"));
  3606. }
  3607. IPX_DEBUG(PNP, ("Telling RTR Manager that the internal net number has changed.\n"));
  3608. if (Device->ForwarderBound && ((p = ExInterlockedRemoveHeadList(
  3609. &Device->NicNtfQueue,
  3610. &Device->Lock)) != NULL))
  3611. {
  3612. PNWLINK_ACTION NwlinkAction = NULL;
  3613. PIPX_NICS pNics = NULL;
  3614. ULONG BufferLength = 0;
  3615. Request = LIST_ENTRY_TO_REQUEST(p);
  3616. IPX_DEBUG(PNP,("Ipxpnphandler: Netnum has changed\n"));
  3617. //
  3618. // Get the Buffer out.
  3619. //
  3620. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&NwlinkAction, &BufferLength, HighPagePriority);
  3621. if (NULL == NwlinkAction) {
  3622. DbgPrint("The IRP has a NULL buffer\n");
  3623. return FALSE;
  3624. }
  3625. pNics = (PIPX_NICS)(NwlinkAction->Data);
  3626. //
  3627. // 0, 0 means that Internal network number has changed.
  3628. //
  3629. pNics->NoOfNics = 0;
  3630. pNics->TotalNoOfNics = 0;
  3631. IoAcquireCancelSpinLock(&OldIrq);
  3632. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  3633. IoReleaseCancelSpinLock(OldIrq);
  3634. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  3635. IpxCompleteRequest (Request);
  3636. IpxFreeRequest (Device, Request);
  3637. IpxDereferenceDevice (Device, DREF_NIC_NOTIFY);
  3638. IPX_DEBUG(PNP,("GetNewNics returned SUCCESS (RTR Manager has been informed\n"));
  3639. } else {
  3640. IPX_DEBUG(PNP,("No IRPs pending - couldnt tell the forwarder about the change in NetNum\n"));
  3641. //DbgBreakPoint();
  3642. }
  3643. }
  3644. return TRUE;
  3645. } else {
  3646. KdPrint(("NULL ADAPTER context AND Not a Virtual Network number!!\n"));
  3647. return FALSE;
  3648. }
  3649. }
  3650. //
  3651. // Otherwise, It is for an adapter.
  3652. //
  3653. ASSERT(Adapter != NULL);
  3654. //
  3655. // Used for error logging
  3656. //
  3657. ConfigBinding.AdapterName.Buffer = IpxAllocateMemory(
  3658. Adapter->AdapterNameLength+1,
  3659. MEMORY_ADAPTER,
  3660. "Adapter Name"
  3661. );
  3662. ConfigBinding.AdapterName.Length = 0;
  3663. if (ConfigBinding.AdapterName.Buffer == NULL) {
  3664. DbgPrint("IPX:IpxNcpaChanges:Failed to allocate buffer for adapter name.\n");
  3665. ConfigBinding.AdapterName.MaximumLength = 0;
  3666. return FALSE;
  3667. } else {
  3668. ConfigBinding.AdapterName.MaximumLength = (USHORT) Adapter->AdapterNameLength+1;
  3669. RtlAppendUnicodeToString(&ConfigBinding.AdapterName, Adapter->AdapterName);
  3670. }
  3671. // NetCfg should not trigger a reconfigure event if no properties have changed.
  3672. // Do we really need to do a Bindadapter again?
  3673. // Maybe we can get away with something smaller/
  3674. //
  3675. PNPContext = Adapter->PNPContext;
  3676. IpxUnbindAdapter(&NtStatus,
  3677. Adapter,
  3678. NULL
  3679. );
  3680. if (NtStatus != STATUS_SUCCESS) {
  3681. IPX_DEBUG(PNP, ("IpxUnbindAdapter return error!! %x\n", NtStatus));
  3682. IpxFreeMemory (
  3683. ConfigBinding.AdapterName.Buffer,
  3684. ConfigBinding.AdapterName.MaximumLength,
  3685. MEMORY_ADAPTER,
  3686. "Adapter Name"
  3687. );
  3688. return FALSE;
  3689. } else {
  3690. IpxBindAdapter(
  3691. &NtStatus,
  3692. NULL,
  3693. &ConfigBinding.AdapterName,
  3694. NULL,
  3695. PNPContext
  3696. );
  3697. IpxFreeMemory (
  3698. ConfigBinding.AdapterName.Buffer,
  3699. ConfigBinding.AdapterName.MaximumLength,
  3700. MEMORY_ADAPTER,
  3701. "Adapter Name"
  3702. );
  3703. if (NtStatus != STATUS_SUCCESS) {
  3704. IPX_DEBUG(PNP, ("IpxBindAdapter return error!! %x\n", NtStatus));
  3705. return FALSE;
  3706. } else {
  3707. IPX_DEBUG(PNP, ("Unbind/Bind SUCCESS. NCPA changes made!!\n"));
  3708. return TRUE;
  3709. }
  3710. }
  3711. }
  3712. #endif // _AUTO_RECONFIG_
  3713. #endif // _PNP_POWER_
  3714. #if TRACK
  3715. KSPIN_LOCK ALock = 0;
  3716. #define MAX_PTR_COUNT 2048
  3717. struct _MemPtr
  3718. {
  3719. PVOID Ptr;
  3720. ULONG Size;
  3721. ULONG ModLine;
  3722. ULONG Tag;
  3723. } IpxMemPtrs[MAX_PTR_COUNT] = { 0 };
  3724. PVOID
  3725. IpxAllocateMemoryTrack(
  3726. IN ULONG Size,
  3727. IN ULONG Tag,
  3728. IN ULONG ModLine
  3729. )
  3730. {
  3731. PVOID p;
  3732. p = ExAllocatePoolWithTag(NonPagedPool, Size, Tag);
  3733. if (p != NULL)
  3734. {
  3735. KIRQL OldIrql;
  3736. UINT i;
  3737. KeAcquireSpinLock(&ALock, &OldIrql);
  3738. for (i = 0; i < MAX_PTR_COUNT; i++)
  3739. {
  3740. if (IpxMemPtrs[i].Ptr == NULL)
  3741. {
  3742. IpxMemPtrs[i].Ptr = p;
  3743. IpxMemPtrs[i].Size = Size;
  3744. IpxMemPtrs[i].ModLine = ModLine;
  3745. IpxMemPtrs[i].Tag = Tag;
  3746. break;
  3747. }
  3748. }
  3749. KeReleaseSpinLock(&ALock, OldIrql);
  3750. }
  3751. return(p);
  3752. }
  3753. VOID
  3754. IpxFreeMemoryTrack(
  3755. IN PVOID Memory
  3756. )
  3757. {
  3758. KIRQL OldIrql;
  3759. UINT i;
  3760. KeAcquireSpinLock(&ALock, &OldIrql);
  3761. for (i = 0; i < MAX_PTR_COUNT; i++)
  3762. {
  3763. if (IpxMemPtrs[i].Ptr == Memory)
  3764. {
  3765. IpxMemPtrs[i].Ptr = NULL;
  3766. IpxMemPtrs[i].Size = 0;
  3767. IpxMemPtrs[i].ModLine = 0;
  3768. IpxMemPtrs[i].Tag = 0;
  3769. }
  3770. }
  3771. KeReleaseSpinLock(&ALock, OldIrql);
  3772. ExFreePool(Memory);
  3773. }
  3774. #endif TRACK