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.

1145 lines
31 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 Netbios module of the ISN transport.
  8. Author:
  9. Adam Barr (adamba) 16-November-1993
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE,NbiBind)
  18. #endif
  19. //
  20. // local functions.
  21. //
  22. NTSTATUS
  23. NbiPnPNotification(
  24. IN IPX_PNP_OPCODE OpCode,
  25. IN PVOID PnPData
  26. );
  27. extern HANDLE TdiProviderHandle;
  28. BOOLEAN fNbiTdiProviderReady = FALSE;
  29. #ifdef BIND_FIX
  30. extern PDRIVER_OBJECT NbiDriverObject;
  31. extern UNICODE_STRING NbiRegistryPath;
  32. extern PEPROCESS NbiFspProcess;
  33. DEFINE_LOCK_STRUCTURE(NbiTdiRequestInterlock);
  34. ULONG NbiBindState = 0;
  35. extern UNICODE_STRING NbiBindString;
  36. BOOLEAN fNbiTdiRequestQueued = FALSE;
  37. typedef struct{
  38. WORK_QUEUE_ITEM WorkItem;
  39. LIST_ENTRY NbiRequestLinkage;
  40. ULONG Data;
  41. } NBI_TDI_REQUEST_CONTEXT;
  42. LIST_ENTRY NbiTdiRequestList;
  43. #ifdef RASAUTODIAL
  44. VOID
  45. NbiAcdBind();
  46. VOID
  47. NbiAcdUnbind();
  48. #endif
  49. #endif // BIND_FIX
  50. NTSTATUS
  51. NbiBind(
  52. IN PDEVICE Device,
  53. IN PCONFIG Config
  54. )
  55. /*++
  56. Routine Description:
  57. This routine binds the Netbios module of ISN to the IPX
  58. module, which provides the NDIS binding services.
  59. Arguments:
  60. Device - Pointer to the Netbios device.
  61. Config - Pointer to the configuration information.
  62. Return Value:
  63. The function value is the final status from the initialization operation.
  64. --*/
  65. {
  66. NTSTATUS Status;
  67. IO_STATUS_BLOCK IoStatusBlock;
  68. OBJECT_ATTRIBUTES ObjectAttributes;
  69. /* union {
  70. IPX_INTERNAL_BIND_INPUT Input;
  71. IPX_INTERNAL_BIND_OUTPUT Output;
  72. } Bind;
  73. */
  74. InitializeObjectAttributes(
  75. &ObjectAttributes,
  76. &Config->BindName,
  77. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  78. NULL,
  79. NULL);
  80. Status = ZwCreateFile(
  81. &Device->BindHandle,
  82. SYNCHRONIZE | GENERIC_READ,
  83. &ObjectAttributes,
  84. &IoStatusBlock,
  85. NULL,
  86. FILE_ATTRIBUTE_NORMAL,
  87. FILE_SHARE_READ | FILE_SHARE_WRITE,
  88. FILE_OPEN,
  89. FILE_SYNCHRONOUS_IO_NONALERT,
  90. NULL,
  91. 0L);
  92. if (!NT_SUCCESS(Status)) {
  93. NB_DEBUG (BIND, ("Could not open IPX (%ws) %lx\n",
  94. Config->BindName.Buffer, Status));
  95. NbiWriteGeneralErrorLog(
  96. Device,
  97. EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
  98. 1,
  99. Status,
  100. Config->BindName.Buffer,
  101. 0,
  102. NULL);
  103. return Status;
  104. }
  105. //
  106. // Fill in our bind data.
  107. //
  108. Device->BindInput.Version = ISN_VERSION;
  109. Device->BindInput.Identifier = IDENTIFIER_NB;
  110. Device->BindInput.BroadcastEnable = TRUE;
  111. Device->BindInput.LookaheadRequired = 192;
  112. Device->BindInput.ProtocolOptions = 0;
  113. Device->BindInput.ReceiveHandler = NbiReceive;
  114. Device->BindInput.ReceiveCompleteHandler = NbiReceiveComplete;
  115. Device->BindInput.StatusHandler = NbiStatus;
  116. Device->BindInput.SendCompleteHandler = NbiSendComplete;
  117. Device->BindInput.TransferDataCompleteHandler = NbiTransferDataComplete;
  118. Device->BindInput.FindRouteCompleteHandler = NbiFindRouteComplete;
  119. Device->BindInput.LineUpHandler = NbiLineUp;
  120. Device->BindInput.LineDownHandler = NbiLineDown;
  121. Device->BindInput.ScheduleRouteHandler = NULL;
  122. Device->BindInput.PnPHandler = NbiPnPNotification;
  123. Status = ZwDeviceIoControlFile(
  124. Device->BindHandle, // HANDLE to File
  125. NULL, // HANDLE to Event
  126. NULL, // ApcRoutine
  127. NULL, // ApcContext
  128. &IoStatusBlock, // IO_STATUS_BLOCK
  129. IOCTL_IPX_INTERNAL_BIND, // IoControlCode
  130. &Device->BindInput, // Input Buffer
  131. sizeof(Device->BindInput), // Input Buffer Length
  132. &Device->Bind, // OutputBuffer
  133. sizeof(Device->Bind)); // OutputBufferLength
  134. //
  135. // We open synchronous, so this shouldn't happen.
  136. //
  137. CTEAssert (Status != STATUS_PENDING);
  138. //
  139. // Save the bind data.
  140. //
  141. if (Status == STATUS_SUCCESS) {
  142. NB_DEBUG2 (BIND, ("Successfully bound to IPX (%ws)\n",
  143. Config->BindName.Buffer));
  144. } else {
  145. NB_DEBUG (BIND, ("Could not bind to IPX (%ws) %lx\n",
  146. Config->BindName.Buffer, Status));
  147. NbiWriteGeneralErrorLog(
  148. Device,
  149. EVENT_TRANSPORT_BINDING_FAILED,
  150. 1,
  151. Status,
  152. Config->BindName.Buffer,
  153. 0,
  154. NULL);
  155. ZwClose(Device->BindHandle);
  156. }
  157. return Status;
  158. } /* NbiBind */
  159. VOID
  160. NbiUnbind(
  161. IN PDEVICE Device
  162. )
  163. /*++
  164. Routine Description:
  165. This function closes the binding between the Netbios over
  166. IPX module and the IPX module previously established by
  167. NbiBind.
  168. Arguments:
  169. Device - The netbios device object.
  170. Return Value:
  171. None.
  172. --*/
  173. {
  174. ZwClose (Device->BindHandle);
  175. } /* NbiUnbind */
  176. #ifdef BIND_FIX
  177. NTSTATUS
  178. NbiBindToIpx(
  179. )
  180. {
  181. NTSTATUS status;
  182. PDEVICE Device;
  183. PIPX_HEADER IpxHeader;
  184. CTELockHandle LockHandle;
  185. WCHAR wcNwlnkNbProviderName[60] = L"\\Device\\NwlnkNb";
  186. UNICODE_STRING ucNwlnkNbProviderName;
  187. PCONFIG Config = NULL;
  188. //
  189. // This allocates the CONFIG structure and returns
  190. // it in Config.
  191. //
  192. status = NbiGetConfiguration(NbiDriverObject, &NbiRegistryPath, &Config);
  193. if (!NT_SUCCESS (status)) {
  194. //
  195. // If it failed it logged an error.
  196. //
  197. PANIC (" Failed to initialize transport, ISN Netbios initialization failed.\n");
  198. return status;
  199. }
  200. //
  201. // Create the device object which exports our name.
  202. //
  203. status = NbiCreateDevice (NbiDriverObject, &Config->DeviceName, &Device);
  204. if (!NT_SUCCESS (status)) {
  205. NbiWriteGeneralErrorLog(
  206. (PVOID)NbiDriverObject,
  207. EVENT_IPX_CREATE_DEVICE,
  208. 801,
  209. status,
  210. NULL,
  211. 0,
  212. NULL);
  213. NbiFreeConfiguration(Config);
  214. return status;
  215. }
  216. NbiDevice = Device;
  217. //
  218. // Initialize the global pool interlock
  219. //
  220. CTEInitLock (&NbiGlobalPoolInterlock);
  221. //
  222. // Save the relevant configuration parameters.
  223. //
  224. Device->AckDelayTime = (Config->Parameters[CONFIG_ACK_DELAY_TIME] / SHORT_TIMER_DELTA) + 1;
  225. Device->AckWindow = Config->Parameters[CONFIG_ACK_WINDOW];
  226. Device->AckWindowThreshold = Config->Parameters[CONFIG_ACK_WINDOW_THRESHOLD];
  227. Device->EnablePiggyBackAck = Config->Parameters[CONFIG_ENABLE_PIGGYBACK_ACK];
  228. Device->Extensions = Config->Parameters[CONFIG_EXTENSIONS];
  229. Device->RcvWindowMax = Config->Parameters[CONFIG_RCV_WINDOW_MAX];
  230. Device->BroadcastCount = Config->Parameters[CONFIG_BROADCAST_COUNT];
  231. Device->BroadcastTimeout = Config->Parameters[CONFIG_BROADCAST_TIMEOUT];
  232. Device->ConnectionCount = Config->Parameters[CONFIG_CONNECTION_COUNT];
  233. Device->ConnectionTimeout = Config->Parameters[CONFIG_CONNECTION_TIMEOUT] * 500;
  234. Device->InitPackets = Config->Parameters[CONFIG_INIT_PACKETS];
  235. Device->MaxPackets = Config->Parameters[CONFIG_MAX_PACKETS];
  236. Device->InitialRetransmissionTime = Config->Parameters[CONFIG_INIT_RETRANSMIT_TIME];
  237. Device->Internet = Config->Parameters[CONFIG_INTERNET];
  238. Device->KeepAliveCount = Config->Parameters[CONFIG_KEEP_ALIVE_COUNT];
  239. Device->KeepAliveTimeout = Config->Parameters[CONFIG_KEEP_ALIVE_TIMEOUT];
  240. Device->RetransmitMax = Config->Parameters[CONFIG_RETRANSMIT_MAX];
  241. Device->RouterMtu = Config->Parameters[CONFIG_ROUTER_MTU];
  242. Device->MaxReceiveBuffers = 20; // Make it configurable?
  243. Device->NameCache = NULL; // MP bug: IPX tries to Flush it before it's initialized!
  244. Device->FindNameTimeout = ((Config->Parameters[CONFIG_BROADCAST_TIMEOUT]) + (FIND_NAME_GRANULARITY/2)) /
  245. FIND_NAME_GRANULARITY;
  246. //
  247. // Initialize the BindReady Event to False
  248. //
  249. KeInitializeEvent (&Device->BindReadyEvent, NotificationEvent, FALSE);
  250. //
  251. // Create Hash Table to store netbios cache entries
  252. // For server create a big table, for workstation a small one
  253. //
  254. if (MmIsThisAnNtAsSystem())
  255. {
  256. status = CreateNetbiosCacheTable( &Device->NameCache, NB_NETBIOS_CACHE_TABLE_LARGE );
  257. }
  258. else
  259. {
  260. status = CreateNetbiosCacheTable( &Device->NameCache, NB_NETBIOS_CACHE_TABLE_SMALL );
  261. }
  262. if (!NT_SUCCESS (status))
  263. {
  264. //
  265. // If it failed it logged an error.
  266. //
  267. NbiFreeConfiguration(Config);
  268. NbiDereferenceDevice (Device, DREF_LOADED);
  269. return status;
  270. }
  271. // Initialize the timer system. This should be done before
  272. // binding to ipx because we should have timers intialized
  273. // before ipx calls our pnp indications.
  274. NbiInitializeTimers (Device);
  275. //
  276. // Register us as a provider with Tdi
  277. //
  278. RtlInitUnicodeString(&ucNwlnkNbProviderName, wcNwlnkNbProviderName);
  279. ucNwlnkNbProviderName.MaximumLength = sizeof (wcNwlnkNbProviderName);
  280. if (!NT_SUCCESS (TdiRegisterProvider (&ucNwlnkNbProviderName, &TdiProviderHandle)))
  281. {
  282. TdiProviderHandle = NULL;
  283. DbgPrint("Nbi.DriverEntry: FAILed to Register NwlnkNb as Provider!\n");
  284. }
  285. //
  286. // Now bind to IPX via the internal interface.
  287. //
  288. status = NbiBind (Device, Config);
  289. if (!NT_SUCCESS (status)) {
  290. //
  291. // If it failed it logged an error.
  292. //
  293. if (TdiProviderHandle)
  294. {
  295. TdiDeregisterProvider (TdiProviderHandle);
  296. }
  297. NbiFreeConfiguration(Config);
  298. NbiDereferenceDevice (Device, DREF_LOADED);
  299. return status;
  300. }
  301. #ifdef RSRC_TIMEOUT_DBG
  302. NbiInitDeathPacket();
  303. // NbiGlobalMaxResTimeout.QuadPart = 50; // 1*1000*10000;
  304. NbiGlobalMaxResTimeout.QuadPart = 20*60*1000;
  305. NbiGlobalMaxResTimeout.QuadPart *= 10000;
  306. #endif // RSRC_TIMEOUT_DBG
  307. NB_GET_LOCK (&Device->Lock, &LockHandle);
  308. //
  309. // Allocate our initial connectionless packet pool.
  310. //
  311. NbiAllocateSendPool (Device);
  312. //
  313. // Allocate our initial receive packet pool.
  314. //
  315. NbiAllocateReceivePool (Device);
  316. //
  317. // Allocate our initial receive buffer pool.
  318. //
  319. //
  320. if ( DEVICE_STATE_CLOSED == Device->State ) {
  321. Device->State = DEVICE_STATE_LOADED;
  322. }
  323. NB_FREE_LOCK (&Device->Lock, LockHandle);
  324. //
  325. // Fill in the default connnectionless header.
  326. //
  327. IpxHeader = &Device->ConnectionlessHeader;
  328. IpxHeader->CheckSum = 0xffff;
  329. IpxHeader->PacketLength[0] = 0;
  330. IpxHeader->PacketLength[1] = 0;
  331. IpxHeader->TransportControl = 0;
  332. IpxHeader->PacketType = 0;
  333. *(UNALIGNED ULONG *)(IpxHeader->DestinationNetwork) = 0;
  334. RtlCopyMemory(IpxHeader->DestinationNode, BroadcastAddress, 6);
  335. IpxHeader->DestinationSocket = NB_SOCKET;
  336. IpxHeader->SourceSocket = NB_SOCKET;
  337. #ifdef RASAUTODIAL
  338. //
  339. // Get the automatic connection
  340. // driver entry points.
  341. //
  342. NbiAcdBind();
  343. #endif
  344. NbiFreeConfiguration(Config);
  345. NbiBindState |= NBI_BOUND_TO_IPX;
  346. Device->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
  347. KeSetEvent(&Device->BindReadyEvent, 0, FALSE);
  348. return STATUS_SUCCESS;
  349. }
  350. VOID
  351. NbiUnbindFromIpx(
  352. )
  353. /*++
  354. Routine Description:
  355. This unbinds from any NDIS drivers that are open and frees all resources
  356. associated with the transport. The I/O system will not call us until
  357. nobody above has Netbios open.
  358. Arguments:
  359. Return Value:
  360. None.
  361. --*/
  362. {
  363. PDEVICE Device = NbiDevice;
  364. NbiBindState &= (~NBI_BOUND_TO_IPX);
  365. #ifdef RASAUTODIAL
  366. //
  367. // Unbind from the
  368. // automatic connection driver.
  369. //
  370. NbiAcdUnbind();
  371. #endif
  372. Device->State = DEVICE_STATE_STOPPING;
  373. //
  374. // Cancel the long timer.
  375. //
  376. if (CTEStopTimer (&Device->LongTimer))
  377. {
  378. NbiDereferenceDevice (Device, DREF_LONG_TIMER);
  379. }
  380. //
  381. // Unbind from the IPX driver.
  382. //
  383. NbiUnbind (Device);
  384. //
  385. // This event will get set when the reference count
  386. // drops to 0.
  387. //
  388. KeInitializeEvent (&Device->UnloadEvent, NotificationEvent, FALSE);
  389. Device->UnloadWaiting = TRUE;
  390. //
  391. // Remove the reference for us being loaded.
  392. //
  393. NbiDereferenceDevice (Device, DREF_LOADED);
  394. //
  395. // Wait for our count to drop to zero.
  396. //
  397. KeWaitForSingleObject (&Device->UnloadEvent, Executive, KernelMode, TRUE, (PLARGE_INTEGER)NULL);
  398. //
  399. // Free the cache of netbios names.
  400. //
  401. DestroyNetbiosCacheTable (Device->NameCache);
  402. //
  403. // Do the cleanup that has to happen at IRQL 0.
  404. //
  405. ExDeleteResourceLite (&Device->AddressResource);
  406. IoDeleteDevice ((PDEVICE_OBJECT)Device);
  407. }
  408. UCHAR AdapterName[NB_NETBIOS_NAME_SIZE];
  409. VOID
  410. NbiNotifyTdiClients(
  411. IN PWORK_QUEUE_ITEM WorkItem
  412. )
  413. {
  414. NTSTATUS Status;
  415. TA_NETBIOS_ADDRESS PermAddress;
  416. HANDLE TdiRegistrationHandle, NetAddressRegistrationHandle;
  417. CTELockHandle LockHandle;
  418. PLIST_ENTRY p;
  419. PDEVICE Device = NbiDevice;
  420. NBI_TDI_REQUEST_CONTEXT *pNbiTdiRequest = (NBI_TDI_REQUEST_CONTEXT *) WorkItem;
  421. ULONG RequestFlag;
  422. BOOLEAN fRegisterWithTdi, fDeregisterWithTdi;
  423. do
  424. {
  425. RequestFlag = pNbiTdiRequest->Data;
  426. fRegisterWithTdi = fDeregisterWithTdi = FALSE;
  427. switch (RequestFlag)
  428. {
  429. case NBI_IPX_REGISTER:
  430. {
  431. if (NbiBindState & TDI_HAS_NOTIFIED)
  432. {
  433. fRegisterWithTdi = TRUE;
  434. }
  435. NbiBindState |= IPX_HAS_DEVICES;
  436. break;
  437. }
  438. case NBI_TDI_REGISTER:
  439. {
  440. if (NbiBindState & IPX_HAS_DEVICES)
  441. {
  442. fRegisterWithTdi = TRUE;
  443. }
  444. NbiBindState |= TDI_HAS_NOTIFIED;
  445. break;
  446. }
  447. case NBI_TDI_DEREGISTER:
  448. {
  449. fDeregisterWithTdi = TRUE;
  450. NbiBindState &= (~TDI_HAS_NOTIFIED);
  451. break;
  452. }
  453. case NBI_IPX_DEREGISTER:
  454. {
  455. fDeregisterWithTdi = TRUE;
  456. NbiBindState &= (~IPX_HAS_DEVICES);
  457. break;
  458. }
  459. default:
  460. {
  461. break;
  462. }
  463. }
  464. if (fRegisterWithTdi)
  465. {
  466. NB_GET_LOCK (&Device->Lock, &LockHandle);
  467. Device->State = DEVICE_STATE_OPEN;
  468. NB_FREE_LOCK (&Device->Lock, LockHandle);
  469. if (!(Device->TdiRegistrationHandle))
  470. {
  471. Status = TdiRegisterDeviceObject (&Device->DeviceString, &Device->TdiRegistrationHandle);
  472. if (!NT_SUCCESS(Status))
  473. {
  474. Device->TdiRegistrationHandle = NULL;
  475. DbgPrint ("Nbi.NbiNotifyTdiClients: ERROR -- TdiRegisterDeviceObject = <%x>\n", Status);
  476. }
  477. }
  478. //
  479. // If there is already an address Registered, Deregister it (since Adapter address could change)
  480. //
  481. if (Device->NetAddressRegistrationHandle)
  482. {
  483. DbgPrint ("Nbi!NbiNotifyTdiClients[REGISTER]: NetAddress exists! Calling TdiDeregisterNetAddress\n");
  484. Status = TdiDeregisterNetAddress (Device->NetAddressRegistrationHandle);
  485. Device->NetAddressRegistrationHandle = NULL;
  486. }
  487. //
  488. // Register the permanent NetAddress!
  489. //
  490. PermAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  491. PermAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  492. PermAddress.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  493. CTEMemCopy (PermAddress.Address[0].Address[0].NetbiosName, AdapterName, NB_NETBIOS_NAME_SIZE);
  494. if (!NT_SUCCESS(Status = TdiRegisterNetAddress((PTA_ADDRESS) PermAddress.Address,
  495. &Device->DeviceString,
  496. NULL,
  497. &Device->NetAddressRegistrationHandle)) )
  498. {
  499. Device->NetAddressRegistrationHandle = NULL;
  500. DbgPrint ("Nbi.NbiNotifyTdiClients[REGISTER]: ERROR -- TdiRegisterNetAddress=<%x>\n",Status);
  501. }
  502. }
  503. else if (fDeregisterWithTdi)
  504. {
  505. NB_GET_LOCK (&Device->Lock, &LockHandle);
  506. TdiRegistrationHandle = Device->TdiRegistrationHandle;
  507. Device->TdiRegistrationHandle = NULL;
  508. NetAddressRegistrationHandle = Device->NetAddressRegistrationHandle;
  509. Device->NetAddressRegistrationHandle = NULL;
  510. Device->State = DEVICE_STATE_LOADED;
  511. NB_FREE_LOCK (&Device->Lock, LockHandle);
  512. //
  513. // DeRegister the NetAddress!
  514. //
  515. if (NetAddressRegistrationHandle)
  516. {
  517. if (!NT_SUCCESS (Status = TdiDeregisterNetAddress (NetAddressRegistrationHandle)))
  518. {
  519. DbgPrint ("NwlnkNb.NbiPnPNotification: ERROR -- TdiDeregisterNetAddress=<%x>\n", Status);
  520. }
  521. }
  522. //
  523. // Deregister the Device
  524. //
  525. if (TdiRegistrationHandle)
  526. {
  527. if (!NT_SUCCESS (Status = TdiDeregisterDeviceObject(TdiRegistrationHandle)))
  528. {
  529. DbgPrint ("NwlnkNb.NbiPnPNotification: ERROR -- TdiDeregisterDeviceObject=<%x>\n",Status);
  530. }
  531. }
  532. }
  533. NbiFreeMemory (pNbiTdiRequest, sizeof(NBI_TDI_REQUEST_CONTEXT), MEMORY_WORK_ITEM, "TdiRequest");
  534. CTEGetLock (&NbiTdiRequestInterlock, &LockHandle);
  535. if (IsListEmpty(&NbiTdiRequestList))
  536. {
  537. fNbiTdiRequestQueued = FALSE;
  538. CTEFreeLock (&NbiTdiRequestInterlock, LockHandle);
  539. break;
  540. }
  541. p = RemoveHeadList (&NbiTdiRequestList);
  542. CTEFreeLock (&NbiTdiRequestInterlock, LockHandle);
  543. pNbiTdiRequest = CONTAINING_RECORD (p, NBI_TDI_REQUEST_CONTEXT, NbiRequestLinkage);
  544. } while (1);
  545. }
  546. NTSTATUS
  547. NbiQueueTdiRequest(
  548. enum eTDI_ACTION RequestFlag
  549. )
  550. {
  551. NBI_TDI_REQUEST_CONTEXT *pNbiTdiRequest;
  552. CTELockHandle LockHandle;
  553. NTSTATUS Status = STATUS_SUCCESS;
  554. CTEGetLock (&NbiTdiRequestInterlock, &LockHandle);
  555. if (pNbiTdiRequest = NbiAllocateMemory (sizeof(NBI_TDI_REQUEST_CONTEXT), MEMORY_WORK_ITEM, "TdiRequest"))
  556. {
  557. pNbiTdiRequest->Data = RequestFlag;
  558. if (fNbiTdiRequestQueued)
  559. {
  560. InsertTailList (&NbiTdiRequestList, &pNbiTdiRequest->NbiRequestLinkage);
  561. }
  562. else
  563. {
  564. fNbiTdiRequestQueued = TRUE;
  565. ExInitializeWorkItem (&pNbiTdiRequest->WorkItem, NbiNotifyTdiClients, (PVOID)pNbiTdiRequest);
  566. ExQueueWorkItem (&pNbiTdiRequest->WorkItem, DelayedWorkQueue);
  567. }
  568. }
  569. else
  570. {
  571. NB_DEBUG( DEVICE, ("Cannt schdule work item to Notify Tdi clients\n"));
  572. Status = STATUS_INSUFFICIENT_RESOURCES;
  573. }
  574. CTEFreeLock (&NbiTdiRequestInterlock, LockHandle);
  575. return (Status);
  576. }
  577. VOID
  578. TdiBindHandler(
  579. TDI_PNP_OPCODE PnPOpCode,
  580. PUNICODE_STRING pDeviceName,
  581. PWSTR MultiSZBindList)
  582. {
  583. NTSTATUS Status;
  584. BOOLEAN Attached;
  585. if ((!pDeviceName) ||
  586. (RtlCompareUnicodeString(pDeviceName, &NbiBindString, TRUE)))
  587. {
  588. return;
  589. }
  590. switch (PnPOpCode)
  591. {
  592. case (TDI_PNP_OP_ADD):
  593. {
  594. if (!(NbiBindState & NBI_BOUND_TO_IPX))
  595. {
  596. if (PsGetCurrentProcess() != NbiFspProcess)
  597. {
  598. KeAttachProcess((PRKPROCESS)NbiFspProcess);
  599. Attached = TRUE;
  600. }
  601. else
  602. {
  603. Attached = FALSE;
  604. }
  605. Status = NbiBindToIpx();
  606. if (Attached)
  607. {
  608. KeDetachProcess();
  609. }
  610. }
  611. NbiQueueTdiRequest ((ULONG) NBI_TDI_REGISTER);
  612. break;
  613. }
  614. case (TDI_PNP_OP_DEL):
  615. {
  616. if (NbiBindState & NBI_BOUND_TO_IPX)
  617. {
  618. NbiQueueTdiRequest ((ULONG) NBI_TDI_DEREGISTER);
  619. }
  620. break;
  621. }
  622. default:
  623. {
  624. break;
  625. }
  626. }
  627. }
  628. #endif // BIND_FIX
  629. VOID
  630. NbiStatus(
  631. IN USHORT NicId,
  632. IN NDIS_STATUS GeneralStatus,
  633. IN PVOID StatusBuffer,
  634. IN UINT StatusBufferLength
  635. )
  636. /*++
  637. Routine Description:
  638. This function receives a status indication from IPX,
  639. corresponding to a status indication from an underlying
  640. NDIS driver.
  641. Arguments:
  642. NicId - The NIC ID of the underlying adapter.
  643. GeneralStatus - The general status code.
  644. StatusBuffer - The status buffer.
  645. StatusBufferLength - The length of the status buffer.
  646. Return Value:
  647. None.
  648. --*/
  649. {
  650. } /* NbiStatus */
  651. VOID
  652. NbiLineUp(
  653. IN USHORT NicId,
  654. IN PIPX_LINE_INFO LineInfo,
  655. IN NDIS_MEDIUM DeviceType,
  656. IN PVOID ConfigurationData
  657. )
  658. /*++
  659. Routine Description:
  660. This function receives line up indications from IPX,
  661. indicating that the specified adapter is now up with
  662. the characteristics shown.
  663. Arguments:
  664. NicId - The NIC ID of the underlying adapter.
  665. LineInfo - Information about the adapter's medium.
  666. DeviceType - The type of the adapter.
  667. ConfigurationData - IPX-specific configuration data.
  668. Return Value:
  669. None.
  670. --*/
  671. {
  672. PIPXCP_CONFIGURATION Configuration = (PIPXCP_CONFIGURATION)ConfigurationData;
  673. } /* NbiLineUp */
  674. VOID
  675. NbiLineDown(
  676. IN USHORT NicId,
  677. IN ULONG_PTR FwdAdapterContext
  678. )
  679. /*++
  680. Routine Description:
  681. This function receives line down indications from IPX,
  682. indicating that the specified adapter is no longer
  683. up.
  684. Arguments:
  685. NicId - The NIC ID of the underlying adapter.
  686. Return Value:
  687. None.
  688. --*/
  689. {
  690. } /* NbiLineDown */
  691. NTSTATUS
  692. NbiPnPNotification(
  693. IN IPX_PNP_OPCODE OpCode,
  694. IN PVOID PnPData
  695. )
  696. /*++
  697. Routine Description:
  698. This function receives the notification about PnP events from IPX.
  699. Arguments:
  700. OpCode - Type of the PnP event
  701. PnPData - Data associated with this event.
  702. Return Value:
  703. None.
  704. --*/
  705. {
  706. CTELockHandle LockHandle;
  707. PADAPTER_ADDRESS AdapterAddress;
  708. USHORT MaximumNicId = 0;
  709. PDEVICE Device = NbiDevice;
  710. NTSTATUS Status = STATUS_SUCCESS;
  711. PNET_PNP_EVENT NetPnpEvent = (PNET_PNP_EVENT) PnPData;
  712. IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
  713. NB_DEBUG2( DEVICE, ("Received a pnp notification, opcode %d\n",OpCode ));
  714. #ifdef BIND_FIX
  715. if (!(NbiBindState & NBI_BOUND_TO_IPX))
  716. {
  717. KeWaitForSingleObject (&Device->BindReadyEvent, // Object to wait on.
  718. Executive, // Reason for waiting
  719. KernelMode, // Processor mode
  720. FALSE, // Alertable
  721. NULL); // Timeout
  722. }
  723. #endif // BIND_FIX
  724. switch( OpCode ) {
  725. case IPX_PNP_ADD_DEVICE : {
  726. BOOLEAN ReallocReceiveBuffers = FALSE;
  727. NB_GET_LOCK( &Device->Lock, &LockHandle );
  728. if ( PnPInfo->NewReservedAddress ) {
  729. *(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress;
  730. RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);
  731. *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork =
  732. *(UNALIGNED ULONG *)Device->Bind.Network;
  733. RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);
  734. }
  735. if ( PnPInfo->FirstORLastDevice ) {
  736. // Comment out the ASSERTS until Ting can check in his fix!
  737. // CTEAssert( PnPInfo->NewReservedAddress );
  738. // CTEAssert( Device->State != DEVICE_STATE_OPEN );
  739. // CTEAssert( !Device->MaximumNicId );
  740. //
  741. // we must do this while we still have the device lock.
  742. //
  743. if ( !Device->LongTimerRunning ) {
  744. Device->LongTimerRunning = TRUE;
  745. NbiReferenceDevice (Device, DREF_LONG_TIMER);
  746. CTEStartTimer( &Device->LongTimer, LONG_TIMER_DELTA, NbiLongTimeout, (PVOID)Device);
  747. }
  748. Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
  749. Device->Bind.LineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumSendSize;
  750. ReallocReceiveBuffers = TRUE;
  751. } else {
  752. if ( PnPInfo->LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) {
  753. Device->Bind.LineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumSendSize;
  754. ReallocReceiveBuffers = TRUE;
  755. }
  756. //
  757. // MaxSendSize could become smaller.
  758. //
  759. Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
  760. }
  761. Device->MaximumNicId++;
  762. //
  763. //
  764. RtlZeroMemory(AdapterName, 10);
  765. RtlCopyMemory(&AdapterName[10], PnPInfo->NodeAddress, 6);
  766. AdapterAddress = NbiCreateAdapterAddress (PnPInfo->NodeAddress);
  767. //
  768. // And finally remove all the failed cache entries since we might
  769. // find those routes using this new adapter
  770. //
  771. FlushFailedNetbiosCacheEntries(Device->NameCache);
  772. NB_FREE_LOCK( &Device->Lock, LockHandle );
  773. if ( ReallocReceiveBuffers ) {
  774. PWORK_QUEUE_ITEM WorkItem;
  775. WorkItem = NbiAllocateMemory( sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buffer work item");
  776. if ( WorkItem ) {
  777. ExInitializeWorkItem( WorkItem, NbiReAllocateReceiveBufferPool, (PVOID) WorkItem );
  778. ExQueueWorkItem( WorkItem, DelayedWorkQueue );
  779. } else {
  780. NB_DEBUG( DEVICE, ("Cannt schdule work item to realloc receive buffer pool\n"));
  781. }
  782. }
  783. //
  784. // Notify the TDI clients about the device creation
  785. //
  786. if (PnPInfo->FirstORLastDevice)
  787. {
  788. NbiQueueTdiRequest ((ULONG) NBI_IPX_REGISTER);
  789. if ((TdiProviderHandle) && (!fNbiTdiProviderReady))
  790. {
  791. fNbiTdiProviderReady = TRUE;
  792. TdiProviderReady (TdiProviderHandle);
  793. }
  794. }
  795. break;
  796. }
  797. case IPX_PNP_DELETE_DEVICE : {
  798. PLIST_ENTRY p;
  799. PNETBIOS_CACHE CacheName;
  800. USHORT i,j,NetworksRemoved;
  801. NB_GET_LOCK( &Device->Lock, &LockHandle );
  802. CTEAssert (Device->MaximumNicId);
  803. Device->MaximumNicId--;
  804. //
  805. // MaximumSendSize could change if the card with the smallest send size just
  806. // got removed. MaximumPacketSize could only become smaller and we ignore that
  807. // since we dont need to(want to) realloc ReceiveBuffers.
  808. //
  809. Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
  810. //
  811. // Flush all the cache entries that are using this NicId in the local
  812. // target.
  813. //
  814. RemoveInvalidRoutesFromNetbiosCacheTable( Device->NameCache, &PnPInfo->NicHandle );
  815. NbiDestroyAdapterAddress (NULL, PnPInfo->NodeAddress);
  816. //
  817. // inform tdi clients about the device deletion
  818. //
  819. if (PnPInfo->FirstORLastDevice)
  820. {
  821. Device->State = DEVICE_STATE_LOADED; // Set this now even though it will be set again later
  822. NB_FREE_LOCK (&Device->Lock, LockHandle);
  823. NbiQueueTdiRequest ((ULONG) NBI_IPX_DEREGISTER);
  824. }
  825. else
  826. {
  827. NB_FREE_LOCK (&Device->Lock, LockHandle);
  828. }
  829. break;
  830. }
  831. case IPX_PNP_ADDRESS_CHANGE: {
  832. PADDRESS Address;
  833. BOOLEAN ReservedNameClosing = FALSE;
  834. CTEAssert( PnPInfo->NewReservedAddress );
  835. NB_GET_LOCK( &Device->Lock, &LockHandle );
  836. *(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress;
  837. RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);
  838. *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network;
  839. RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);
  840. NB_FREE_LOCK( &Device->Lock, LockHandle );
  841. break;
  842. }
  843. case IPX_PNP_TRANSLATE_DEVICE:
  844. break;
  845. case IPX_PNP_TRANSLATE_ADDRESS:
  846. break;
  847. case IPX_PNP_QUERY_POWER:
  848. case IPX_PNP_QUERY_REMOVE:
  849. //
  850. // IPX wants to know if we can power off or remove an apapter.
  851. // We DONT look if there are any open connections before deciding.
  852. // We merely ask our TDI Clients, if they are OK with it, so are we.
  853. //
  854. // Via TDI to our Clients.
  855. Status = TdiPnPPowerRequest(
  856. &Device->DeviceString,
  857. NetPnpEvent,
  858. NULL,
  859. NULL,
  860. Device->Bind.PnPCompleteHandler
  861. );
  862. break;
  863. case IPX_PNP_SET_POWER:
  864. case IPX_PNP_CANCEL_REMOVE:
  865. //
  866. // IPX is telling us that the power is going off.
  867. // We tell our TDI Clients about it.
  868. //
  869. Status = TdiPnPPowerRequest(
  870. &Device->DeviceString,
  871. NetPnpEvent,
  872. NULL,
  873. NULL,
  874. Device->Bind.PnPCompleteHandler
  875. );
  876. break;
  877. default:
  878. CTEAssert( FALSE );
  879. }
  880. return Status;
  881. } /* NbiPnPNotification */