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.

1454 lines
41 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. internal.c
  5. Abstract:
  6. This module contains the code to handle the internal
  7. binding of the upper drivers to IPX.
  8. Author:
  9. Adam Barr (adamba) 2-September-1993
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Sanjay Anand (SanjayAn) 25-August-1995
  14. Bug Fixes - tagged [SA]
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. NTSTATUS
  19. IpxInternalBind(
  20. IN PDEVICE Device,
  21. IN PIRP Irp
  22. )
  23. /*++
  24. Routine Description:
  25. This routine is used when one of the upper drivers submits
  26. a request to bind to IPX.
  27. Arguments:
  28. DeviceObject - Pointer to the device object for this driver.
  29. Irp - Pointer to the request packet representing the I/O request.
  30. Return Value:
  31. The function value is the status of the operation.
  32. --*/
  33. {
  34. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp);
  35. PIPX_INTERNAL_BIND_INPUT BindInput;
  36. PIPX_INTERNAL_BIND_OUTPUT BindOutput;
  37. PIPX_INTERNAL_BIND_RIP_OUTPUT BindRipOutput;
  38. CTELockHandle LockHandle;
  39. PIPX_NIC_DATA NicData;
  40. PBINDING Binding, LastRealBinding;
  41. PADAPTER Adapter;
  42. ULONG Identifier;
  43. ULONG BindOutputSize;
  44. BOOLEAN BroadcastEnable;
  45. #ifdef SUNDOWN
  46. // To avoid a warning when NicData->NicId = i;
  47. // Assume that USHORT is enough to hold the number of bindings
  48. USHORT i;
  49. #else
  50. UINT i;
  51. #endif
  52. #if DBG
  53. PUCHAR IdStrings[] = { "NB", "SPX", "RIP" };
  54. #endif
  55. BOOLEAN fFwdBindAttempt = FALSE;
  56. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  57. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  58. (sizeof(IPX_INTERNAL_BIND_INPUT) - sizeof(ULONG))) {
  59. IPX_DEBUG (BIND, ("Bind received, bad input length %d/%d\n",
  60. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  61. sizeof (IPX_INTERNAL_BIND_INPUT)));
  62. return STATUS_INVALID_PARAMETER;
  63. }
  64. BindInput = (PIPX_INTERNAL_BIND_INPUT)(Irp->AssociatedIrp.SystemBuffer);
  65. if (BindInput->Identifier >= UPPER_DRIVER_COUNT) {
  66. IPX_DEBUG (BIND, ("Bind received, bad id %d\n", BindInput->Identifier));
  67. return STATUS_INVALID_PARAMETER;
  68. }
  69. IPX_DEBUG (BIND, ("Bind received from id %d (%s)\n",
  70. BindInput->Identifier,
  71. IdStrings[BindInput->Identifier]));
  72. //
  73. // RIP gives us version == 1 whereas Forwarder gives us 2 (ISN_VERSION).
  74. //
  75. if (BindInput->Identifier == IDENTIFIER_RIP) {
  76. if (BindInput->Version == ISN_VERSION) {
  77. fFwdBindAttempt = TRUE;
  78. } else {
  79. CTEAssert(!Device->ForwarderBound);
  80. DbgPrint("IPX:Check out who is requesting bind?.\n");
  81. CTEAssert(FALSE);
  82. if (BindInput->Version != 1) {
  83. IPX_DEBUG (BIND, ("Bind: bad version %d/%d\n",
  84. BindInput->Version, 1));
  85. return STATUS_INVALID_PARAMETER;
  86. }
  87. }
  88. } else {
  89. if (BindInput->Version != ISN_VERSION) {
  90. IPX_DEBUG (BIND, ("Bind: bad version %d/%d\n",
  91. BindInput->Version, 1));
  92. return STATUS_INVALID_PARAMETER;
  93. }
  94. }
  95. if (BindInput->Identifier != IDENTIFIER_RIP) {
  96. BindOutputSize = sizeof(IPX_INTERNAL_BIND_OUTPUT);
  97. } else {
  98. BindOutputSize = FIELD_OFFSET (IPX_INTERNAL_BIND_RIP_OUTPUT, NicInfoBuffer.NicData[0]) +
  99. (MIN (Device->MaxBindings, Device->HighestExternalNicId) * sizeof(IPX_NIC_DATA));
  100. }
  101. Irp->IoStatus.Information = BindOutputSize;
  102. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  103. BindOutputSize) {
  104. IPX_DEBUG (BIND, ("Bind: bad output length %d/%d\n",
  105. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  106. BindOutputSize));
  107. //
  108. // Fail this request with BUFFER_TOO_SMALL. Since the
  109. // I/O system may not copy the status block back to
  110. // the user's status block, do that here so that
  111. // he gets IoStatus.Information.
  112. //
  113. try {
  114. *Irp->UserIosb = Irp->IoStatus;
  115. } except(EXCEPTION_EXECUTE_HANDLER) {
  116. NOTHING;
  117. }
  118. return STATUS_BUFFER_TOO_SMALL;
  119. }
  120. //
  121. // We have verified the length, make sure we are not
  122. // already bound.
  123. //
  124. Identifier = BindInput->Identifier;
  125. CTEGetLock (&Device->Lock, &LockHandle);
  126. if (Device->UpperDriverBound[Identifier]) {
  127. IPX_DEBUG (BIND, ("Bind: already bound\n"));
  128. CTEFreeLock (&Device->Lock, LockHandle);
  129. return STATUS_REQUEST_NOT_ACCEPTED;
  130. }
  131. {
  132. LARGE_INTEGER ControlChId;
  133. CCID_FROM_REQUEST(ControlChId, Irp);
  134. IPX_DEBUG (BIND, ("Control ChId: (%d, %d) for Id: %d\n", ControlChId.HighPart, ControlChId.LowPart, Identifier));
  135. Device->UpperDriverControlChannel[Identifier].QuadPart = ControlChId.QuadPart;
  136. }
  137. RtlCopyMemory(
  138. &Device->UpperDrivers[Identifier],
  139. BindInput,
  140. sizeof (IPX_INTERNAL_BIND_INPUT)
  141. );
  142. BroadcastEnable = BindInput->BroadcastEnable;
  143. //
  144. // Now construct the output buffer.
  145. //
  146. if (Identifier != IDENTIFIER_RIP) {
  147. BindOutput = (PIPX_INTERNAL_BIND_OUTPUT)Irp->AssociatedIrp.SystemBuffer;
  148. RtlZeroMemory(BindOutput, sizeof(IPX_INTERNAL_BIND_OUTPUT));
  149. BindOutput->Version = 1;
  150. //
  151. // Tell netbios our first binding's net/node instead of the
  152. // virtual one.
  153. //
  154. //
  155. // Fill the fields in only if the adapters have already appeared
  156. // Else, set NodeNumber to 0 so NB/SPX know of it.
  157. //
  158. if ((*(UNALIGNED USHORT *)(Device->SourceAddress.NodeAddress+4) != 0) ||
  159. (*(UNALIGNED ULONG *)Device->SourceAddress.NodeAddress != 0)) {
  160. IPX_DEBUG(BIND, ("Device already opened\n"));
  161. CTEAssert(Device->ValidBindings);
  162. if (Identifier == IDENTIFIER_SPX) {
  163. //
  164. // For SPX, inform directly.
  165. //
  166. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  167. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  168. if (!NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier]) {
  169. NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier] = TRUE;
  170. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  171. ExInitializeWorkItem(
  172. &Device->PnPIndicationsQueueItemSpx,
  173. IpxPnPIsnIndicate,
  174. UlongToPtr(Identifier));
  175. IpxReferenceDevice(Device, DREF_PNP);
  176. ExQueueWorkItem(&Device->PnPIndicationsQueueItemSpx, DelayedWorkQueue);
  177. // DbgPrint("---------- 5. Queued with IpxPnPIsnIndicate ----------\n");
  178. //IpxPnPIsnIndicate((PVOID)Identifier);
  179. } else {
  180. CTEAssert(FALSE);
  181. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  182. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  183. }
  184. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  185. } else {
  186. //
  187. // For NB, queue a work item which will go thru' the adapters list and
  188. // inform the upper drivers about each of them.
  189. //
  190. KeResetEvent(&Device->NbEvent);
  191. ExInitializeWorkItem(
  192. &Device->PnPIndicationsQueueItemNb,
  193. IpxPnPIsnIndicate,
  194. UlongToPtr(Identifier));
  195. IpxReferenceDevice(Device, DREF_PNP);
  196. ExQueueWorkItem(&Device->PnPIndicationsQueueItemNb, DelayedWorkQueue);
  197. // DbgPrint("---------- 5 (2). Queued with IpxPnPIsnIndicate ----------\n");
  198. }
  199. } else {
  200. // This should not happen as SourceAddress should set in DriverEntry
  201. // to initial loopback address or virtual network address.
  202. DbgPrint("IPX:IpxInternalBind:Device not open:IpxPnPIsnIndicate thread did not launch.\n");
  203. *((UNALIGNED ULONG *)BindOutput->Node) = 0;
  204. *((UNALIGNED USHORT *)(BindOutput->Node+4)) = 0;
  205. RtlZeroMemory(&BindOutput->LineInfo, sizeof(BindOutput->LineInfo));
  206. }
  207. BindOutput->MacHeaderNeeded = MAC_HEADER_SIZE; //40;
  208. BindOutput->IncludedHeaderOffset = MAC_HEADER_SIZE; // (USHORT)Device->IncludedHeaderOffset;
  209. BindOutput->SendHandler = IpxSendFramePreFwd;
  210. BindOutput->FindRouteHandler = IpxInternalFindRoute;
  211. BindOutput->QueryHandler = IpxInternalQuery;
  212. BindOutput->TransferDataHandler = IpxTransferData;
  213. BindOutput->PnPCompleteHandler = IpxPnPCompletionHandler;
  214. } else {
  215. //
  216. // Set this so we stop RIPping for our virtual network (if
  217. // we have one).
  218. //
  219. Device->RipResponder = FALSE;
  220. //
  221. // See if he wants a single wan network number.
  222. //
  223. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  224. sizeof(IPX_INTERNAL_BIND_INPUT)) ||
  225. ((BindInput->RipParameters & IPX_RIP_PARAM_GLOBAL_NETWORK) == 0)) {
  226. Device->WanGlobalNetworkNumber = FALSE;
  227. Device->SapNicCount = Device->HighestExternalNicId;
  228. } else {
  229. Device->WanGlobalNetworkNumber = TRUE;
  230. }
  231. BindRipOutput = (PIPX_INTERNAL_BIND_RIP_OUTPUT)Irp->AssociatedIrp.SystemBuffer;
  232. RtlZeroMemory(BindRipOutput, sizeof(IPX_INTERNAL_BIND_RIP_OUTPUT));
  233. BindRipOutput->Version = 1;
  234. BindRipOutput->MaximumNicCount = MIN (Device->MaxBindings, Device->HighestExternalNicId) + 1;
  235. BindRipOutput->MacHeaderNeeded = MAC_HEADER_SIZE; //40;
  236. BindRipOutput->IncludedHeaderOffset = (USHORT)Device->IncludedHeaderOffset;
  237. BindRipOutput->SendHandler = IpxSendFrame;
  238. if (!fFwdBindAttempt) {
  239. BindRipOutput->SegmentCount = Device->SegmentCount;
  240. BindRipOutput->SegmentLocks = Device->SegmentLocks;
  241. BindRipOutput->GetSegmentHandler = RipGetSegment;
  242. BindRipOutput->GetRouteHandler = RipGetRoute;
  243. BindRipOutput->AddRouteHandler = RipAddRoute;
  244. BindRipOutput->DeleteRouteHandler = RipDeleteRoute;
  245. BindRipOutput->GetFirstRouteHandler = RipGetFirstRoute;
  246. BindRipOutput->GetNextRouteHandler = RipGetNextRoute;
  247. //
  248. // remove this...
  249. //
  250. BindRipOutput->IncrementWanInactivityHandler = IpxInternalIncrementWanInactivity;
  251. BindRipOutput->QueryWanInactivityHandler = IpxInternalQueryWanInactivity;
  252. } else {
  253. //
  254. // [FW] New routines provided for the Forwarder
  255. //
  256. BindRipOutput->OpenAdapterHandler = IpxOpenAdapter;
  257. BindRipOutput->CloseAdapterHandler = IpxCloseAdapter;
  258. BindRipOutput->InternalSendCompleteHandler = IpxInternalSendComplete;
  259. }
  260. BindRipOutput->TransferDataHandler = IpxTransferData;
  261. BindRipOutput->NicInfoBuffer.NicCount = (USHORT)MIN (Device->MaxBindings, Device->HighestExternalNicId);
  262. BindRipOutput->NicInfoBuffer.VirtualNicId = 0;
  263. if (Device->VirtualNetwork || Device->MultiCardZeroVirtual) {
  264. *(UNALIGNED ULONG *)(BindRipOutput->NicInfoBuffer.VirtualNetwork) = Device->SourceAddress.NetworkAddress;
  265. } else if (Device->DedicatedRouter) {
  266. *(UNALIGNED ULONG *)(BindRipOutput->NicInfoBuffer.VirtualNetwork) = 0x0;
  267. }
  268. NicData = &BindRipOutput->NicInfoBuffer.NicData[0];
  269. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  270. {
  271. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  272. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  273. Binding = NIC_ID_TO_BINDING(Device, i);
  274. //
  275. // NULL bindings are WAN bindings, so we return the
  276. // information from the last non-NULL binding found,
  277. // which will be the first one on this adapter.
  278. // Otherwise we save this as the last non-NULL one.
  279. //
  280. if (Binding == NULL) {
  281. Binding = LastRealBinding;
  282. } else {
  283. LastRealBinding = Binding;
  284. }
  285. Adapter = Binding->Adapter;
  286. NicData->NicId = i;
  287. RtlCopyMemory (NicData->Node, Binding->LocalAddress.NodeAddress, 6);
  288. *(UNALIGNED ULONG *)NicData->Network = Binding->LocalAddress.NetworkAddress;
  289. NicData->LineInfo.LinkSpeed = Binding->MediumSpeed;
  290. NicData->LineInfo.MaximumPacketSize =
  291. Binding->MaxLookaheadData + sizeof(IPX_HEADER);
  292. NicData->LineInfo.MaximumSendSize =
  293. Binding->AnnouncedMaxDatagramSize + sizeof(IPX_HEADER);
  294. NicData->LineInfo.MacOptions = Adapter->MacInfo.MacOptions;
  295. NicData->DeviceType = Adapter->MacInfo.RealMediumType;
  296. NicData->EnableWanRouter = Adapter->EnableWanRouter;
  297. ++NicData;
  298. }
  299. }
  300. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  301. }
  302. //
  303. // This is enabled by default these days!
  304. //
  305. /*
  306. if (BroadcastEnable) {
  307. IpxAddBroadcast (Device);
  308. }
  309. */
  310. Device->UpperDriverBound[Identifier] = TRUE;
  311. Device->ForwarderBound = fFwdBindAttempt;
  312. Device->AnyUpperDriverBound = TRUE;
  313. CTEFreeLock (&Device->Lock, LockHandle);
  314. return STATUS_SUCCESS;
  315. } /* IpxInternalBind */
  316. NTSTATUS
  317. IpxInternalUnbind(
  318. IN PDEVICE Device,
  319. IN UINT Identifier
  320. )
  321. /*++
  322. Routine Description:
  323. This routine is used when one of the upper drivers submits
  324. a request to unbind from IPX. It does this by closing the
  325. control channel on which the bind ioctl was submitted.
  326. Arguments:
  327. DeviceObject - Pointer to the device object for this driver.
  328. Irp - Pointer to the request packet representing the I/O request.
  329. Return Value:
  330. The function value is the status of the operation.
  331. --*/
  332. {
  333. CTELockHandle LockHandle;
  334. #if DBG
  335. PUCHAR IdStrings[] = { "NB", "SPX", "RIP" };
  336. #endif
  337. IPX_DEBUG (BIND, ("Unbind received from id %d (%s)\n",
  338. Identifier,
  339. IdStrings[Identifier]));
  340. CTEGetLock (&Device->Lock, &LockHandle);
  341. if (!Device->UpperDriverBound[Identifier]) {
  342. CTEFreeLock (&Device->Lock, LockHandle);
  343. IPX_DEBUG (BIND, ("No existing binding\n"));
  344. return STATUS_SUCCESS;
  345. }
  346. //
  347. // [FW] If RIP is unbinding, restart the long timer
  348. // Also, set the RipResponder flag if virutal net configured
  349. //
  350. // Deref all bindings that RIP did not close
  351. //
  352. if (Identifier == IDENTIFIER_RIP &&
  353. Device->ForwarderBound) {
  354. UINT i;
  355. Device->ForwarderBound = FALSE;
  356. //
  357. // [FW] Walk the binding list, to deref all bindings not closed by
  358. // the forwarder before it unbound from us.
  359. //
  360. {
  361. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  362. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  363. PBINDING Binding = NIC_ID_TO_BINDING(Device, i);
  364. //
  365. // We need to ensure that they will all be indicated when
  366. // the Router starts up again.
  367. //
  368. if (Binding) {
  369. Binding->fInfoIndicated = FALSE;
  370. }
  371. if (Binding && (Binding->FwdAdapterContext != 0)) {
  372. IpxDereferenceBinding(Binding, BREF_FWDOPEN);
  373. }
  374. }
  375. }
  376. if (Device->VirtualNetwork) {
  377. Device->RipResponder = TRUE;
  378. }
  379. //
  380. // Start the timer which updates the RIP database
  381. // periodically.
  382. //
  383. IpxReferenceDevice (Device, DREF_LONG_TIMER);
  384. CTEStartTimer(
  385. &Device->RipLongTimer,
  386. 10000,
  387. RipLongTimeout,
  388. (PVOID)Device);
  389. }
  390. Device->UpperDriverBound[Identifier] = FALSE;
  391. Device->AnyUpperDriverBound = (BOOLEAN)
  392. (Device->UpperDriverBound[IDENTIFIER_RIP] ||
  393. Device->UpperDriverBound[IDENTIFIER_SPX] ||
  394. Device->UpperDriverBound[IDENTIFIER_NB]);
  395. //
  396. // Lets do it in UnBindadapter anyway - later! [ShreeM]
  397. //
  398. /*
  399. if (Device->UpperDrivers[Identifier].BroadcastEnable) {
  400. IpxRemoveBroadcast (Device);
  401. }
  402. */
  403. if (Device->ValidBindings > 0) {
  404. //
  405. // If SPX went away, reset the IsnIndicate flag in the first binding
  406. //
  407. if (Identifier == IDENTIFIER_SPX) {
  408. CTEAssert(NIC_ID_TO_BINDING(Device, 1));
  409. if (NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier]) {
  410. NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier] = FALSE;
  411. IPX_DEBUG(PNP, ("SPX unbound: IsnInformed turned off\n"));
  412. }
  413. }
  414. //
  415. // If NB went away, reset all the Binding's flags
  416. //
  417. if (Identifier == IDENTIFIER_NB) {
  418. PBINDING Binding;
  419. UINT i;
  420. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  421. // DbgBreakPoint();
  422. for (i = LOOPBACK_NIC_ID; i < Index; i++) {
  423. Binding = NIC_ID_TO_BINDING(Device, i);
  424. if (Binding && Binding->IsnInformed[Identifier]) {
  425. Binding->IsnInformed[Identifier] = FALSE;
  426. IPX_DEBUG(PNP, ("NB unbound: IsnInformed off for NicId: %lx\n", i));
  427. }
  428. }
  429. }
  430. }
  431. //
  432. // Lets NULL out the drivers
  433. //
  434. RtlZeroMemory(
  435. &Device->UpperDrivers[Identifier],
  436. sizeof (IPX_INTERNAL_BIND_INPUT)
  437. );
  438. CTEFreeLock (&Device->Lock, LockHandle);
  439. return STATUS_SUCCESS;
  440. } /* IpxInternalUnbind */
  441. VOID
  442. IpxInternalFindRoute (
  443. IN PIPX_FIND_ROUTE_REQUEST FindRouteRequest
  444. )
  445. /*++
  446. Routine Description:
  447. This routine is the entry point for upper drivers to submit
  448. requests to find a remote network, which is contained in
  449. FindRouteRequest->Network. FindRouteRequest->Identifier must
  450. contain the identifier of the upper driver.
  451. This request is always asynchronous and is completed by
  452. a call to the FindRouteComplete handler of the upper driver.
  453. NOTE: As a currently unspecified extension to this call,
  454. we returns the tick and hop counts as two USHORTs in the
  455. PVOID Reserved2 structure of the request.
  456. Arguments:
  457. FindRouteRequest - Describes the request and contains
  458. storage for IPX to use while processing it.
  459. Return Value:
  460. None.
  461. --*/
  462. {
  463. PDEVICE Device = IpxDevice;
  464. ULONG Segment;
  465. TDI_ADDRESS_IPX TempAddress;
  466. PBINDING Binding, MasterBinding;
  467. NTSTATUS Status;
  468. IPX_DEFINE_SYNC_CONTEXT (SyncContext)
  469. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  470. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  471. //
  472. // [FW] Call the Forwarder's FindRoute if installed
  473. //
  474. if (Device->ForwarderBound) {
  475. // IPX_ROUTE_ENTRY routeEntry;
  476. Status = (*Device->UpperDrivers[IDENTIFIER_RIP].FindRouteHandler) (
  477. FindRouteRequest->Network,
  478. FindRouteRequest->Node,
  479. FindRouteRequest);
  480. if (Status != STATUS_SUCCESS) {
  481. IPX_DEBUG (RIP, ("RouteHandler returned: %lx\n", Status));
  482. } else {
  483. #if DBG
  484. //
  485. // If a demand-dial NIC was returned, we should have a WAN adapter. In PnP we can check this
  486. // by making sure that Device->HighestLanNicId < Device->HighestExternalNicId.
  487. //
  488. if (FindRouteRequest->LocalTarget.NicId == DEMAND_DIAL_ADAPTER_CONTEXT) {
  489. CTEAssert(Device->HighestLanNicId < Device->HighestExternalNicId);
  490. }
  491. #endif
  492. IPX_DEBUG(RIP, ("FindRoute for %02x-%02x-%02x-%02x-%02x-%02x returned %lx",
  493. FindRouteRequest->LocalTarget.MacAddress[0],
  494. FindRouteRequest->LocalTarget.MacAddress[1],
  495. FindRouteRequest->LocalTarget.MacAddress[2],
  496. FindRouteRequest->LocalTarget.MacAddress[3],
  497. FindRouteRequest->LocalTarget.MacAddress[4],
  498. FindRouteRequest->LocalTarget.MacAddress[5],
  499. Status));
  500. }
  501. } else {
  502. //
  503. // First see if we have a route to this network in our
  504. // table.
  505. //
  506. TempAddress.NetworkAddress = *(UNALIGNED ULONG *)(FindRouteRequest->Network);
  507. //
  508. // [SA] Bug #15094 Copy over the Node address so it can be used in WAN cases
  509. //
  510. // RtlZeroMemory (TempAddress.NodeAddress, 6);
  511. *((UNALIGNED ULONG *)TempAddress.NodeAddress) = *((UNALIGNED ULONG *)FindRouteRequest->Node);
  512. *((UNALIGNED USHORT *)(TempAddress.NodeAddress+4)) = *((UNALIGNED USHORT *)(FindRouteRequest->Node+4));
  513. Segment = RipGetSegment(FindRouteRequest->Network);
  514. //
  515. // Since we maintain the order of locks as Bind > Device > RIP table
  516. // Get the lock up-front.
  517. //
  518. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  519. IPX_BEGIN_SYNC (&SyncContext);
  520. IPX_GET_LOCK (&Device->SegmentLocks[Segment], &LockHandle);
  521. //
  522. // This call will return STATUS_PENDING if we need to
  523. // RIP for the packet.
  524. //
  525. CTEAssert ((sizeof(USHORT)*2) <= sizeof(PVOID));
  526. Status = RipGetLocalTarget(
  527. Segment,
  528. &TempAddress,
  529. FindRouteRequest->Type,
  530. &FindRouteRequest->LocalTarget,
  531. (PUSHORT)&FindRouteRequest->Reserved2);
  532. if (Status == STATUS_PENDING) {
  533. //
  534. // A RIP request went out on the network; we queue
  535. // this find route request for completion when the
  536. // RIP response arrives.
  537. //
  538. CTEAssert (FindRouteRequest->Type != IPX_FIND_ROUTE_NO_RIP); // should never pend
  539. InsertTailList(
  540. &Device->Segments[Segment].FindWaitingForRoute,
  541. &FindRouteRequest->Linkage);
  542. }
  543. IPX_FREE_LOCK (&Device->SegmentLocks[Segment], LockHandle);
  544. IPX_END_SYNC (&SyncContext);
  545. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  546. }
  547. if (Status != STATUS_PENDING) {
  548. if (Status == STATUS_SUCCESS && FindRouteRequest->LocalTarget.NicId) {
  549. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  550. Binding = NIC_HANDLE_TO_BINDING(Device, &FindRouteRequest->LocalTarget.NicHandle);
  551. if (Binding == NULL) {
  552. Status = STATUS_NETWORK_UNREACHABLE;
  553. } else {
  554. if (Binding->BindingSetMember) {
  555. //
  556. // It's a binding set member, we round-robin the
  557. // responses across all the cards to distribute
  558. // the traffic.
  559. //
  560. MasterBinding = Binding->MasterBinding;
  561. Binding = MasterBinding->CurrentSendBinding;
  562. MasterBinding->CurrentSendBinding = Binding->NextBinding;
  563. FILL_LOCAL_TARGET(&FindRouteRequest->LocalTarget, Binding->NicId);
  564. }
  565. }
  566. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  567. }
  568. (*Device->UpperDrivers[FindRouteRequest->Identifier].FindRouteCompleteHandler)(
  569. FindRouteRequest,
  570. (BOOLEAN)((Status == STATUS_SUCCESS) ? TRUE : FALSE));
  571. }
  572. } /* IpxInternalFindRoute */
  573. NTSTATUS
  574. IpxInternalQuery(
  575. IN ULONG InternalQueryType,
  576. IN PNIC_HANDLE NicHandle OPTIONAL,
  577. IN OUT PVOID Buffer,
  578. IN ULONG BufferLength,
  579. OUT PULONG BufferLengthNeeded OPTIONAL
  580. )
  581. /*++
  582. Routine Description:
  583. This routine is the entry point for upper drivers to query
  584. information from us.
  585. Arguments:
  586. InternalQueryType - Identifies the type of the query.
  587. NicId - The ID to query, if needed
  588. Buffer - Input or output buffer for the query.
  589. BufferLength - The length of the buffer.
  590. BufferLengthNeeded - If the buffer is too short, this returns
  591. the length needed.
  592. Return Value:
  593. None.
  594. --*/
  595. {
  596. PBINDING Binding;
  597. BOOLEAN BindingNeeded;
  598. ULONG LengthNeeded;
  599. PIPX_LINE_INFO LineInfo;
  600. PUSHORT MaximumNicId;
  601. PULONG ReceiveBufferSpace;
  602. TDI_ADDRESS_IPX UNALIGNED * IpxAddress;
  603. IPX_SOURCE_ROUTING_INFO UNALIGNED * SourceRoutingInfo;
  604. ULONG SourceRoutingLength;
  605. UINT MaxUserData;
  606. PDEVICE Device = IpxDevice;
  607. USHORT NicId;
  608. PNDIS_MEDIUM Medium;
  609. PVOID *PPDO;
  610. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  611. //
  612. // First verify the parameters.
  613. //
  614. switch (InternalQueryType) {
  615. case IPX_QUERY_LINE_INFO:
  616. BindingNeeded = TRUE;
  617. LengthNeeded = sizeof(IPX_LINE_INFO);
  618. break;
  619. case IPX_QUERY_MAXIMUM_NIC_ID:
  620. case IPX_QUERY_MAX_TYPE_20_NIC_ID:
  621. BindingNeeded = FALSE;
  622. LengthNeeded = sizeof(USHORT);
  623. break;
  624. case IPX_QUERY_IS_ADDRESS_LOCAL:
  625. BindingNeeded = FALSE; // for now we don't need it
  626. LengthNeeded = sizeof(TDI_ADDRESS_IPX);
  627. break;
  628. case IPX_QUERY_RECEIVE_BUFFER_SPACE:
  629. BindingNeeded = TRUE;
  630. LengthNeeded = sizeof(ULONG);
  631. break;
  632. case IPX_QUERY_IPX_ADDRESS:
  633. if (NicHandle != NULL) {
  634. NicId = NicHandle->NicId;
  635. } else {
  636. return STATUS_INVALID_PARAMETER;
  637. }
  638. if ((NicId == 0) &&
  639. (BufferLength >= sizeof(TDI_ADDRESS_IPX))) {
  640. RtlCopyMemory (Buffer, &Device->SourceAddress, sizeof(TDI_ADDRESS_IPX));
  641. return STATUS_SUCCESS;
  642. }
  643. BindingNeeded = TRUE;
  644. LengthNeeded = sizeof(TDI_ADDRESS_IPX);
  645. break;
  646. case IPX_QUERY_SOURCE_ROUTING:
  647. BindingNeeded = TRUE;
  648. LengthNeeded = sizeof(IPX_SOURCE_ROUTING_INFO);
  649. break;
  650. //
  651. // These are moved down from NB/SPX to IPX. LengthNeeded is set to 0
  652. // so we dont return BUFFER_TOO_SMALL here; we assume here that
  653. // Bufferlength is also 0.
  654. // Buffer is actually the IRP here.
  655. //
  656. case IPX_QUERY_DATA_LINK_ADDRESS:
  657. case IPX_QUERY_NETWORK_ADDRESS:
  658. BindingNeeded = FALSE;
  659. LengthNeeded = 0;
  660. break;
  661. //
  662. // NBIPX wants to know if it is a WAN link
  663. //
  664. case IPX_QUERY_MEDIA_TYPE:
  665. BindingNeeded = TRUE;
  666. LengthNeeded = sizeof(NDIS_MEDIUM);
  667. break;
  668. case IPX_QUERY_DEVICE_RELATION:
  669. BindingNeeded = TRUE;
  670. LengthNeeded = sizeof(void *);
  671. break;
  672. default:
  673. return STATUS_NOT_SUPPORTED;
  674. }
  675. if (LengthNeeded > BufferLength) {
  676. if (BufferLengthNeeded != NULL) {
  677. *BufferLengthNeeded = LengthNeeded;
  678. }
  679. return STATUS_BUFFER_TOO_SMALL;
  680. }
  681. if (BindingNeeded) {
  682. if (NicHandle != NULL) {
  683. NicId = NicHandle->NicId;
  684. } else {
  685. return STATUS_INVALID_PARAMETER;
  686. }
  687. if (NicId == 0) {
  688. NicId = 1;
  689. }
  690. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  691. Binding = NIC_ID_TO_BINDING(IpxDevice, NicId);
  692. if ((Binding == NULL) ||
  693. (!Binding->LineUp)) {
  694. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  695. return STATUS_INVALID_PARAMETER;
  696. }
  697. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  698. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  699. }
  700. //
  701. // Now return the data.
  702. //
  703. switch (InternalQueryType) {
  704. case IPX_QUERY_LINE_INFO:
  705. LineInfo = (PIPX_LINE_INFO)Buffer;
  706. LineInfo->LinkSpeed = Binding->MediumSpeed;
  707. LineInfo->MaximumPacketSize = Binding->MaxLookaheadData + sizeof(IPX_HEADER);
  708. LineInfo->MaximumSendSize = Binding->AnnouncedMaxDatagramSize + sizeof(IPX_HEADER);
  709. LineInfo->MacOptions = Binding->Adapter->MacInfo.MacOptions;
  710. break;
  711. case IPX_QUERY_MAXIMUM_NIC_ID:
  712. MaximumNicId = (PUSHORT)Buffer;
  713. *MaximumNicId = MIN (Device->MaxBindings, IpxDevice->HighestExternalNicId);
  714. break;
  715. case IPX_QUERY_IS_ADDRESS_LOCAL:
  716. IpxAddress = (TDI_ADDRESS_IPX UNALIGNED *)Buffer;
  717. if (!IpxIsAddressLocal(IpxAddress)) {
  718. return STATUS_NO_SUCH_DEVICE;
  719. }
  720. break;
  721. case IPX_QUERY_RECEIVE_BUFFER_SPACE:
  722. ReceiveBufferSpace = (PULONG)Buffer;
  723. *ReceiveBufferSpace = Binding->Adapter->ReceiveBufferSpace;
  724. break;
  725. case IPX_QUERY_IPX_ADDRESS:
  726. RtlCopyMemory (Buffer, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
  727. break;
  728. case IPX_QUERY_SOURCE_ROUTING:
  729. SourceRoutingInfo = (IPX_SOURCE_ROUTING_INFO UNALIGNED *)Buffer;
  730. MacLookupSourceRouting(
  731. SourceRoutingInfo->Identifier,
  732. Binding,
  733. SourceRoutingInfo->RemoteAddress,
  734. SourceRoutingInfo->SourceRouting,
  735. &SourceRoutingLength);
  736. //
  737. // Reverse the direction of the source routing since it
  738. // is returned in the outgoing order.
  739. //
  740. if (SourceRoutingLength > 0) {
  741. SourceRoutingInfo->SourceRouting[0] &= 0x7f;
  742. }
  743. SourceRoutingInfo->SourceRoutingLength = (USHORT)SourceRoutingLength;
  744. MacReturnMaxDataSize(
  745. &Binding->Adapter->MacInfo,
  746. SourceRoutingInfo->SourceRouting,
  747. SourceRoutingLength,
  748. Binding->MaxSendPacketSize,
  749. &MaxUserData);
  750. //
  751. // MaxUserData does not include the MAC header but does include
  752. // any extra 802.2 etc. headers, so we adjust for that to get the
  753. // size starting at the IPX header.
  754. //
  755. SourceRoutingInfo->MaximumSendSize =
  756. MaxUserData -
  757. (Binding->DefHeaderSize - Binding->Adapter->MacInfo.MinHeaderLength);
  758. break;
  759. case IPX_QUERY_MAX_TYPE_20_NIC_ID:
  760. MaximumNicId = (PUSHORT)Buffer;
  761. *MaximumNicId = MIN (Device->MaxBindings, IpxDevice->HighestType20NicId);
  762. break;
  763. case IPX_QUERY_DATA_LINK_ADDRESS:
  764. case IPX_QUERY_NETWORK_ADDRESS:
  765. //
  766. // Call the TDI query equivalent here.
  767. //
  768. return IpxTdiQueryInformation(Device, (PREQUEST)Buffer);
  769. case IPX_QUERY_MEDIA_TYPE:
  770. Medium = (PNDIS_MEDIUM) Buffer;
  771. *Medium = Binding->Adapter->MacInfo.MediumType;
  772. IPX_DEBUG(CONFIG, ("The medium is %x\n", *Medium));
  773. break;
  774. case IPX_QUERY_DEVICE_RELATION:
  775. PPDO = (PVOID *) Buffer;
  776. *PPDO = Binding->Adapter->PNPContext;
  777. IPX_DEBUG(CONFIG, ("The PDO is %p\n", *PPDO));
  778. if (*PPDO == NULL) {
  779. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  780. return STATUS_UNSUCCESSFUL;
  781. }
  782. break;
  783. }
  784. //
  785. // If Binding was needed earlier, it was referenced, deref it now.
  786. //
  787. if (BindingNeeded) {
  788. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  789. }
  790. //
  791. // If we haven't returned failure by now, succeed.
  792. //
  793. return STATUS_SUCCESS;
  794. } /* IpxInternalQuery */
  795. VOID
  796. IpxInternalIncrementWanInactivity(
  797. #ifdef _PNP_LATER
  798. // RIP not converted yet...
  799. //
  800. IN NIC_HANDLE NicHandle
  801. #else
  802. IN USHORT NicId
  803. #endif
  804. )
  805. /*++
  806. Routine Description:
  807. This routine is the entry point where rip calls us to increment
  808. the inactivity counter on a wan binding. This is done every
  809. minute.
  810. Arguments:
  811. NicId - The NIC ID of the wan binding.
  812. Return Value:
  813. None.
  814. --*/
  815. {
  816. PBINDING Binding;
  817. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  818. IPX_GET_LOCK1(&IpxDevice->BindAccessLock, &LockHandle1);
  819. //
  820. // Change to NIC_HANDLE_TO_BINDING later. Not done yet since RIP not changed to
  821. // use NICHANDLE instead of NicId
  822. //
  823. Binding = NIC_ID_TO_BINDING(IpxDevice, NicId);
  824. if ((Binding != NULL) &&
  825. (Binding->Adapter->MacInfo.MediumAsync)) {
  826. ++Binding->WanInactivityCounter;
  827. } else {
  828. CTEAssert (FALSE);
  829. }
  830. IPX_FREE_LOCK1(&IpxDevice->BindAccessLock, LockHandle1);
  831. } /* IpxInternalIncrementWanInactivity */
  832. ULONG
  833. IpxInternalQueryWanInactivity(
  834. #ifdef _PNP_LATER
  835. IN NIC_HANDLE NicHandle
  836. #else
  837. IN USHORT NicId
  838. #endif
  839. )
  840. /*++
  841. Routine Description:
  842. This routine is the entry point where rip calls us to query
  843. the inactivity counter on a wan binding.
  844. Arguments:
  845. NicId - The NIC ID of the wan binding.
  846. Return Value:
  847. The inactivity counter for this binding.
  848. --*/
  849. {
  850. PBINDING Binding;
  851. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  852. IPX_GET_LOCK1(&IpxDevice->BindAccessLock, &LockHandle1);
  853. // Binding = NIC_HANDLE_TO_BINDING(IpxDevice, &NicHandle);
  854. Binding = NIC_ID_TO_BINDING(IpxDevice, NicId);
  855. if ((Binding != NULL) &&
  856. (Binding->Adapter->MacInfo.MediumAsync)) {
  857. IPX_FREE_LOCK1(&IpxDevice->BindAccessLock, LockHandle1);
  858. return Binding->WanInactivityCounter;
  859. } else {
  860. IPX_FREE_LOCK1(&IpxDevice->BindAccessLock, LockHandle1);
  861. CTEAssert (FALSE);
  862. return 0;
  863. }
  864. } /* IpxInternalQueryWanInactivity */
  865. // Pre-condition: Loopback binding has been created.
  866. //
  867. // This routine is used to essure that we have indicated the loopback
  868. // binding before indicate any other bindings.
  869. //
  870. // This routine returns true if we have informed NB about loopback bindings;
  871. // false if we have not informed NB about loopback and if loopback binding
  872. // does not exist.
  873. BOOLEAN IpxHasInformedNbLoopback() {
  874. BOOLEAN RetVal;
  875. PBINDING Binding;
  876. PDEVICE Device = IpxDevice;
  877. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  878. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  879. Binding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  880. if (Binding != NULL) {
  881. RetVal = Binding->IsnInformed[IDENTIFIER_NB];
  882. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  883. return RetVal;
  884. } else {
  885. DbgPrint("IPX:IpxHasInformedNbLoopback:Loopback binding is null.\n");
  886. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  887. return FALSE;
  888. }
  889. }
  890. // Pre-condition: Loopback binding has been created.
  891. //
  892. // This routine informs NB about IPX loopback binding.
  893. //
  894. // This should be the only place that we tell NB about loopback bindings.
  895. // Loopback bindings must be the first device that we indicate to NB and the
  896. // last device that we delete from NB. Thus, FirstOrLastDevice is only true
  897. // when we inform NB about the loopback binding. It simply returns we already
  898. // informed NB of loopback bindngs.
  899. VOID IpxInformNbLoopback() {
  900. PDEVICE Device = IpxDevice;
  901. IPX_PNP_INFO IpxPnPInfo;
  902. PBINDING Binding;
  903. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  904. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  905. IPX_GET_LOCK(&Device->Lock, &LockHandle);
  906. // IPX_GET_LOCK1 is no op.
  907. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  908. Binding = NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID);
  909. if (!Binding) {
  910. DbgPrint("IPX:IpxHasInformedNbLoopback:Loopback binding is null.\n");
  911. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  912. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  913. return;
  914. }
  915. if (Binding->IsnInformed[IDENTIFIER_NB] != TRUE) {
  916. Binding->IsnInformed[IDENTIFIER_NB] = TRUE;
  917. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  918. RtlZeroMemory(&IpxPnPInfo, sizeof(IpxPnPInfo));
  919. IpxPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  920. IpxPnPInfo.LineInfo.MaximumPacketSize =
  921. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  922. IpxPnPInfo.LineInfo.MaximumSendSize =
  923. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  924. IpxPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  925. IpxPnPInfo.FirstORLastDevice = TRUE;
  926. IpxPnPInfo.NewReservedAddress = TRUE;
  927. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  928. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  929. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  930. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, (USHORT) LOOPBACK_NIC_ID);
  931. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  932. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  933. //
  934. // give the PnP indication
  935. //
  936. (*Device->UpperDrivers[IDENTIFIER_NB].PnPHandler) (
  937. IPX_PNP_ADD_DEVICE,
  938. &IpxPnPInfo);
  939. IPX_DEBUG(PNP, ("IpxPnPIsnIndicate: PnP to NB add: %lx\n", Binding));
  940. } else {
  941. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  942. IPX_FREE_LOCK(&Device->Lock, LockHandle);
  943. }
  944. }
  945. VOID
  946. IpxPnPIsnIndicate(
  947. IN PVOID Param
  948. )
  949. /*++
  950. Routine Description:
  951. This routine goes through the list of adapters and informs (thru' PnP indications)
  952. the ISN drivers bound to IPX about any new adapters that have appeared before the
  953. bind took place.
  954. This is queued as a work item in the InternalBind routine.
  955. Arguments:
  956. Param - the upper driver identifier.
  957. Return Value:
  958. None.
  959. --*/
  960. {
  961. #ifdef SUNDOWN
  962. ULONG_PTR Identifier = (ULONG_PTR)Param;
  963. #else
  964. ULONG Identifier = (ULONG)Param;
  965. #endif
  966. PDEVICE Device=IpxDevice;
  967. ULONG i;
  968. PBINDING Binding;
  969. IPX_PNP_INFO IpxPnPInfo;
  970. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  971. //
  972. // Set up the LineInfo struct.
  973. //
  974. //
  975. // Do we give Binding-specific information here?
  976. //
  977. IpxPnPInfo.LineInfo.LinkSpeed = Device->LinkSpeed;
  978. IpxPnPInfo.LineInfo.MaximumPacketSize =
  979. Device->Information.MaximumLookaheadData + sizeof(IPX_HEADER);
  980. IpxPnPInfo.LineInfo.MaximumSendSize =
  981. Device->Information.MaxDatagramSize + sizeof(IPX_HEADER);
  982. IpxPnPInfo.LineInfo.MacOptions = Device->MacOptions;
  983. switch(Identifier) {
  984. case IDENTIFIER_NB:
  985. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  986. //
  987. // Inform about all the adapters
  988. //
  989. {
  990. ULONG Index = MIN (Device->MaxBindings, Device->HighestExternalNicId);
  991. IpxInformNbLoopback();
  992. KeSetEvent(
  993. &Device->NbEvent,
  994. 0L,
  995. FALSE);
  996. for (i = LOOPBACK_NIC_ID + 1; i <= Index; i++) {
  997. Binding = NIC_ID_TO_BINDING(Device, i);
  998. if (!Binding) {
  999. continue;
  1000. }
  1001. //
  1002. // We could have informed the upper driver from IpxBindAdapter
  1003. //
  1004. if (!Binding->IsnInformed[Identifier]) {
  1005. //
  1006. // Inform NB - the reserved network/node address is always that of the first
  1007. // binding
  1008. //
  1009. IpxPnPInfo.FirstORLastDevice = FALSE;
  1010. IpxPnPInfo.NewReservedAddress = FALSE;
  1011. IpxPnPInfo.NetworkAddress = Binding->LocalAddress.NetworkAddress;
  1012. RtlCopyMemory(IpxPnPInfo.NodeAddress, Binding->LocalAddress.NodeAddress, 6);
  1013. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, (USHORT)i);
  1014. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1015. //
  1016. // give the PnP indication
  1017. //
  1018. ASSERT(IpxPnPInfo.FirstORLastDevice == FALSE);
  1019. ASSERT(IpxHasInformedNbLoopback());
  1020. (*Device->UpperDrivers[Identifier].PnPHandler) (
  1021. IPX_PNP_ADD_DEVICE,
  1022. &IpxPnPInfo);
  1023. Binding->IsnInformed[Identifier] = TRUE;
  1024. IPX_DEBUG(PNP, ("IpxPnPIsnIndicate: PnP to NB add: %lx\n", Binding));
  1025. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1026. }
  1027. }
  1028. }
  1029. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1030. break;
  1031. case IDENTIFIER_SPX:
  1032. //
  1033. // For SPX this is called directly, with the IsnInformed flag appropriately set.
  1034. // This is done so that the IsnInformed flag cannot be changed under
  1035. // us by the BindAdapter routine.
  1036. //
  1037. #if 0
  1038. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  1039. if (!NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier]) {
  1040. NIC_ID_TO_BINDING(Device, 1)->IsnInformed[Identifier] = TRUE;
  1041. #endif
  1042. IpxPnPInfo.FirstORLastDevice = TRUE;
  1043. //
  1044. // Inform of the reserved address only
  1045. //
  1046. if (Device->VirtualNetwork) {
  1047. IpxPnPInfo.NetworkAddress = Device->SourceAddress.NetworkAddress;
  1048. RtlCopyMemory(IpxPnPInfo.NodeAddress, Device->SourceAddress.NodeAddress, 6);
  1049. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 0);
  1050. } else {
  1051. IpxPnPInfo.NetworkAddress = NIC_ID_TO_BINDING(Device, 1)->LocalAddress.NetworkAddress;
  1052. RtlCopyMemory(IpxPnPInfo.NodeAddress, NIC_ID_TO_BINDING(Device, 1)->LocalAddress.NodeAddress, 6);
  1053. NIC_HANDLE_FROM_NIC(IpxPnPInfo.NicHandle, 1);
  1054. }
  1055. IpxPnPInfo.NewReservedAddress = TRUE;
  1056. // IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1057. (*Device->UpperDrivers[Identifier].PnPHandler) (
  1058. IPX_PNP_ADD_DEVICE,
  1059. &IpxPnPInfo);
  1060. IPX_DEBUG(PNP, ("IpxPnPIsnIndicate: PnP to SPX add: %lx\n", NIC_ID_TO_BINDING(Device, 1)));
  1061. #if 0
  1062. } else {
  1063. CTEAssert(FALSE);
  1064. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  1065. }
  1066. #endif
  1067. }
  1068. // DbgPrint("---------- 5. Done with IpxPnPIsnIndicate ----------\n");
  1069. IpxDereferenceDevice(Device, DREF_PNP);
  1070. }