Source code of Windows XP (NT5)
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.

3036 lines
84 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. nbfdrvr.c
  5. Abstract:
  6. This module contains code which defines the NetBIOS Frames Protocol
  7. transport provider's device object.
  8. Author:
  9. David Beaver (dbeaver) 2-July-1991
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // This is a list of all the device contexts that NBF owns,
  18. // used while unloading.
  19. //
  20. LIST_ENTRY NbfDeviceList = {0,0}; // initialized for real at runtime.
  21. //
  22. // And a lock that protects the global list of NBF devices
  23. //
  24. FAST_MUTEX NbfDevicesLock;
  25. //
  26. // Global variables this is a copy of the path in the registry for
  27. // configuration data.
  28. //
  29. UNICODE_STRING NbfRegistryPath;
  30. //
  31. // We need the driver object to create device context structures.
  32. //
  33. PDRIVER_OBJECT NbfDriverObject;
  34. //
  35. // A handle to be used in all provider notifications to TDI layer
  36. //
  37. HANDLE NbfProviderHandle;
  38. //
  39. // Global Configuration block for the driver ( no lock required )
  40. //
  41. PCONFIG_DATA NbfConfig = NULL;
  42. #ifdef NBF_LOCKS // see spnlckdb.c
  43. extern KSPIN_LOCK NbfGlobalLock;
  44. #endif // def NBF_LOCKS
  45. //
  46. // The debugging longword, containing a bitmask as defined in NBFCONST.H.
  47. // If a bit is set, then debugging is turned on for that component.
  48. //
  49. #if DBG
  50. ULONG NbfDebug = 0;
  51. BOOLEAN NbfDisconnectDebug;
  52. NBF_SEND NbfSends[TRACK_TDI_LIMIT+1];
  53. LONG NbfSendsNext;
  54. NBF_SEND_COMPLETE NbfCompletedSends[TRACK_TDI_LIMIT+1];
  55. LONG NbfCompletedSendsNext;
  56. NBF_RECEIVE NbfReceives[TRACK_TDI_LIMIT+1];
  57. LONG NbfReceivesNext;
  58. NBF_RECEIVE_COMPLETE NbfCompletedReceives[TRACK_TDI_LIMIT+1];
  59. LONG NbfCompletedReceivesNext=0;
  60. PVOID * NbfConnectionTable;
  61. PVOID * NbfRequestTable;
  62. PVOID * NbfUiFrameTable;
  63. PVOID * NbfSendPacketTable;
  64. PVOID * NbfLinkTable;
  65. PVOID * NbfAddressFileTable;
  66. PVOID * NbfAddressTable;
  67. LIST_ENTRY NbfGlobalRequestList;
  68. LIST_ENTRY NbfGlobalLinkList;
  69. LIST_ENTRY NbfGlobalConnectionList;
  70. KSPIN_LOCK NbfGlobalInterlock;
  71. KSPIN_LOCK NbfGlobalHistoryLock;
  72. PVOID
  73. TtdiSend ();
  74. PVOID
  75. TtdiReceive ();
  76. PVOID
  77. TtdiServer ();
  78. KEVENT TdiSendEvent;
  79. KEVENT TdiReceiveEvent;
  80. KEVENT TdiServerEvent;
  81. #endif
  82. #if MAGIC
  83. BOOLEAN NbfEnableMagic = FALSE; // Controls sending of magic bullets.
  84. #endif // MAGIC
  85. //
  86. // This prevents us from having a bss section
  87. //
  88. ULONG _setjmpexused = 0;
  89. //
  90. // Forward declaration of various routines used in this module.
  91. //
  92. NTSTATUS
  93. DriverEntry(
  94. IN PDRIVER_OBJECT DriverObject,
  95. IN PUNICODE_STRING RegistryPath
  96. );
  97. VOID
  98. NbfUnload(
  99. IN PDRIVER_OBJECT DriverObject
  100. );
  101. VOID
  102. NbfFreeConfigurationInfo (
  103. IN PCONFIG_DATA ConfigurationInfo
  104. );
  105. NTSTATUS
  106. NbfDispatchOpenClose(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp
  109. );
  110. NTSTATUS
  111. NbfDispatchInternal(
  112. IN PDEVICE_OBJECT DeviceObject,
  113. IN PIRP Irp
  114. );
  115. NTSTATUS
  116. NbfDispatch(
  117. IN PDEVICE_OBJECT DeviceObject,
  118. IN PIRP Irp
  119. );
  120. NTSTATUS
  121. NbfDeviceControl(
  122. IN PDEVICE_OBJECT DeviceObject,
  123. IN PIRP Irp,
  124. IN PIO_STACK_LOCATION IrpSp
  125. );
  126. NTSTATUS
  127. NbfDispatchPnPPower(
  128. IN PDEVICE_OBJECT DeviceObject,
  129. IN PIRP Irp,
  130. IN PIO_STACK_LOCATION IrpSp
  131. );
  132. VOID
  133. NbfDeallocateResources(
  134. IN PDEVICE_CONTEXT DeviceContext
  135. );
  136. #ifdef RASAUTODIAL
  137. VOID
  138. NbfAcdBind();
  139. VOID
  140. NbfAcdUnbind();
  141. #endif // RASAUTODIAL
  142. #ifdef ALLOC_PRAGMA
  143. #pragma alloc_text(INIT,DriverEntry)
  144. #endif
  145. NTSTATUS
  146. DriverEntry(
  147. IN PDRIVER_OBJECT DriverObject,
  148. IN PUNICODE_STRING RegistryPath
  149. )
  150. /*++
  151. Routine Description:
  152. This routine performs initialization of the NetBIOS Frames Protocol
  153. transport driver. It creates the device objects for the transport
  154. provider and performs other driver initialization.
  155. Arguments:
  156. DriverObject - Pointer to driver object created by the system.
  157. RegistryPath - The name of NBF's node in the registry.
  158. Return Value:
  159. The function value is the final status from the initialization operation.
  160. --*/
  161. {
  162. ULONG j;
  163. UNICODE_STRING nameString;
  164. NTSTATUS status;
  165. ASSERT (sizeof (SHORT) == 2);
  166. #ifdef MEMPRINT
  167. MemPrintInitialize ();
  168. #endif
  169. #ifdef NBF_LOCKS
  170. KeInitializeSpinLock( &NbfGlobalLock );
  171. #endif
  172. #if DBG
  173. InitializeListHead (&NbfGlobalRequestList);
  174. InitializeListHead (&NbfGlobalLinkList);
  175. InitializeListHead (&NbfGlobalConnectionList);
  176. KeInitializeSpinLock (&NbfGlobalInterlock);
  177. KeInitializeSpinLock (&NbfGlobalHistoryLock);
  178. #endif
  179. NbfRegistryPath = *RegistryPath;
  180. NbfRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
  181. RegistryPath->MaximumLength,
  182. NBF_MEM_TAG_REGISTRY_PATH);
  183. if (NbfRegistryPath.Buffer == NULL) {
  184. PANIC(" Failed to allocate Registry Path!\n");
  185. return(STATUS_INSUFFICIENT_RESOURCES);
  186. }
  187. RtlCopyMemory(NbfRegistryPath.Buffer, RegistryPath->Buffer,
  188. RegistryPath->MaximumLength);
  189. NbfDriverObject = DriverObject;
  190. RtlInitUnicodeString( &nameString, NBF_NAME);
  191. //
  192. // Initialize the driver object with this driver's entry points.
  193. //
  194. DriverObject->MajorFunction [IRP_MJ_CREATE] = NbfDispatchOpenClose;
  195. DriverObject->MajorFunction [IRP_MJ_CLOSE] = NbfDispatchOpenClose;
  196. DriverObject->MajorFunction [IRP_MJ_CLEANUP] = NbfDispatchOpenClose;
  197. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = NbfDispatchInternal;
  198. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = NbfDispatch;
  199. DriverObject->MajorFunction [IRP_MJ_PNP_POWER] = NbfDispatch;
  200. DriverObject->DriverUnload = NbfUnload;
  201. //
  202. // Initialize the global list of devices.
  203. // & the lock guarding this global list
  204. //
  205. InitializeListHead (&NbfDeviceList);
  206. ExInitializeFastMutex (&NbfDevicesLock);
  207. TdiInitialize();
  208. status = NbfRegisterProtocol (&nameString);
  209. if (!NT_SUCCESS (status)) {
  210. //
  211. // No configuration info read at startup when using PNP
  212. //
  213. ExFreePool(NbfRegistryPath.Buffer);
  214. PANIC ("NbfInitialize: RegisterProtocol with NDIS failed!\n");
  215. NbfWriteGeneralErrorLog(
  216. (PVOID)DriverObject,
  217. EVENT_TRANSPORT_REGISTER_FAILED,
  218. 607,
  219. status,
  220. NULL,
  221. 0,
  222. NULL);
  223. return STATUS_INSUFFICIENT_RESOURCES;
  224. }
  225. RtlInitUnicodeString( &nameString, NBF_DEVICE_NAME);
  226. //
  227. // Register as a provider with TDI
  228. //
  229. status = TdiRegisterProvider(
  230. &nameString,
  231. &NbfProviderHandle);
  232. if (!NT_SUCCESS (status)) {
  233. //
  234. // Deregister with the NDIS layer as TDI registration failed
  235. //
  236. NbfDeregisterProtocol();
  237. ExFreePool(NbfRegistryPath.Buffer);
  238. PANIC ("NbfInitialize: RegisterProtocol with TDI failed!\n");
  239. NbfWriteGeneralErrorLog(
  240. (PVOID)DriverObject,
  241. EVENT_TRANSPORT_REGISTER_FAILED,
  242. 607,
  243. status,
  244. NULL,
  245. 0,
  246. NULL);
  247. return STATUS_INSUFFICIENT_RESOURCES;
  248. }
  249. return(status);
  250. }
  251. VOID
  252. NbfUnload(
  253. IN PDRIVER_OBJECT DriverObject
  254. )
  255. /*++
  256. Routine Description:
  257. This routine unloads the NetBIOS Frames Protocol transport driver.
  258. It unbinds from any NDIS drivers that are open and frees all resources
  259. associated with the transport. The I/O system will not call us until
  260. nobody above has NBF open.
  261. Arguments:
  262. DriverObject - Pointer to driver object created by the system.
  263. Return Value:
  264. None. When the function returns, the driver is unloaded.
  265. --*/
  266. {
  267. PDEVICE_CONTEXT DeviceContext;
  268. PLIST_ENTRY p;
  269. KIRQL oldIrql;
  270. UNREFERENCED_PARAMETER (DriverObject);
  271. IF_NBFDBG (NBF_DEBUG_PNP) {
  272. NbfPrint0 ("ENTER NbfUnload\n");
  273. }
  274. /*
  275. #ifdef RASAUTODIAL
  276. //
  277. // Unbind from the automatic connection driver.
  278. //
  279. #if DBG
  280. DbgPrint("Calling NbfAcdUnbind()\n");
  281. #endif
  282. NbfAcdUnbind();
  283. #endif // RASAUTODIAL
  284. */
  285. //
  286. // Walk the list of device contexts.
  287. //
  288. ACQUIRE_DEVICES_LIST_LOCK();
  289. while (!IsListEmpty (&NbfDeviceList)) {
  290. // Remove an entry from list and reset its
  291. // links (as we might try to remove from
  292. // the list again - when ref goes to zero)
  293. p = RemoveHeadList (&NbfDeviceList);
  294. InitializeListHead(p);
  295. DeviceContext = CONTAINING_RECORD (p, DEVICE_CONTEXT, Linkage);
  296. DeviceContext->State = DEVICECONTEXT_STATE_STOPPING;
  297. // Remove creation ref if it has not already been removed
  298. if (InterlockedExchange(&DeviceContext->CreateRefRemoved, TRUE) == FALSE) {
  299. RELEASE_DEVICES_LIST_LOCK();
  300. // Stop all internal timers
  301. NbfStopTimerSystem(DeviceContext);
  302. // Remove creation reference
  303. NbfDereferenceDeviceContext ("Unload", DeviceContext, DCREF_CREATION);
  304. ACQUIRE_DEVICES_LIST_LOCK();
  305. }
  306. }
  307. RELEASE_DEVICES_LIST_LOCK();
  308. //
  309. // Deregister from TDI layer as a network provider
  310. //
  311. TdiDeregisterProvider(NbfProviderHandle);
  312. //
  313. // Then remove ourselves as an NDIS protocol.
  314. //
  315. NbfDeregisterProtocol();
  316. //
  317. // Finally free any memory allocated for config info
  318. //
  319. if (NbfConfig != NULL) {
  320. // Free configuration block
  321. NbfFreeConfigurationInfo(NbfConfig);
  322. #if DBG
  323. // Free debugging tables
  324. ExFreePool(NbfConnectionTable);
  325. #endif
  326. }
  327. //
  328. // Free memory allocated in DriverEntry for reg path
  329. //
  330. ExFreePool(NbfRegistryPath.Buffer);
  331. IF_NBFDBG (NBF_DEBUG_PNP) {
  332. NbfPrint0 ("LEAVE NbfUnload\n");
  333. }
  334. return;
  335. }
  336. VOID
  337. NbfFreeResources (
  338. IN PDEVICE_CONTEXT DeviceContext
  339. )
  340. /*++
  341. Routine Description:
  342. This routine is called by NBF to clean up the data structures associated
  343. with a given DeviceContext. When this routine exits, the DeviceContext
  344. should be deleted as it no longer has any assocaited resources.
  345. Arguments:
  346. DeviceContext - Pointer to the DeviceContext we wish to clean up.
  347. Return Value:
  348. None.
  349. --*/
  350. {
  351. PLIST_ENTRY p;
  352. PSINGLE_LIST_ENTRY s;
  353. PTP_PACKET packet;
  354. PTP_UI_FRAME uiFrame;
  355. PTP_ADDRESS address;
  356. PTP_CONNECTION connection;
  357. PTP_REQUEST request;
  358. PTP_LINK link;
  359. PTP_ADDRESS_FILE addressFile;
  360. PNDIS_PACKET ndisPacket;
  361. PBUFFER_TAG BufferTag;
  362. KIRQL oldirql;
  363. PNBF_POOL_LIST_DESC PacketPoolDescCurr;
  364. PNBF_POOL_LIST_DESC PacketPoolDescNext;
  365. //
  366. // Clean up I-frame packet pool.
  367. //
  368. while ( DeviceContext->PacketPool.Next != NULL ) {
  369. s = PopEntryList( &DeviceContext->PacketPool );
  370. packet = CONTAINING_RECORD( s, TP_PACKET, Linkage );
  371. NbfDeallocateSendPacket (DeviceContext, packet);
  372. }
  373. //
  374. // Clean up RR-frame packet pool.
  375. //
  376. while ( DeviceContext->RrPacketPool.Next != NULL ) {
  377. s = PopEntryList( &DeviceContext->RrPacketPool );
  378. packet = CONTAINING_RECORD( s, TP_PACKET, Linkage );
  379. NbfDeallocateSendPacket (DeviceContext, packet);
  380. }
  381. //
  382. // Clean up UI frame pool.
  383. //
  384. while ( !IsListEmpty( &DeviceContext->UIFramePool ) ) {
  385. p = RemoveHeadList( &DeviceContext->UIFramePool );
  386. uiFrame = CONTAINING_RECORD (p, TP_UI_FRAME, Linkage );
  387. NbfDeallocateUIFrame (DeviceContext, uiFrame);
  388. }
  389. //
  390. // Clean up address pool.
  391. //
  392. while ( !IsListEmpty (&DeviceContext->AddressPool) ) {
  393. p = RemoveHeadList (&DeviceContext->AddressPool);
  394. address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  395. NbfDeallocateAddress (DeviceContext, address);
  396. }
  397. //
  398. // Clean up address file pool.
  399. //
  400. while ( !IsListEmpty (&DeviceContext->AddressFilePool) ) {
  401. p = RemoveHeadList (&DeviceContext->AddressFilePool);
  402. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  403. NbfDeallocateAddressFile (DeviceContext, addressFile);
  404. }
  405. //
  406. // Clean up connection pool.
  407. //
  408. while ( !IsListEmpty (&DeviceContext->ConnectionPool) ) {
  409. p = RemoveHeadList (&DeviceContext->ConnectionPool);
  410. connection = CONTAINING_RECORD (p, TP_CONNECTION, LinkList);
  411. NbfDeallocateConnection (DeviceContext, connection);
  412. }
  413. //
  414. // Clean up link pool.
  415. //
  416. while ( !IsListEmpty (&DeviceContext->LinkPool) ) {
  417. p = RemoveHeadList (&DeviceContext->LinkPool);
  418. link = CONTAINING_RECORD (p, TP_LINK, Linkage);
  419. NbfDeallocateLink (DeviceContext, link);
  420. }
  421. //
  422. // Clean up request pool.
  423. //
  424. while ( !IsListEmpty( &DeviceContext->RequestPool ) ) {
  425. p = RemoveHeadList( &DeviceContext->RequestPool );
  426. request = CONTAINING_RECORD (p, TP_REQUEST, Linkage );
  427. NbfDeallocateRequest (DeviceContext, request);
  428. }
  429. //
  430. // Clean up receive packet pool
  431. //
  432. while ( DeviceContext->ReceivePacketPool.Next != NULL) {
  433. s = PopEntryList (&DeviceContext->ReceivePacketPool);
  434. //
  435. // HACK: This works because Linkage is the first field in
  436. // ProtocolReserved for a receive packet.
  437. //
  438. ndisPacket = CONTAINING_RECORD (s, NDIS_PACKET, ProtocolReserved[0]);
  439. NbfDeallocateReceivePacket (DeviceContext, ndisPacket);
  440. }
  441. //
  442. // Clean up receive buffer pool.
  443. //
  444. while ( DeviceContext->ReceiveBufferPool.Next != NULL ) {
  445. s = PopEntryList( &DeviceContext->ReceiveBufferPool );
  446. BufferTag = CONTAINING_RECORD (s, BUFFER_TAG, Linkage );
  447. NbfDeallocateReceiveBuffer (DeviceContext, BufferTag);
  448. }
  449. //
  450. // Now clean up all NDIS resources -
  451. // packet pools, buffers and such
  452. //
  453. //
  454. // Cleanup list of send packet pools
  455. //
  456. if (DeviceContext->SendPacketPoolDesc != NULL) {
  457. ACQUIRE_SPIN_LOCK (&DeviceContext->SendPoolListLock, &oldirql);
  458. for (PacketPoolDescCurr = DeviceContext->SendPacketPoolDesc;
  459. PacketPoolDescCurr != NULL; ) {
  460. if (PacketPoolDescCurr->PoolHandle != NULL) {
  461. NdisFreePacketPool (PacketPoolDescCurr->PoolHandle);
  462. DeviceContext->MemoryUsage -=
  463. (PacketPoolDescCurr->TotalElements * (sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG)));
  464. }
  465. PacketPoolDescNext = PacketPoolDescCurr->Next;
  466. ExFreePool(PacketPoolDescCurr);
  467. PacketPoolDescCurr = PacketPoolDescNext;
  468. }
  469. DeviceContext->SendPacketPoolDesc = NULL;
  470. DeviceContext->SendPacketPoolSize = 0;
  471. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  472. }
  473. //
  474. // Cleanup list of receive packet pools
  475. //
  476. if (DeviceContext->ReceivePacketPoolDesc != NULL) {
  477. ACQUIRE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, &oldirql);
  478. for (PacketPoolDescCurr = DeviceContext->ReceivePacketPoolDesc;
  479. PacketPoolDescCurr != NULL; ) {
  480. if (PacketPoolDescCurr->PoolHandle != NULL) {
  481. NdisFreePacketPool (PacketPoolDescCurr->PoolHandle);
  482. DeviceContext->MemoryUsage -=
  483. (PacketPoolDescCurr->TotalElements * (sizeof(NDIS_PACKET) + sizeof(RECEIVE_PACKET_TAG)));
  484. }
  485. PacketPoolDescNext = PacketPoolDescCurr->Next;
  486. ExFreePool(PacketPoolDescCurr);
  487. PacketPoolDescCurr = PacketPoolDescNext;
  488. }
  489. DeviceContext->ReceivePacketPoolDesc = NULL;
  490. DeviceContext->ReceivePacketPoolSize = 0;
  491. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  492. }
  493. //
  494. // Cleanup list of ndis buffers
  495. //
  496. if (DeviceContext->NdisBufferPool != NULL) {
  497. NdisFreeBufferPool (DeviceContext->NdisBufferPool);
  498. DeviceContext->NdisBufferPool = NULL;
  499. }
  500. return;
  501. } /* NbfFreeResources */
  502. NTSTATUS
  503. NbfDispatch(
  504. IN PDEVICE_OBJECT DeviceObject,
  505. IN PIRP Irp
  506. )
  507. /*++
  508. Routine Description:
  509. This routine is the main dispatch routine for the NBF device driver.
  510. It accepts an I/O Request Packet, performs the request, and then
  511. returns with the appropriate status.
  512. Arguments:
  513. DeviceObject - Pointer to the device object for this driver.
  514. Irp - Pointer to the request packet representing the I/O request.
  515. Return Value:
  516. The function value is the status of the operation.
  517. --*/
  518. {
  519. BOOL DeviceControlIrp = FALSE;
  520. NTSTATUS Status;
  521. PIO_STACK_LOCATION IrpSp;
  522. PDEVICE_CONTEXT DeviceContext;
  523. ENTER_NBF;
  524. //
  525. // Check to see if NBF has been initialized; if not, don't allow any use.
  526. // Note that this only covers any user mode code use; kernel TDI clients
  527. // will fail on their creation of an endpoint.
  528. //
  529. try {
  530. DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
  531. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  532. LEAVE_NBF;
  533. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  534. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  535. return STATUS_INVALID_DEVICE_STATE;
  536. }
  537. // Reference the device so that it does not go away from under us
  538. NbfReferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  539. } except(EXCEPTION_EXECUTE_HANDLER) {
  540. LEAVE_NBF;
  541. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  542. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  543. return STATUS_DEVICE_DOES_NOT_EXIST;
  544. }
  545. //
  546. // Make sure status information is consistent every time.
  547. //
  548. IoMarkIrpPending (Irp);
  549. Irp->IoStatus.Status = STATUS_PENDING;
  550. Irp->IoStatus.Information = 0;
  551. //
  552. // Get a pointer to the current stack location in the IRP. This is where
  553. // the function codes and parameters are stored.
  554. //
  555. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  556. //
  557. // Case on the function that is being performed by the requestor. If the
  558. // operation is a valid one for this device, then make it look like it was
  559. // successfully completed, where possible.
  560. //
  561. switch (IrpSp->MajorFunction) {
  562. case IRP_MJ_DEVICE_CONTROL:
  563. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  564. NbfPrint0 ("NbfDispatch: IRP_MJ_DEVICE_CONTROL.\n");
  565. }
  566. DeviceControlIrp = TRUE;
  567. Status = NbfDeviceControl (DeviceObject, Irp, IrpSp);
  568. break;
  569. case IRP_MJ_PNP:
  570. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  571. NbfPrint0 ("NbfDispatch: IRP_MJ_PNP.\n");
  572. }
  573. Status = NbfDispatchPnPPower (DeviceObject, Irp, IrpSp);
  574. break;
  575. default:
  576. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  577. NbfPrint0 ("NbfDispatch: OTHER (DEFAULT).\n");
  578. }
  579. Status = STATUS_INVALID_DEVICE_REQUEST;
  580. } /* major function switch */
  581. if (Status == STATUS_PENDING) {
  582. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  583. NbfPrint0 ("NbfDispatch: request PENDING from handler.\n");
  584. }
  585. } else {
  586. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  587. NbfPrint0 ("NbfDispatch: request COMPLETED by handler.\n");
  588. }
  589. //
  590. // NbfDeviceControl would have completed this IRP already
  591. //
  592. if (!DeviceControlIrp)
  593. {
  594. LEAVE_NBF;
  595. IrpSp->Control &= ~SL_PENDING_RETURNED;
  596. Irp->IoStatus.Status = Status;
  597. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  598. ENTER_NBF;
  599. }
  600. }
  601. // Remove the temp use reference on device context added above
  602. NbfDereferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  603. //
  604. // Return the immediate status code to the caller.
  605. //
  606. LEAVE_NBF;
  607. return Status;
  608. } /* NbfDispatch */
  609. NTSTATUS
  610. NbfDispatchOpenClose(
  611. IN PDEVICE_OBJECT DeviceObject,
  612. IN PIRP Irp
  613. )
  614. /*++
  615. Routine Description:
  616. This routine is the main dispatch routine for the NBF device driver.
  617. It accepts an I/O Request Packet, performs the request, and then
  618. returns with the appropriate status.
  619. Arguments:
  620. DeviceObject - Pointer to the device object for this driver.
  621. Irp - Pointer to the request packet representing the I/O request.
  622. Return Value:
  623. The function value is the status of the operation.
  624. --*/
  625. {
  626. KIRQL oldirql;
  627. PDEVICE_CONTEXT DeviceContext;
  628. NTSTATUS Status = STATUS_SUCCESS;
  629. PIO_STACK_LOCATION IrpSp;
  630. PFILE_FULL_EA_INFORMATION openType;
  631. USHORT i;
  632. BOOLEAN found;
  633. PTP_ADDRESS_FILE AddressFile;
  634. PTP_CONNECTION Connection;
  635. ENTER_NBF;
  636. //
  637. // Check to see if NBF has been initialized; if not, don't allow any use.
  638. // Note that this only covers any user mode code use; kernel TDI clients
  639. // will fail on their creation of an endpoint.
  640. //
  641. try {
  642. DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
  643. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  644. LEAVE_NBF;
  645. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  646. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  647. return STATUS_INVALID_DEVICE_STATE;
  648. }
  649. // Reference the device so that it does not go away from under us
  650. NbfReferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  651. } except(EXCEPTION_EXECUTE_HANDLER) {
  652. LEAVE_NBF;
  653. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  654. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  655. return STATUS_DEVICE_DOES_NOT_EXIST;
  656. }
  657. //
  658. // Make sure status information is consistent every time.
  659. //
  660. IoMarkIrpPending (Irp);
  661. Irp->IoStatus.Status = STATUS_PENDING;
  662. Irp->IoStatus.Information = 0;
  663. //
  664. // Get a pointer to the current stack location in the IRP. This is where
  665. // the function codes and parameters are stored.
  666. //
  667. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  668. //
  669. // Case on the function that is being performed by the requestor. If the
  670. // operation is a valid one for this device, then make it look like it was
  671. // successfully completed, where possible.
  672. //
  673. switch (IrpSp->MajorFunction) {
  674. //
  675. // The Create function opens a transport object (either address or
  676. // connection). Access checking is performed on the specified
  677. // address to ensure security of transport-layer addresses.
  678. //
  679. case IRP_MJ_CREATE:
  680. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  681. NbfPrint0 ("NbfDispatch: IRP_MJ_CREATE.\n");
  682. }
  683. openType =
  684. (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  685. if (openType != NULL) {
  686. //
  687. // Address?
  688. //
  689. found = TRUE;
  690. if ((USHORT)openType->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) {
  691. for (i = 0; i < TDI_TRANSPORT_ADDRESS_LENGTH; i++) {
  692. if (openType->EaName[i] != TdiTransportAddress[i]) {
  693. found = FALSE;
  694. break;
  695. }
  696. }
  697. }
  698. else {
  699. found = FALSE;
  700. }
  701. if (found) {
  702. Status = NbfOpenAddress (DeviceObject, Irp, IrpSp);
  703. break;
  704. }
  705. //
  706. // Connection?
  707. //
  708. found = TRUE;
  709. if ((USHORT)openType->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) {
  710. for (i = 0; i < TDI_CONNECTION_CONTEXT_LENGTH; i++) {
  711. if (openType->EaName[i] != TdiConnectionContext[i]) {
  712. found = FALSE;
  713. break;
  714. }
  715. }
  716. }
  717. else {
  718. found = FALSE;
  719. }
  720. if (found) {
  721. Status = NbfOpenConnection (DeviceObject, Irp, IrpSp);
  722. break;
  723. }
  724. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  725. NbfPrint2 ("NbfDispatchOpenClose: IRP_MJ_CREATE on invalid type, len: %3d, name: %s\n",
  726. (USHORT)openType->EaNameLength, openType->EaName);
  727. }
  728. } else {
  729. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  730. NbfPrint0 ("NbfDispatchOpenClose: IRP_MJ_CREATE on control channel!\n");
  731. }
  732. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  733. IrpSp->FileObject->FsContext = (PVOID)(DeviceContext->ControlChannelIdentifier);
  734. ++DeviceContext->ControlChannelIdentifier;
  735. if (DeviceContext->ControlChannelIdentifier == 0) {
  736. DeviceContext->ControlChannelIdentifier = 1;
  737. }
  738. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  739. IrpSp->FileObject->FsContext2 = UlongToPtr(NBF_FILE_TYPE_CONTROL);
  740. Status = STATUS_SUCCESS;
  741. }
  742. break;
  743. case IRP_MJ_CLOSE:
  744. //
  745. // The Close function closes a transport endpoint, terminates
  746. // all outstanding transport activity on the endpoint, and unbinds
  747. // the endpoint from its transport address, if any. If this
  748. // is the last transport endpoint bound to the address, then
  749. // the address is removed from the provider.
  750. //
  751. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  752. NbfPrint0 ("NbfDispatch: IRP_MJ_CLOSE.\n");
  753. }
  754. switch (PtrToUlong(IrpSp->FileObject->FsContext2)) {
  755. case TDI_TRANSPORT_ADDRESS_FILE:
  756. AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext;
  757. //
  758. // This creates a reference to AddressFile->Address
  759. // which is removed by NbfCloseAddress.
  760. //
  761. Status = NbfVerifyAddressObject(AddressFile);
  762. if (!NT_SUCCESS (Status)) {
  763. Status = STATUS_INVALID_HANDLE;
  764. } else {
  765. Status = NbfCloseAddress (DeviceObject, Irp, IrpSp);
  766. }
  767. break;
  768. case TDI_CONNECTION_FILE:
  769. //
  770. // This is a connection
  771. //
  772. Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext;
  773. Status = NbfVerifyConnectionObject (Connection);
  774. if (NT_SUCCESS (Status)) {
  775. Status = NbfCloseConnection (DeviceObject, Irp, IrpSp);
  776. NbfDereferenceConnection ("Temporary Use",Connection, CREF_BY_ID);
  777. }
  778. break;
  779. case NBF_FILE_TYPE_CONTROL:
  780. //
  781. // this always succeeds
  782. //
  783. Status = STATUS_SUCCESS;
  784. break;
  785. default:
  786. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  787. NbfPrint1 ("NbfDispatch: IRP_MJ_CLOSE on unknown file type %lx.\n",
  788. IrpSp->FileObject->FsContext2);
  789. }
  790. Status = STATUS_INVALID_HANDLE;
  791. }
  792. break;
  793. case IRP_MJ_CLEANUP:
  794. //
  795. // Handle the two stage IRP for a file close operation. When the first
  796. // stage hits, run down all activity on the object of interest. This
  797. // do everything to it but remove the creation hold. Then, when the
  798. // CLOSE irp hits, actually close the object.
  799. //
  800. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  801. NbfPrint0 ("NbfDispatch: IRP_MJ_CLEANUP.\n");
  802. }
  803. switch (PtrToUlong(IrpSp->FileObject->FsContext2)) {
  804. case TDI_TRANSPORT_ADDRESS_FILE:
  805. AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext;
  806. Status = NbfVerifyAddressObject(AddressFile);
  807. if (!NT_SUCCESS (Status)) {
  808. Status = STATUS_INVALID_HANDLE;
  809. } else {
  810. NbfStopAddressFile (AddressFile, AddressFile->Address);
  811. NbfDereferenceAddress ("IRP_MJ_CLEANUP", AddressFile->Address, AREF_VERIFY);
  812. Status = STATUS_SUCCESS;
  813. }
  814. break;
  815. case TDI_CONNECTION_FILE:
  816. Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext;
  817. Status = NbfVerifyConnectionObject (Connection);
  818. if (NT_SUCCESS (Status)) {
  819. KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
  820. NbfStopConnection (Connection, STATUS_LOCAL_DISCONNECT);
  821. KeLowerIrql (oldirql);
  822. Status = STATUS_SUCCESS;
  823. NbfDereferenceConnection ("Temporary Use",Connection, CREF_BY_ID);
  824. }
  825. break;
  826. case NBF_FILE_TYPE_CONTROL:
  827. NbfStopControlChannel(
  828. (PDEVICE_CONTEXT)DeviceObject,
  829. (USHORT)IrpSp->FileObject->FsContext
  830. );
  831. Status = STATUS_SUCCESS;
  832. break;
  833. default:
  834. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  835. NbfPrint1 ("NbfDispatch: IRP_MJ_CLEANUP on unknown file type %lx.\n",
  836. IrpSp->FileObject->FsContext2);
  837. }
  838. Status = STATUS_INVALID_HANDLE;
  839. }
  840. break;
  841. default:
  842. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  843. NbfPrint0 ("NbfDispatch: OTHER (DEFAULT).\n");
  844. }
  845. Status = STATUS_INVALID_DEVICE_REQUEST;
  846. } /* major function switch */
  847. if (Status == STATUS_PENDING) {
  848. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  849. NbfPrint0 ("NbfDispatch: request PENDING from handler.\n");
  850. }
  851. } else {
  852. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  853. NbfPrint0 ("NbfDispatch: request COMPLETED by handler.\n");
  854. }
  855. LEAVE_NBF;
  856. IrpSp->Control &= ~SL_PENDING_RETURNED;
  857. Irp->IoStatus.Status = Status;
  858. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  859. ENTER_NBF;
  860. }
  861. // Remove the temp use reference on device context added above
  862. NbfDereferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  863. //
  864. // Return the immediate status code to the caller.
  865. //
  866. LEAVE_NBF;
  867. return Status;
  868. } /* NbfDispatchOpenClose */
  869. NTSTATUS
  870. NbfDeviceControl(
  871. IN PDEVICE_OBJECT DeviceObject,
  872. IN PIRP Irp,
  873. IN PIO_STACK_LOCATION IrpSp
  874. )
  875. /*++
  876. Routine Description:
  877. This routine dispatches TDI request types to different handlers based
  878. on the minor IOCTL function code in the IRP's current stack location.
  879. In addition to cracking the minor function code, this routine also
  880. reaches into the IRP and passes the packetized parameters stored there
  881. as parameters to the various TDI request handlers so that they are
  882. not IRP-dependent.
  883. Arguments:
  884. DeviceObject - Pointer to the device object for this driver.
  885. Irp - Pointer to the request packet representing the I/O request.
  886. IrpSp - Pointer to current IRP stack frame.
  887. Return Value:
  888. The function value is the status of the operation.
  889. --*/
  890. {
  891. BOOL InternalIrp = FALSE;
  892. NTSTATUS Status;
  893. PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
  894. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  895. NbfPrint0 ("NbfDeviceControl: Entered.\n");
  896. }
  897. //
  898. // Branch to the appropriate request handler. Preliminary checking of
  899. // the size of the request block is performed here so that it is known
  900. // in the handlers that the minimum input parameters are readable. It
  901. // is *not* determined here whether variable length input fields are
  902. // passed correctly;this is a check which must be made within each routine.
  903. //
  904. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  905. #if MAGIC
  906. case IOCTL_TDI_MAGIC_BULLET:
  907. //
  908. // Special: send the magic bullet (to trigger the Sniffer).
  909. //
  910. NbfPrint1 ("NBF: Sending user MagicBullet on %lx\n", DeviceContext);
  911. {
  912. extern VOID NbfSendMagicBullet (PDEVICE_CONTEXT, PTP_LINK);
  913. NbfSendMagicBullet (DeviceContext, NULL);
  914. }
  915. if (IrpSp->Parameters.DeviceIoControl.Type3InputBuffer != NULL) {
  916. NbfPrint0 ("NBF: DbgBreakPoint after MagicBullet\n");
  917. DbgBreakPoint();
  918. }
  919. Status = STATUS_SUCCESS;
  920. break;
  921. #endif
  922. #if DBG
  923. case IOCTL_TDI_SEND_TEST:
  924. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  925. NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start send side test\n");
  926. }
  927. (VOID) KeSetEvent( &TdiSendEvent, 0, FALSE );
  928. break;
  929. case IOCTL_TDI_RECEIVE_TEST:
  930. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  931. NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start receive side test\n");
  932. }
  933. (VOID) KeSetEvent( &TdiReceiveEvent, 0, FALSE );
  934. break;
  935. case IOCTL_TDI_SERVER_TEST:
  936. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  937. NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start receive side test\n");
  938. }
  939. (VOID) KeSetEvent( &TdiServerEvent, 0, FALSE );
  940. break;
  941. #endif
  942. default:
  943. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  944. NbfPrint0 ("NbfDeviceControl: invalid request type.\n");
  945. }
  946. //
  947. // Convert the user call to the proper internal device call.
  948. //
  949. Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp);
  950. if (Status == STATUS_SUCCESS) {
  951. //
  952. // If TdiMapUserRequest returns SUCCESS then the IRP
  953. // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL
  954. // IRP, so we dispatch it as usual. The IRP will be
  955. // completed by this call to NbfDispatchInternal, so we dont
  956. //
  957. InternalIrp = TRUE;
  958. Status = NbfDispatchInternal (DeviceObject, Irp);
  959. }
  960. }
  961. //
  962. // If this IRP got converted to an internal IRP,
  963. // it will be completed by NbfDispatchInternal.
  964. //
  965. if ((!InternalIrp) && (Status != STATUS_PENDING))
  966. {
  967. LEAVE_NBF;
  968. IrpSp->Control &= ~SL_PENDING_RETURNED;
  969. Irp->IoStatus.Status = Status;
  970. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  971. ENTER_NBF;
  972. }
  973. return Status;
  974. } /* NbfDeviceControl */
  975. NTSTATUS
  976. NbfDispatchPnPPower(
  977. IN PDEVICE_OBJECT DeviceObject,
  978. IN PIRP Irp,
  979. IN PIO_STACK_LOCATION IrpSp
  980. )
  981. /*++
  982. Routine Description:
  983. This routine dispatches PnP request types to different handlers based
  984. on the minor IOCTL function code in the IRP's current stack location.
  985. Arguments:
  986. DeviceObject - Pointer to the device object for this driver.
  987. Irp - Pointer to the request packet representing the I/O request.
  988. IrpSp - Pointer to current IRP stack frame.
  989. Return Value:
  990. The function value is the status of the operation.
  991. --*/
  992. {
  993. PDEVICE_RELATIONS DeviceRelations = NULL;
  994. PTP_CONNECTION Connection;
  995. PVOID PnPContext;
  996. NTSTATUS Status;
  997. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  998. NbfPrint0 ("NbfDispatchPnPPower: Entered.\n");
  999. }
  1000. Status = STATUS_INVALID_DEVICE_REQUEST;
  1001. switch (IrpSp->MinorFunction) {
  1002. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1003. if (IrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation){
  1004. switch (PtrToUlong(IrpSp->FileObject->FsContext2))
  1005. {
  1006. case TDI_CONNECTION_FILE:
  1007. // Get the connection object and verify
  1008. Connection = IrpSp->FileObject->FsContext;
  1009. //
  1010. // This adds a connection reference of type BY_ID if successful.
  1011. //
  1012. Status = NbfVerifyConnectionObject (Connection);
  1013. if (NT_SUCCESS (Status)) {
  1014. //
  1015. // Get the PDO associated with conn's device object
  1016. //
  1017. PnPContext = Connection->Provider->PnPContext;
  1018. if (PnPContext) {
  1019. DeviceRelations =
  1020. ExAllocatePoolWithTag(NonPagedPool,
  1021. sizeof(DEVICE_RELATIONS),
  1022. NBF_MEM_TAG_DEVICE_PDO);
  1023. if (DeviceRelations) {
  1024. //
  1025. // TargetDeviceRelation allows exactly 1 PDO. fill it.
  1026. //
  1027. DeviceRelations->Count = 1;
  1028. DeviceRelations->Objects[0] = PnPContext;
  1029. ObReferenceObject(PnPContext);
  1030. } else {
  1031. Status = STATUS_NO_MEMORY;
  1032. }
  1033. } else {
  1034. Status = STATUS_INVALID_DEVICE_STATE;
  1035. }
  1036. NbfDereferenceConnection ("Temp Rel", Connection, CREF_BY_ID);
  1037. }
  1038. break;
  1039. case TDI_TRANSPORT_ADDRESS_FILE:
  1040. Status = STATUS_UNSUCCESSFUL;
  1041. break;
  1042. }
  1043. }
  1044. }
  1045. //
  1046. // Invoker of this irp will free the information buffer.
  1047. //
  1048. Irp->IoStatus.Status = Status;
  1049. Irp->IoStatus.Information = (ULONG_PTR) DeviceRelations;
  1050. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1051. NbfPrint1 ("NbfDispatchPnPPower: exiting, status: %lx\n",Status);
  1052. }
  1053. return Status;
  1054. } /* NbfDispatchPnPPower */
  1055. NTSTATUS
  1056. NbfDispatchInternal (
  1057. IN PDEVICE_OBJECT DeviceObject,
  1058. IN PIRP Irp
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. This routine dispatches TDI request types to different handlers based
  1063. on the minor IOCTL function code in the IRP's current stack location.
  1064. In addition to cracking the minor function code, this routine also
  1065. reaches into the IRP and passes the packetized parameters stored there
  1066. as parameters to the various TDI request handlers so that they are
  1067. not IRP-dependent.
  1068. Arguments:
  1069. DeviceObject - Pointer to the device object for this driver.
  1070. Irp - Pointer to the request packet representing the I/O request.
  1071. Return Value:
  1072. The function value is the status of the operation.
  1073. --*/
  1074. {
  1075. NTSTATUS Status;
  1076. PDEVICE_CONTEXT DeviceContext;
  1077. PIO_STACK_LOCATION IrpSp;
  1078. #if DBG
  1079. KIRQL IrqlOnEnter = KeGetCurrentIrql();
  1080. #endif
  1081. ENTER_NBF;
  1082. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1083. NbfPrint0 ("NbfInternalDeviceControl: Entered.\n");
  1084. }
  1085. //
  1086. // Get a pointer to the current stack location in the IRP. This is where
  1087. // the function codes and parameters are stored.
  1088. //
  1089. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  1090. DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
  1091. try {
  1092. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  1093. LEAVE_NBF;
  1094. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  1095. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1096. return STATUS_INVALID_DEVICE_STATE;
  1097. }
  1098. // Reference the device so that it does not go away from under us
  1099. NbfReferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  1100. } except(EXCEPTION_EXECUTE_HANDLER) {
  1101. LEAVE_NBF;
  1102. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  1103. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1104. return STATUS_DEVICE_DOES_NOT_EXIST;
  1105. }
  1106. //
  1107. // Make sure status information is consistent every time.
  1108. //
  1109. IoMarkIrpPending (Irp);
  1110. Irp->IoStatus.Status = STATUS_PENDING;
  1111. Irp->IoStatus.Information = 0;
  1112. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1113. {
  1114. PULONG Temp=(PULONG)&IrpSp->Parameters;
  1115. NbfPrint5 ("Got IrpSp %lx %lx %lx %lx %lx\n", Temp++, Temp++,
  1116. Temp++, Temp++, Temp++);
  1117. }
  1118. }
  1119. //
  1120. // Branch to the appropriate request handler. Preliminary checking of
  1121. // the size of the request block is performed here so that it is known
  1122. // in the handlers that the minimum input parameters are readable. It
  1123. // is *not* determined here whether variable length input fields are
  1124. // passed correctly; this is a check which must be made within each routine.
  1125. //
  1126. switch (IrpSp->MinorFunction) {
  1127. case TDI_ACCEPT:
  1128. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1129. NbfPrint0 ("NbfDispatchInternal: TdiAccept request.\n");
  1130. }
  1131. Status = NbfTdiAccept (Irp);
  1132. break;
  1133. case TDI_ACTION:
  1134. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1135. NbfPrint0 ("NbfDispatchInternal: TdiAction request.\n");
  1136. }
  1137. Status = NbfTdiAction (DeviceContext, Irp);
  1138. break;
  1139. case TDI_ASSOCIATE_ADDRESS:
  1140. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1141. NbfPrint0 ("NbfDispatchInternal: TdiAccept request.\n");
  1142. }
  1143. Status = NbfTdiAssociateAddress (Irp);
  1144. break;
  1145. case TDI_DISASSOCIATE_ADDRESS:
  1146. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1147. NbfPrint0 ("NbfDispatchInternal: TdiDisassociateAddress request.\n");
  1148. }
  1149. Status = NbfTdiDisassociateAddress (Irp);
  1150. break;
  1151. case TDI_CONNECT:
  1152. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1153. NbfPrint0 ("NbfDispatchInternal: TdiConnect request\n");
  1154. }
  1155. Status = NbfTdiConnect (Irp);
  1156. break;
  1157. case TDI_DISCONNECT:
  1158. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1159. NbfPrint0 ("NbfDispatchInternal: TdiDisconnect request.\n");
  1160. }
  1161. Status = NbfTdiDisconnect (Irp);
  1162. break;
  1163. case TDI_LISTEN:
  1164. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1165. NbfPrint0 ("NbfDispatchInternal: TdiListen request.\n");
  1166. }
  1167. Status = NbfTdiListen (Irp);
  1168. break;
  1169. case TDI_QUERY_INFORMATION:
  1170. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1171. NbfPrint0 ("NbfDispatchInternal: TdiQueryInformation request.\n");
  1172. }
  1173. Status = NbfTdiQueryInformation (DeviceContext, Irp);
  1174. break;
  1175. case TDI_RECEIVE:
  1176. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1177. NbfPrint0 ("NbfDispatchInternal: TdiReceive request.\n");
  1178. }
  1179. Status = NbfTdiReceive (Irp);
  1180. break;
  1181. case TDI_RECEIVE_DATAGRAM:
  1182. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1183. NbfPrint0 ("NbfDispatchInternal: TdiReceiveDatagram request.\n");
  1184. }
  1185. Status = NbfTdiReceiveDatagram (Irp);
  1186. break;
  1187. case TDI_SEND:
  1188. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1189. NbfPrint0 ("NbfDispatchInternal: TdiSend request.\n");
  1190. }
  1191. Status = NbfTdiSend (Irp);
  1192. break;
  1193. case TDI_SEND_DATAGRAM:
  1194. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1195. NbfPrint0 ("NbfDispatchInternal: TdiSendDatagram request.\n");
  1196. }
  1197. Status = NbfTdiSendDatagram (Irp);
  1198. break;
  1199. case TDI_SET_EVENT_HANDLER:
  1200. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1201. NbfPrint0 ("NbfDispatchInternal: TdiSetEventHandler request.\n");
  1202. }
  1203. //
  1204. // Because this request will enable direct callouts from the
  1205. // transport provider at DISPATCH_LEVEL to a client-specified
  1206. // routine, this request is only valid in kernel mode, denying
  1207. // access to this request in user mode.
  1208. //
  1209. Status = NbfTdiSetEventHandler (Irp);
  1210. break;
  1211. case TDI_SET_INFORMATION:
  1212. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1213. NbfPrint0 ("NbfDispatchInternal: TdiSetInformation request.\n");
  1214. }
  1215. Status = NbfTdiSetInformation (Irp);
  1216. break;
  1217. #if DBG
  1218. case 0x7f:
  1219. //
  1220. // Special: send the magic bullet (to trigger the Sniffer).
  1221. //
  1222. NbfPrint1 ("NBF: Sending MagicBullet on %lx\n", DeviceContext);
  1223. {
  1224. extern VOID NbfSendMagicBullet (PDEVICE_CONTEXT, PTP_LINK);
  1225. NbfSendMagicBullet (DeviceContext, NULL);
  1226. }
  1227. Status = STATUS_SUCCESS;
  1228. break;
  1229. #endif
  1230. //
  1231. // Something we don't know about was submitted.
  1232. //
  1233. default:
  1234. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1235. NbfPrint1 ("NbfDispatchInternal: invalid request type %lx\n",
  1236. IrpSp->MinorFunction);
  1237. }
  1238. Status = STATUS_INVALID_DEVICE_REQUEST;
  1239. }
  1240. if (Status == STATUS_PENDING) {
  1241. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1242. NbfPrint0 ("NbfDispatchInternal: request PENDING from handler.\n");
  1243. }
  1244. } else {
  1245. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1246. NbfPrint0 ("NbfDispatchInternal: request COMPLETED by handler.\n");
  1247. }
  1248. LEAVE_NBF;
  1249. IrpSp->Control &= ~SL_PENDING_RETURNED;
  1250. Irp->IoStatus.Status = Status;
  1251. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1252. ENTER_NBF;
  1253. }
  1254. IF_NBFDBG (NBF_DEBUG_DISPATCH) {
  1255. NbfPrint1 ("NbfDispatchInternal: exiting, status: %lx\n",Status);
  1256. }
  1257. // Remove the temp use reference on device context added above
  1258. NbfDereferenceDeviceContext ("Temp Use Ref", DeviceContext, DCREF_TEMP_USE);
  1259. //
  1260. // Return the immediate status code to the caller.
  1261. //
  1262. LEAVE_NBF;
  1263. #if DBG
  1264. ASSERT (KeGetCurrentIrql() == IrqlOnEnter);
  1265. #endif
  1266. return Status;
  1267. } /* NbfDispatchInternal */
  1268. VOID
  1269. NbfWriteResourceErrorLog(
  1270. IN PDEVICE_CONTEXT DeviceContext,
  1271. IN NTSTATUS ErrorCode,
  1272. IN ULONG UniqueErrorValue,
  1273. IN ULONG BytesNeeded,
  1274. IN ULONG ResourceId
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. This routine allocates and writes an error log entry indicating
  1279. an out of resources condition. It will handle event codes
  1280. RESOURCE_POOL, RESOURCE_LIMIT, and RESOURCE_SPECIFIC.
  1281. Arguments:
  1282. DeviceContext - Pointer to the device context.
  1283. ErrorCode - The transport event code.
  1284. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  1285. packet.
  1286. BytesNeeded - If applicable, the number of bytes that could not
  1287. be allocated.
  1288. ResourceId - The resource ID of the allocated structure.
  1289. Return Value:
  1290. None.
  1291. --*/
  1292. {
  1293. PIO_ERROR_LOG_PACKET errorLogEntry;
  1294. UCHAR EntrySize;
  1295. PWSTR SecondString;
  1296. ULONG SecondStringSize;
  1297. PUCHAR StringLoc;
  1298. WCHAR ResourceIdBuffer[3];
  1299. WCHAR SizeBuffer[2];
  1300. WCHAR SpecificMaxBuffer[11];
  1301. ULONG SpecificMax;
  1302. INT i;
  1303. switch (ErrorCode) {
  1304. case EVENT_TRANSPORT_RESOURCE_POOL:
  1305. SecondString = NULL;
  1306. SecondStringSize = 0;
  1307. break;
  1308. case EVENT_TRANSPORT_RESOURCE_LIMIT:
  1309. SecondString = SizeBuffer;
  1310. SecondStringSize = sizeof(SizeBuffer);
  1311. switch (DeviceContext->MemoryLimit) {
  1312. case 100000: SizeBuffer[0] = L'1'; break;
  1313. case 250000: SizeBuffer[0] = L'2'; break;
  1314. case 0: SizeBuffer[0] = L'3'; break;
  1315. default: SizeBuffer[0] = L'0'; break;
  1316. }
  1317. SizeBuffer[1] = 0;
  1318. break;
  1319. case EVENT_TRANSPORT_RESOURCE_SPECIFIC:
  1320. switch (ResourceId) {
  1321. case UI_FRAME_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize; break;
  1322. case PACKET_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize; break;
  1323. case RECEIVE_PACKET_RESOURCE_ID: SpecificMax = DeviceContext->ReceivePacketPoolSize; break;
  1324. case RECEIVE_BUFFER_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize+DeviceContext->ReceivePacketPoolSize; break;
  1325. case ADDRESS_RESOURCE_ID: SpecificMax = DeviceContext->MaxAddresses; break;
  1326. case ADDRESS_FILE_RESOURCE_ID: SpecificMax = DeviceContext->MaxAddressFiles; break;
  1327. case CONNECTION_RESOURCE_ID: SpecificMax = DeviceContext->MaxConnections; break;
  1328. case LINK_RESOURCE_ID: SpecificMax = DeviceContext->MaxLinks; break;
  1329. case REQUEST_RESOURCE_ID: SpecificMax = DeviceContext->MaxRequests; break;
  1330. }
  1331. for (i=9; i>=0; i--) {
  1332. SpecificMaxBuffer[i] = (WCHAR)((SpecificMax % 10) + L'0');
  1333. SpecificMax /= 10;
  1334. if (SpecificMax == 0) {
  1335. break;
  1336. }
  1337. }
  1338. SecondString = SpecificMaxBuffer + i;
  1339. SecondStringSize = sizeof(SpecificMaxBuffer) - (i * sizeof(WCHAR));
  1340. SpecificMaxBuffer[10] = 0;
  1341. break;
  1342. default:
  1343. ASSERT (FALSE);
  1344. SecondString = NULL;
  1345. SecondStringSize = 0;
  1346. break;
  1347. }
  1348. EntrySize = (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  1349. DeviceContext->DeviceNameLength +
  1350. sizeof(ResourceIdBuffer) +
  1351. SecondStringSize);
  1352. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1353. (PDEVICE_OBJECT)DeviceContext,
  1354. EntrySize
  1355. );
  1356. //
  1357. // Convert the resource ID into a buffer.
  1358. //
  1359. ResourceIdBuffer[1] = (WCHAR)((ResourceId % 10) + L'0');
  1360. ResourceId /= 10;
  1361. ASSERT(ResourceId <= 9);
  1362. ResourceIdBuffer[0] = (WCHAR)((ResourceId % 10) + L'0');
  1363. ResourceIdBuffer[2] = 0;
  1364. if (errorLogEntry != NULL) {
  1365. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1366. errorLogEntry->RetryCount = (UCHAR)-1;
  1367. errorLogEntry->DumpDataSize = sizeof(ULONG);
  1368. errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 2 : 3;
  1369. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
  1370. errorLogEntry->EventCategory = 0;
  1371. errorLogEntry->ErrorCode = ErrorCode;
  1372. errorLogEntry->UniqueErrorValue = 0;
  1373. errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  1374. errorLogEntry->SequenceNumber = (ULONG)-1;
  1375. errorLogEntry->IoControlCode = 0;
  1376. errorLogEntry->DumpData[0] = BytesNeeded;
  1377. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1378. RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
  1379. StringLoc += DeviceContext->DeviceNameLength;
  1380. RtlCopyMemory (StringLoc, ResourceIdBuffer, sizeof(ResourceIdBuffer));
  1381. StringLoc += sizeof(ResourceIdBuffer);
  1382. if (SecondString) {
  1383. RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
  1384. }
  1385. IoWriteErrorLogEntry(errorLogEntry);
  1386. }
  1387. } /* NbfWriteResourceErrorLog */
  1388. VOID
  1389. NbfWriteGeneralErrorLog(
  1390. IN PDEVICE_CONTEXT DeviceContext,
  1391. IN NTSTATUS ErrorCode,
  1392. IN ULONG UniqueErrorValue,
  1393. IN NTSTATUS FinalStatus,
  1394. IN PWSTR SecondString,
  1395. IN ULONG DumpDataCount,
  1396. IN ULONG DumpData[]
  1397. )
  1398. /*++
  1399. Routine Description:
  1400. This routine allocates and writes an error log entry indicating
  1401. a general problem as indicated by the parameters. It handles
  1402. event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND,
  1403. TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these
  1404. events have messages with one or two strings in them.
  1405. Arguments:
  1406. DeviceContext - Pointer to the device context, or this may be
  1407. a driver object instead.
  1408. ErrorCode - The transport event code.
  1409. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  1410. packet.
  1411. FinalStatus - Used as the FinalStatus in the error log packet.
  1412. SecondString - If not NULL, the string to use as the %3
  1413. value in the error log packet.
  1414. DumpDataCount - The number of ULONGs of dump data.
  1415. DumpData - Dump data for the packet.
  1416. Return Value:
  1417. None.
  1418. --*/
  1419. {
  1420. PIO_ERROR_LOG_PACKET errorLogEntry;
  1421. UCHAR EntrySize;
  1422. ULONG SecondStringSize;
  1423. PUCHAR StringLoc;
  1424. PWSTR DriverName;
  1425. EntrySize = (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  1426. (DumpDataCount * sizeof(ULONG)));
  1427. if (DeviceContext->Type == IO_TYPE_DEVICE) {
  1428. EntrySize += (UCHAR)DeviceContext->DeviceNameLength;
  1429. } else {
  1430. DriverName = L"Nbf";
  1431. EntrySize += 4 * sizeof(WCHAR);
  1432. }
  1433. if (SecondString) {
  1434. SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
  1435. EntrySize += (UCHAR)SecondStringSize;
  1436. }
  1437. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1438. (PDEVICE_OBJECT)DeviceContext,
  1439. EntrySize
  1440. );
  1441. if (errorLogEntry != NULL) {
  1442. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1443. errorLogEntry->RetryCount = (UCHAR)-1;
  1444. errorLogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
  1445. errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2;
  1446. errorLogEntry->StringOffset =
  1447. (USHORT)(sizeof(IO_ERROR_LOG_PACKET) + ((DumpDataCount-1) * sizeof(ULONG)));
  1448. errorLogEntry->EventCategory = 0;
  1449. errorLogEntry->ErrorCode = ErrorCode;
  1450. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  1451. errorLogEntry->FinalStatus = FinalStatus;
  1452. errorLogEntry->SequenceNumber = (ULONG)-1;
  1453. errorLogEntry->IoControlCode = 0;
  1454. if (DumpDataCount) {
  1455. RtlCopyMemory(errorLogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
  1456. }
  1457. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1458. if (DeviceContext->Type == IO_TYPE_DEVICE) {
  1459. RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
  1460. StringLoc += DeviceContext->DeviceNameLength;
  1461. } else {
  1462. RtlCopyMemory (StringLoc, DriverName, 4 * sizeof(WCHAR));
  1463. StringLoc += 4 * sizeof(WCHAR);
  1464. }
  1465. if (SecondString) {
  1466. RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
  1467. }
  1468. IoWriteErrorLogEntry(errorLogEntry);
  1469. }
  1470. } /* NbfWriteGeneralErrorLog */
  1471. VOID
  1472. NbfWriteOidErrorLog(
  1473. IN PDEVICE_CONTEXT DeviceContext,
  1474. IN NTSTATUS ErrorCode,
  1475. IN NTSTATUS FinalStatus,
  1476. IN PWSTR AdapterString,
  1477. IN ULONG OidValue
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. This routine allocates and writes an error log entry indicating
  1482. a problem querying or setting an OID on an adapter. It handles
  1483. event codes SET_OID_FAILED and QUERY_OID_FAILED.
  1484. Arguments:
  1485. DeviceContext - Pointer to the device context.
  1486. ErrorCode - Used as the ErrorCode in the error log packet.
  1487. FinalStatus - Used as the FinalStatus in the error log packet.
  1488. AdapterString - The name of the adapter we were bound to.
  1489. OidValue - The OID which could not be set or queried.
  1490. Return Value:
  1491. None.
  1492. --*/
  1493. {
  1494. PIO_ERROR_LOG_PACKET errorLogEntry;
  1495. ULONG EntrySize;
  1496. PUCHAR StringLoc;
  1497. WCHAR OidBuffer[9];
  1498. INT i;
  1499. UINT CurrentDigit;
  1500. EntrySize = (sizeof(IO_ERROR_LOG_PACKET) -
  1501. sizeof(ULONG) +
  1502. DeviceContext->DeviceNameLength +
  1503. sizeof(OidBuffer));
  1504. if (EntrySize > ERROR_LOG_LIMIT_SIZE) {
  1505. return;
  1506. }
  1507. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1508. (PDEVICE_OBJECT)DeviceContext,
  1509. (UCHAR) EntrySize
  1510. );
  1511. //
  1512. // Convert the OID into a buffer.
  1513. //
  1514. for (i=7; i>=0; i--) {
  1515. CurrentDigit = OidValue & 0xf;
  1516. OidValue >>= 4;
  1517. if (CurrentDigit >= 0xa) {
  1518. OidBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A');
  1519. } else {
  1520. OidBuffer[i] = (WCHAR)(CurrentDigit + L'0');
  1521. }
  1522. }
  1523. OidBuffer[8] = 0;
  1524. if (errorLogEntry != NULL) {
  1525. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1526. errorLogEntry->RetryCount = (UCHAR)-1;
  1527. errorLogEntry->DumpDataSize = 0;
  1528. errorLogEntry->NumberOfStrings = 3;
  1529. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
  1530. errorLogEntry->EventCategory = 0;
  1531. errorLogEntry->ErrorCode = ErrorCode;
  1532. errorLogEntry->UniqueErrorValue = 0;
  1533. errorLogEntry->FinalStatus = FinalStatus;
  1534. errorLogEntry->SequenceNumber = (ULONG)-1;
  1535. errorLogEntry->IoControlCode = 0;
  1536. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1537. RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
  1538. StringLoc += DeviceContext->DeviceNameLength;
  1539. RtlCopyMemory (StringLoc, OidBuffer, sizeof(OidBuffer));
  1540. IoWriteErrorLogEntry(errorLogEntry);
  1541. }
  1542. } /* NbfWriteOidErrorLog */
  1543. ULONG
  1544. NbfInitializeOneDeviceContext(
  1545. OUT PNDIS_STATUS NdisStatus,
  1546. IN PDRIVER_OBJECT DriverObject,
  1547. IN PCONFIG_DATA NbfConfig,
  1548. IN PUNICODE_STRING BindName,
  1549. IN PUNICODE_STRING ExportName,
  1550. IN PVOID SystemSpecific1,
  1551. IN PVOID SystemSpecific2
  1552. )
  1553. /*++
  1554. Routine Description:
  1555. This routine creates and initializes one nbf device context. In order to
  1556. do this it must successfully open and bind to the adapter described by
  1557. nbfconfig->names[adapterindex].
  1558. Arguments:
  1559. NdisStatus - The outputted status of the operations.
  1560. DriverObject - the nbf driver object.
  1561. NbfConfig - the transport configuration information from the registry.
  1562. SystemSpecific1 - SystemSpecific1 argument to ProtocolBindAdapter
  1563. SystemSpecific2 - SystemSpecific2 argument to ProtocolBindAdapter
  1564. Return Value:
  1565. The number of successful binds.
  1566. --*/
  1567. {
  1568. ULONG i;
  1569. PDEVICE_CONTEXT DeviceContext;
  1570. PTP_REQUEST Request;
  1571. PTP_LINK Link;
  1572. PTP_CONNECTION Connection;
  1573. PTP_ADDRESS_FILE AddressFile;
  1574. PTP_ADDRESS Address;
  1575. PTP_UI_FRAME UIFrame;
  1576. PTP_PACKET Packet;
  1577. PNDIS_PACKET NdisPacket;
  1578. PRECEIVE_PACKET_TAG ReceiveTag;
  1579. PBUFFER_TAG BufferTag;
  1580. KIRQL oldIrql;
  1581. NTSTATUS status;
  1582. UINT MaxUserData;
  1583. ULONG InitReceivePackets;
  1584. BOOLEAN UniProcessor;
  1585. PDEVICE_OBJECT DeviceObject;
  1586. UNICODE_STRING DeviceString;
  1587. UCHAR PermAddr[sizeof(TA_ADDRESS)+TDI_ADDRESS_LENGTH_NETBIOS];
  1588. PTA_ADDRESS pAddress = (PTA_ADDRESS)PermAddr;
  1589. PTDI_ADDRESS_NETBIOS NetBIOSAddress =
  1590. (PTDI_ADDRESS_NETBIOS)pAddress->Address;
  1591. struct {
  1592. TDI_PNP_CONTEXT tdiPnPContextHeader;
  1593. PVOID tdiPnPContextTrailer;
  1594. } tdiPnPContext1, tdiPnPContext2;
  1595. pAddress->AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
  1596. pAddress->AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  1597. NetBIOSAddress->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  1598. //
  1599. // Determine if we are on a uniprocessor.
  1600. //
  1601. if (KeNumberProcessors == 1) {
  1602. UniProcessor = TRUE;
  1603. } else {
  1604. UniProcessor = FALSE;
  1605. }
  1606. //
  1607. // Loop through all the adapters that are in the configuration
  1608. // information structure. Allocate a device object for each
  1609. // one that we find.
  1610. //
  1611. status = NbfCreateDeviceContext(
  1612. DriverObject,
  1613. ExportName,
  1614. &DeviceContext
  1615. );
  1616. if (!NT_SUCCESS (status)) {
  1617. IF_NBFDBG (NBF_DEBUG_PNP) {
  1618. NbfPrint2 ("NbfCreateDeviceContext for %S returned error %08x\n",
  1619. ExportName->Buffer, status);
  1620. }
  1621. //
  1622. // First check if we already have an object with this name
  1623. // This is because a previous unbind was not done properly.
  1624. //
  1625. if (status == STATUS_OBJECT_NAME_COLLISION) {
  1626. // See if we can reuse the binding and device name
  1627. NbfReInitializeDeviceContext(
  1628. &status,
  1629. DriverObject,
  1630. NbfConfig,
  1631. BindName,
  1632. ExportName,
  1633. SystemSpecific1,
  1634. SystemSpecific2
  1635. );
  1636. if (status == STATUS_NOT_FOUND)
  1637. {
  1638. // Must have got deleted in the meantime
  1639. return NbfInitializeOneDeviceContext(
  1640. NdisStatus,
  1641. DriverObject,
  1642. NbfConfig,
  1643. BindName,
  1644. ExportName,
  1645. SystemSpecific1,
  1646. SystemSpecific2
  1647. );
  1648. }
  1649. }
  1650. *NdisStatus = status;
  1651. if (!NT_SUCCESS (status))
  1652. {
  1653. NbfWriteGeneralErrorLog(
  1654. (PVOID)DriverObject,
  1655. EVENT_TRANSPORT_BINDING_FAILED,
  1656. 707,
  1657. status,
  1658. BindName->Buffer,
  1659. 0,
  1660. NULL);
  1661. return(0);
  1662. }
  1663. return(1);
  1664. }
  1665. DeviceContext->UniProcessor = UniProcessor;
  1666. //
  1667. // Initialize the timer and retry values (note that the link timeouts
  1668. // are converted from NT ticks to NBF ticks). These values may
  1669. // be modified by NbfInitializeNdis.
  1670. //
  1671. DeviceContext->MinimumT1Timeout = NbfConfig->MinimumT1Timeout / SHORT_TIMER_DELTA;
  1672. DeviceContext->DefaultT1Timeout = NbfConfig->DefaultT1Timeout / SHORT_TIMER_DELTA;
  1673. DeviceContext->DefaultT2Timeout = NbfConfig->DefaultT2Timeout / SHORT_TIMER_DELTA;
  1674. DeviceContext->DefaultTiTimeout = NbfConfig->DefaultTiTimeout / LONG_TIMER_DELTA;
  1675. DeviceContext->LlcRetries = NbfConfig->LlcRetries;
  1676. DeviceContext->LlcMaxWindowSize = NbfConfig->LlcMaxWindowSize;
  1677. DeviceContext->MaxConsecutiveIFrames = (UCHAR)NbfConfig->MaximumIncomingFrames;
  1678. DeviceContext->NameQueryRetries = NbfConfig->NameQueryRetries;
  1679. DeviceContext->NameQueryTimeout = NbfConfig->NameQueryTimeout;
  1680. DeviceContext->AddNameQueryRetries = NbfConfig->AddNameQueryRetries;
  1681. DeviceContext->AddNameQueryTimeout = NbfConfig->AddNameQueryTimeout;
  1682. DeviceContext->GeneralRetries = NbfConfig->GeneralRetries;
  1683. DeviceContext->GeneralTimeout = NbfConfig->GeneralTimeout;
  1684. DeviceContext->MinimumSendWindowLimit = NbfConfig->MinimumSendWindowLimit;
  1685. //
  1686. // Initialize our counter that records memory usage.
  1687. //
  1688. DeviceContext->MemoryUsage = 0;
  1689. DeviceContext->MemoryLimit = NbfConfig->MaxMemoryUsage;
  1690. DeviceContext->MaxRequests = NbfConfig->MaxRequests;
  1691. DeviceContext->MaxLinks = NbfConfig->MaxLinks;
  1692. DeviceContext->MaxConnections = NbfConfig->MaxConnections;
  1693. DeviceContext->MaxAddressFiles = NbfConfig->MaxAddressFiles;
  1694. DeviceContext->MaxAddresses = NbfConfig->MaxAddresses;
  1695. //
  1696. // Now fire up NDIS so this adapter talks
  1697. //
  1698. status = NbfInitializeNdis (DeviceContext,
  1699. NbfConfig,
  1700. BindName);
  1701. if (!NT_SUCCESS (status)) {
  1702. //
  1703. // Log an error if we were failed to
  1704. // open this adapter.
  1705. //
  1706. NbfWriteGeneralErrorLog(
  1707. DeviceContext,
  1708. EVENT_TRANSPORT_BINDING_FAILED,
  1709. 601,
  1710. status,
  1711. BindName->Buffer,
  1712. 0,
  1713. NULL);
  1714. if (InterlockedExchange(&DeviceContext->CreateRefRemoved, TRUE) == FALSE) {
  1715. NbfDereferenceDeviceContext ("Initialize NDIS failed", DeviceContext, DCREF_CREATION);
  1716. }
  1717. *NdisStatus = status;
  1718. return(0);
  1719. }
  1720. #if 0
  1721. DbgPrint("Opened %S as %S\n", &NbfConfig->Names[j], &nameString);
  1722. #endif
  1723. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1724. NbfPrint6 ("NbfInitialize: NDIS returned: %x %x %x %x %x %x as local address.\n",
  1725. DeviceContext->LocalAddress.Address[0],
  1726. DeviceContext->LocalAddress.Address[1],
  1727. DeviceContext->LocalAddress.Address[2],
  1728. DeviceContext->LocalAddress.Address[3],
  1729. DeviceContext->LocalAddress.Address[4],
  1730. DeviceContext->LocalAddress.Address[5]);
  1731. }
  1732. //
  1733. // Initialize our provider information structure; since it
  1734. // doesn't change, we just keep it around and copy it to
  1735. // whoever requests it.
  1736. //
  1737. MacReturnMaxDataSize(
  1738. &DeviceContext->MacInfo,
  1739. NULL,
  1740. 0,
  1741. DeviceContext->MaxSendPacketSize,
  1742. TRUE,
  1743. &MaxUserData);
  1744. DeviceContext->Information.Version = 0x0100;
  1745. DeviceContext->Information.MaxSendSize = 0x1fffe; // 128k - 2
  1746. DeviceContext->Information.MaxConnectionUserData = 0;
  1747. DeviceContext->Information.MaxDatagramSize =
  1748. MaxUserData - (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS));
  1749. DeviceContext->Information.ServiceFlags = NBF_SERVICE_FLAGS;
  1750. if (DeviceContext->MacInfo.MediumAsync) {
  1751. DeviceContext->Information.ServiceFlags |= TDI_SERVICE_POINT_TO_POINT;
  1752. }
  1753. DeviceContext->Information.MinimumLookaheadData =
  1754. 240 - (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS));
  1755. DeviceContext->Information.MaximumLookaheadData =
  1756. DeviceContext->MaxReceivePacketSize - (sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  1757. DeviceContext->Information.NumberOfResources = NBF_TDI_RESOURCES;
  1758. KeQuerySystemTime (&DeviceContext->Information.StartTime);
  1759. //
  1760. // Allocate various structures we will need.
  1761. //
  1762. ENTER_NBF;
  1763. //
  1764. // The TP_UI_FRAME structure has a CHAR[1] field at the end
  1765. // which we expand upon to include all the headers needed;
  1766. // the size of the MAC header depends on what the adapter
  1767. // told us about its max header size.
  1768. //
  1769. DeviceContext->UIFrameHeaderLength =
  1770. DeviceContext->MacInfo.MaxHeaderLength +
  1771. sizeof(DLC_FRAME) +
  1772. sizeof(NBF_HDR_CONNECTIONLESS);
  1773. DeviceContext->UIFrameLength =
  1774. FIELD_OFFSET(TP_UI_FRAME, Header[0]) +
  1775. DeviceContext->UIFrameHeaderLength;
  1776. //
  1777. // The TP_PACKET structure has a CHAR[1] field at the end
  1778. // which we expand upon to include all the headers needed;
  1779. // the size of the MAC header depends on what the adapter
  1780. // told us about its max header size. TP_PACKETs are used
  1781. // for connection-oriented frame as well as for
  1782. // control frames, but since DLC_I_FRAME and DLC_S_FRAME
  1783. // are the same size, the header is the same size.
  1784. //
  1785. ASSERT (sizeof(DLC_I_FRAME) == sizeof(DLC_S_FRAME));
  1786. DeviceContext->PacketHeaderLength =
  1787. DeviceContext->MacInfo.MaxHeaderLength +
  1788. sizeof(DLC_I_FRAME) +
  1789. sizeof(NBF_HDR_CONNECTION);
  1790. DeviceContext->PacketLength =
  1791. FIELD_OFFSET(TP_PACKET, Header[0]) +
  1792. DeviceContext->PacketHeaderLength;
  1793. //
  1794. // The BUFFER_TAG structure has a CHAR[1] field at the end
  1795. // which we expand upong to include all the frame data.
  1796. //
  1797. DeviceContext->ReceiveBufferLength =
  1798. DeviceContext->MaxReceivePacketSize +
  1799. FIELD_OFFSET(BUFFER_TAG, Buffer[0]);
  1800. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1801. NbfPrint0 ("NBFDRVR: pre-allocating requests.\n");
  1802. }
  1803. for (i=0; i<NbfConfig->InitRequests; i++) {
  1804. NbfAllocateRequest (DeviceContext, &Request);
  1805. if (Request == NULL) {
  1806. PANIC ("NbfInitialize: insufficient memory to allocate requests.\n");
  1807. status = STATUS_INSUFFICIENT_RESOURCES;
  1808. goto cleanup;
  1809. }
  1810. InsertTailList (&DeviceContext->RequestPool, &Request->Linkage);
  1811. #if DBG
  1812. NbfRequestTable[i+1] = (PVOID)Request;
  1813. #endif
  1814. }
  1815. #if DBG
  1816. NbfRequestTable[0] = UlongToPtr(NbfConfig->InitRequests);
  1817. NbfRequestTable[NbfConfig->InitRequests + 1] = (PVOID)
  1818. ((NBF_REQUEST_SIGNATURE << 16) | sizeof (TP_REQUEST));
  1819. InitializeListHead (&NbfGlobalRequestList);
  1820. #endif
  1821. DeviceContext->RequestInitAllocated = NbfConfig->InitRequests;
  1822. DeviceContext->RequestMaxAllocated = NbfConfig->MaxRequests;
  1823. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1824. NbfPrint2 ("%d requests, %ld\n", NbfConfig->InitRequests, DeviceContext->MemoryUsage);
  1825. }
  1826. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1827. NbfPrint0 ("NBFDRVR: allocating links.\n");
  1828. }
  1829. for (i=0; i<NbfConfig->InitLinks; i++) {
  1830. NbfAllocateLink (DeviceContext, &Link);
  1831. if (Link == NULL) {
  1832. PANIC ("NbfInitialize: insufficient memory to allocate links.\n");
  1833. status = STATUS_INSUFFICIENT_RESOURCES;
  1834. goto cleanup;
  1835. }
  1836. InsertTailList (&DeviceContext->LinkPool, &Link->Linkage);
  1837. #if DBG
  1838. NbfLinkTable[i+1] = (PVOID)Link;
  1839. #endif
  1840. }
  1841. #if DBG
  1842. NbfLinkTable[0] = UlongToPtr(NbfConfig->InitLinks);
  1843. NbfLinkTable[NbfConfig->InitLinks+1] = (PVOID)
  1844. ((NBF_LINK_SIGNATURE << 16) | sizeof (TP_LINK));
  1845. #endif
  1846. DeviceContext->LinkInitAllocated = NbfConfig->InitLinks;
  1847. DeviceContext->LinkMaxAllocated = NbfConfig->MaxLinks;
  1848. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1849. NbfPrint2 ("%d links, %ld\n", NbfConfig->InitLinks, DeviceContext->MemoryUsage);
  1850. }
  1851. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1852. NbfPrint0 ("NBFDRVR: allocating connections.\n");
  1853. }
  1854. for (i=0; i<NbfConfig->InitConnections; i++) {
  1855. NbfAllocateConnection (DeviceContext, &Connection);
  1856. if (Connection == NULL) {
  1857. PANIC ("NbfInitialize: insufficient memory to allocate connections.\n");
  1858. status = STATUS_INSUFFICIENT_RESOURCES;
  1859. goto cleanup;
  1860. }
  1861. InsertTailList (&DeviceContext->ConnectionPool, &Connection->LinkList);
  1862. #if DBG
  1863. NbfConnectionTable[i+1] = (PVOID)Connection;
  1864. #endif
  1865. }
  1866. #if DBG
  1867. NbfConnectionTable[0] = UlongToPtr(NbfConfig->InitConnections);
  1868. NbfConnectionTable[NbfConfig->InitConnections+1] = (PVOID)
  1869. ((NBF_CONNECTION_SIGNATURE << 16) | sizeof (TP_CONNECTION));
  1870. #endif
  1871. DeviceContext->ConnectionInitAllocated = NbfConfig->InitConnections;
  1872. DeviceContext->ConnectionMaxAllocated = NbfConfig->MaxConnections;
  1873. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1874. NbfPrint2 ("%d connections, %ld\n", NbfConfig->InitConnections, DeviceContext->MemoryUsage);
  1875. }
  1876. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1877. NbfPrint0 ("NBFDRVR: allocating AddressFiles.\n");
  1878. }
  1879. for (i=0; i<NbfConfig->InitAddressFiles; i++) {
  1880. NbfAllocateAddressFile (DeviceContext, &AddressFile);
  1881. if (AddressFile == NULL) {
  1882. PANIC ("NbfInitialize: insufficient memory to allocate Address Files.\n");
  1883. status = STATUS_INSUFFICIENT_RESOURCES;
  1884. goto cleanup;
  1885. }
  1886. InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage);
  1887. #if DBG
  1888. NbfAddressFileTable[i+1] = (PVOID)AddressFile;
  1889. #endif
  1890. }
  1891. #if DBG
  1892. NbfAddressFileTable[0] = UlongToPtr(NbfConfig->InitAddressFiles);
  1893. NbfAddressFileTable[NbfConfig->InitAddressFiles + 1] = (PVOID)
  1894. ((NBF_ADDRESSFILE_SIGNATURE << 16) |
  1895. sizeof (TP_ADDRESS_FILE));
  1896. #endif
  1897. DeviceContext->AddressFileInitAllocated = NbfConfig->InitAddressFiles;
  1898. DeviceContext->AddressFileMaxAllocated = NbfConfig->MaxAddressFiles;
  1899. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1900. NbfPrint2 ("%d address files, %ld\n", NbfConfig->InitAddressFiles, DeviceContext->MemoryUsage);
  1901. }
  1902. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1903. NbfPrint0 ("NBFDRVR: allocating addresses.\n");
  1904. }
  1905. for (i=0; i<NbfConfig->InitAddresses; i++) {
  1906. NbfAllocateAddress (DeviceContext, &Address);
  1907. if (Address == NULL) {
  1908. PANIC ("NbfInitialize: insufficient memory to allocate addresses.\n");
  1909. status = STATUS_INSUFFICIENT_RESOURCES;
  1910. goto cleanup;
  1911. }
  1912. InsertTailList (&DeviceContext->AddressPool, &Address->Linkage);
  1913. #if DBG
  1914. NbfAddressTable[i+1] = (PVOID)Address;
  1915. #endif
  1916. }
  1917. #if DBG
  1918. NbfAddressTable[0] = UlongToPtr(NbfConfig->InitAddresses);
  1919. NbfAddressTable[NbfConfig->InitAddresses + 1] = (PVOID)
  1920. ((NBF_ADDRESS_SIGNATURE << 16) | sizeof (TP_ADDRESS));
  1921. #endif
  1922. DeviceContext->AddressInitAllocated = NbfConfig->InitAddresses;
  1923. DeviceContext->AddressMaxAllocated = NbfConfig->MaxAddresses;
  1924. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1925. NbfPrint2 ("%d addresses, %ld\n", NbfConfig->InitAddresses, DeviceContext->MemoryUsage);
  1926. }
  1927. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1928. NbfPrint0 ("NBFDRVR: allocating UI frames.\n");
  1929. }
  1930. for (i=0; i<NbfConfig->InitUIFrames; i++) {
  1931. NbfAllocateUIFrame (DeviceContext, &UIFrame);
  1932. if (UIFrame == NULL) {
  1933. PANIC ("NbfInitialize: insufficient memory to allocate UI frames.\n");
  1934. status = STATUS_INSUFFICIENT_RESOURCES;
  1935. goto cleanup;
  1936. }
  1937. InsertTailList (&(DeviceContext->UIFramePool), &UIFrame->Linkage);
  1938. #if DBG
  1939. NbfUiFrameTable[i+1] = UIFrame;
  1940. #endif
  1941. }
  1942. #if DBG
  1943. NbfUiFrameTable[0] = UlongToPtr(NbfConfig->InitUIFrames);
  1944. #endif
  1945. DeviceContext->UIFrameInitAllocated = NbfConfig->InitUIFrames;
  1946. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1947. NbfPrint2 ("%d UI frames, %ld\n", NbfConfig->InitUIFrames, DeviceContext->MemoryUsage);
  1948. }
  1949. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1950. NbfPrint0 ("NBFDRVR: allocating I frames.\n");
  1951. NbfPrint1 ("NBFDRVR: Packet pool header: %lx\n",&DeviceContext->PacketPool);
  1952. }
  1953. for (i=0; i<NbfConfig->InitPackets; i++) {
  1954. NbfAllocateSendPacket (DeviceContext, &Packet);
  1955. if (Packet == NULL) {
  1956. PANIC ("NbfInitialize: insufficient memory to allocate packets.\n");
  1957. status = STATUS_INSUFFICIENT_RESOURCES;
  1958. goto cleanup;
  1959. }
  1960. PushEntryList (&DeviceContext->PacketPool, (PSINGLE_LIST_ENTRY)&Packet->Linkage);
  1961. #if DBG
  1962. NbfSendPacketTable[i+1] = Packet;
  1963. #endif
  1964. }
  1965. #if DBG
  1966. NbfSendPacketTable[0] = UlongToPtr(NbfConfig->InitPackets);
  1967. NbfSendPacketTable[NbfConfig->InitPackets+1] = (PVOID)
  1968. ((NBF_PACKET_SIGNATURE << 16) | sizeof (TP_PACKET));
  1969. #endif
  1970. DeviceContext->PacketInitAllocated = NbfConfig->InitPackets;
  1971. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1972. NbfPrint2 ("%d I-frame send packets, %ld\n", NbfConfig->InitPackets, DeviceContext->MemoryUsage);
  1973. }
  1974. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1975. NbfPrint0 ("NBFDRVR: allocating RR frames.\n");
  1976. NbfPrint1 ("NBFDRVR: Packet pool header: %lx\n",&DeviceContext->RrPacketPool);
  1977. }
  1978. for (i=0; i<10; i++) {
  1979. NbfAllocateSendPacket (DeviceContext, &Packet);
  1980. if (Packet == NULL) {
  1981. PANIC ("NbfInitialize: insufficient memory to allocate packets.\n");
  1982. status = STATUS_INSUFFICIENT_RESOURCES;
  1983. goto cleanup;
  1984. }
  1985. Packet->Action = PACKET_ACTION_RR;
  1986. PushEntryList (&DeviceContext->RrPacketPool, (PSINGLE_LIST_ENTRY)&Packet->Linkage);
  1987. }
  1988. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1989. NbfPrint2 ("%d RR-frame send packets, %ld\n", 10, DeviceContext->MemoryUsage);
  1990. }
  1991. // Allocate receive Ndis packets
  1992. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1993. NbfPrint0 ("NBFDRVR: allocating Ndis Receive packets.\n");
  1994. }
  1995. if (DeviceContext->MacInfo.SingleReceive) {
  1996. InitReceivePackets = 2;
  1997. } else {
  1998. InitReceivePackets = NbfConfig->InitReceivePackets;
  1999. }
  2000. for (i=0; i<InitReceivePackets; i++) {
  2001. NbfAllocateReceivePacket (DeviceContext, &NdisPacket);
  2002. if (NdisPacket == NULL) {
  2003. PANIC ("NbfInitialize: insufficient memory to allocate packet MDLs.\n");
  2004. status = STATUS_INSUFFICIENT_RESOURCES;
  2005. goto cleanup;
  2006. }
  2007. ReceiveTag = (PRECEIVE_PACKET_TAG)NdisPacket->ProtocolReserved;
  2008. PushEntryList (&DeviceContext->ReceivePacketPool, &ReceiveTag->Linkage);
  2009. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  2010. PNDIS_BUFFER NdisBuffer;
  2011. NdisQueryPacket(NdisPacket, NULL, NULL, &NdisBuffer, NULL);
  2012. NbfPrint2 ("NbfInitialize: Created NDIS Pkt: %x Buffer: %x\n",
  2013. NdisPacket, NdisBuffer);
  2014. }
  2015. }
  2016. DeviceContext->ReceivePacketInitAllocated = InitReceivePackets;
  2017. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  2018. NbfPrint2 ("%d receive packets, %ld\n", InitReceivePackets, DeviceContext->MemoryUsage);
  2019. }
  2020. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  2021. NbfPrint0 ("NBFDRVR: allocating Ndis Receive buffers.\n");
  2022. }
  2023. for (i=0; i<NbfConfig->InitReceiveBuffers; i++) {
  2024. NbfAllocateReceiveBuffer (DeviceContext, &BufferTag);
  2025. if (BufferTag == NULL) {
  2026. PANIC ("NbfInitialize: Unable to allocate receive packet.\n");
  2027. status = STATUS_INSUFFICIENT_RESOURCES;
  2028. goto cleanup;
  2029. }
  2030. PushEntryList (&DeviceContext->ReceiveBufferPool, (PSINGLE_LIST_ENTRY)&BufferTag->Linkage);
  2031. }
  2032. DeviceContext->ReceiveBufferInitAllocated = NbfConfig->InitReceiveBuffers;
  2033. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  2034. NbfPrint2 ("%d receive buffers, %ld\n", NbfConfig->InitReceiveBuffers, DeviceContext->MemoryUsage);
  2035. }
  2036. // Store away the PDO for the underlying object
  2037. DeviceContext->PnPContext = SystemSpecific2;
  2038. DeviceContext->State = DEVICECONTEXT_STATE_OPEN;
  2039. //
  2040. // Start the link-level timers running.
  2041. //
  2042. NbfInitializeTimerSystem (DeviceContext);
  2043. //
  2044. // Now link the device into the global list.
  2045. //
  2046. ACQUIRE_DEVICES_LIST_LOCK();
  2047. InsertTailList (&NbfDeviceList, &DeviceContext->Linkage);
  2048. RELEASE_DEVICES_LIST_LOCK();
  2049. DeviceObject = (PDEVICE_OBJECT) DeviceContext;
  2050. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  2051. RtlInitUnicodeString(&DeviceString, DeviceContext->DeviceName);
  2052. IF_NBFDBG (NBF_DEBUG_PNP) {
  2053. NbfPrint1 ("TdiRegisterDeviceObject for %S\n", DeviceString.Buffer);
  2054. }
  2055. status = TdiRegisterDeviceObject(&DeviceString,
  2056. &DeviceContext->TdiDeviceHandle);
  2057. if (!NT_SUCCESS (status)) {
  2058. RemoveEntryList(&DeviceContext->Linkage);
  2059. goto cleanup;
  2060. }
  2061. RtlCopyMemory(NetBIOSAddress->NetbiosName,
  2062. DeviceContext->ReservedNetBIOSAddress, 16);
  2063. tdiPnPContext1.tdiPnPContextHeader.ContextSize = sizeof(PVOID);
  2064. tdiPnPContext1.tdiPnPContextHeader.ContextType = TDI_PNP_CONTEXT_TYPE_IF_NAME;
  2065. *(PVOID UNALIGNED *) &tdiPnPContext1.tdiPnPContextHeader.ContextData = &DeviceString;
  2066. tdiPnPContext2.tdiPnPContextHeader.ContextSize = sizeof(PVOID);
  2067. tdiPnPContext2.tdiPnPContextHeader.ContextType = TDI_PNP_CONTEXT_TYPE_PDO;
  2068. *(PVOID UNALIGNED *) &tdiPnPContext2.tdiPnPContextHeader.ContextData = SystemSpecific2;
  2069. IF_NBFDBG (NBF_DEBUG_PNP) {
  2070. NbfPrint1 ("TdiRegisterNetAddress on %S ", DeviceString.Buffer);
  2071. NbfPrint6 ("for %02x%02x%02x%02x%02x%02x\n",
  2072. NetBIOSAddress->NetbiosName[10],
  2073. NetBIOSAddress->NetbiosName[11],
  2074. NetBIOSAddress->NetbiosName[12],
  2075. NetBIOSAddress->NetbiosName[13],
  2076. NetBIOSAddress->NetbiosName[14],
  2077. NetBIOSAddress->NetbiosName[15]);
  2078. }
  2079. status = TdiRegisterNetAddress(pAddress,
  2080. &DeviceString,
  2081. (TDI_PNP_CONTEXT *) &tdiPnPContext2,
  2082. &DeviceContext->ReservedAddressHandle);
  2083. if (!NT_SUCCESS (status)) {
  2084. RemoveEntryList(&DeviceContext->Linkage);
  2085. goto cleanup;
  2086. }
  2087. NbfReferenceDeviceContext ("Load Succeeded", DeviceContext, DCREF_CREATION);
  2088. LEAVE_NBF;
  2089. *NdisStatus = NDIS_STATUS_SUCCESS;
  2090. return(1);
  2091. cleanup:
  2092. NbfWriteResourceErrorLog(
  2093. DeviceContext,
  2094. EVENT_TRANSPORT_RESOURCE_POOL,
  2095. 501,
  2096. DeviceContext->MemoryUsage,
  2097. 0);
  2098. //
  2099. // Cleanup whatever device context we were initializing
  2100. // when we failed.
  2101. //
  2102. *NdisStatus = status;
  2103. ASSERT(status != STATUS_SUCCESS);
  2104. if (InterlockedExchange(&DeviceContext->CreateRefRemoved, TRUE) == FALSE) {
  2105. // Stop all internal timers
  2106. NbfStopTimerSystem(DeviceContext);
  2107. // Remove creation reference
  2108. NbfDereferenceDeviceContext ("Load failed", DeviceContext, DCREF_CREATION);
  2109. }
  2110. LEAVE_NBF;
  2111. return (0);
  2112. }
  2113. VOID
  2114. NbfReInitializeDeviceContext(
  2115. OUT PNDIS_STATUS NdisStatus,
  2116. IN PDRIVER_OBJECT DriverObject,
  2117. IN PCONFIG_DATA NbfConfig,
  2118. IN PUNICODE_STRING BindName,
  2119. IN PUNICODE_STRING ExportName,
  2120. IN PVOID SystemSpecific1,
  2121. IN PVOID SystemSpecific2
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. This routine re-initializes an existing nbf device context. In order to
  2126. do this, we need to undo whatever is done in the Unbind handler exposed
  2127. to NDIS - recreate the NDIS binding, and re-start the NBF timer system.
  2128. Arguments:
  2129. NdisStatus - The outputted status of the operations.
  2130. DriverObject - the nbf driver object.
  2131. NbfConfig - the transport configuration information from the registry.
  2132. SystemSpecific1 - SystemSpecific1 argument to ProtocolBindAdapter
  2133. SystemSpecific2 - SystemSpecific2 argument to ProtocolBindAdapter
  2134. Return Value:
  2135. None
  2136. --*/
  2137. {
  2138. PDEVICE_CONTEXT DeviceContext;
  2139. KIRQL oldIrql;
  2140. PLIST_ENTRY p;
  2141. NTSTATUS status;
  2142. UNICODE_STRING DeviceString;
  2143. UCHAR PermAddr[sizeof(TA_ADDRESS)+TDI_ADDRESS_LENGTH_NETBIOS];
  2144. PTA_ADDRESS pAddress = (PTA_ADDRESS)PermAddr;
  2145. PTDI_ADDRESS_NETBIOS NetBIOSAddress =
  2146. (PTDI_ADDRESS_NETBIOS)pAddress->Address;
  2147. struct {
  2148. TDI_PNP_CONTEXT tdiPnPContextHeader;
  2149. PVOID tdiPnPContextTrailer;
  2150. } tdiPnPContext1, tdiPnPContext2;
  2151. IF_NBFDBG (NBF_DEBUG_PNP) {
  2152. NbfPrint1 ("ENTER NbfReInitializeDeviceContext for %S\n",
  2153. ExportName->Buffer);
  2154. }
  2155. //
  2156. // Search the list of NBF devices for a matching device name
  2157. //
  2158. ACQUIRE_DEVICES_LIST_LOCK();
  2159. for (p = NbfDeviceList.Flink ; p != &NbfDeviceList; p = p->Flink)
  2160. {
  2161. DeviceContext = CONTAINING_RECORD (p, DEVICE_CONTEXT, Linkage);
  2162. RtlInitUnicodeString(&DeviceString, DeviceContext->DeviceName);
  2163. if (NdisEqualString(&DeviceString, ExportName, TRUE)) {
  2164. // This has to be a rebind - otherwise something wrong
  2165. ASSERT(DeviceContext->CreateRefRemoved == TRUE);
  2166. // Reference within lock so that it is not cleaned up
  2167. NbfReferenceDeviceContext ("Reload Temp Use", DeviceContext, DCREF_TEMP_USE);
  2168. break;
  2169. }
  2170. }
  2171. RELEASE_DEVICES_LIST_LOCK();
  2172. if (p == &NbfDeviceList)
  2173. {
  2174. IF_NBFDBG (NBF_DEBUG_PNP) {
  2175. NbfPrint2 ("LEAVE NbfReInitializeDeviceContext for %S with Status %08x\n",
  2176. ExportName->Buffer,
  2177. STATUS_NOT_FOUND);
  2178. }
  2179. *NdisStatus = STATUS_NOT_FOUND;
  2180. return;
  2181. }
  2182. //
  2183. // Fire up NDIS again so this adapter talks
  2184. //
  2185. status = NbfInitializeNdis (DeviceContext,
  2186. NbfConfig,
  2187. BindName);
  2188. if (!NT_SUCCESS (status)) {
  2189. goto Cleanup;
  2190. }
  2191. // Store away the PDO for the underlying object
  2192. DeviceContext->PnPContext = SystemSpecific2;
  2193. DeviceContext->State = DEVICECONTEXT_STATE_OPEN;
  2194. //
  2195. // Restart the link-level timers on device
  2196. //
  2197. NbfInitializeTimerSystem (DeviceContext);
  2198. //
  2199. // Re-Indicate to TDI that new binding has arrived
  2200. //
  2201. status = TdiRegisterDeviceObject(&DeviceString,
  2202. &DeviceContext->TdiDeviceHandle);
  2203. if (!NT_SUCCESS (status)) {
  2204. goto Cleanup;
  2205. }
  2206. pAddress->AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
  2207. pAddress->AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  2208. NetBIOSAddress->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  2209. RtlCopyMemory(NetBIOSAddress->NetbiosName,
  2210. DeviceContext->ReservedNetBIOSAddress, 16);
  2211. tdiPnPContext1.tdiPnPContextHeader.ContextSize = sizeof(PVOID);
  2212. tdiPnPContext1.tdiPnPContextHeader.ContextType = TDI_PNP_CONTEXT_TYPE_IF_NAME;
  2213. *(PVOID UNALIGNED *) &tdiPnPContext1.tdiPnPContextHeader.ContextData = &DeviceString;
  2214. tdiPnPContext2.tdiPnPContextHeader.ContextSize = sizeof(PVOID);
  2215. tdiPnPContext2.tdiPnPContextHeader.ContextType = TDI_PNP_CONTEXT_TYPE_PDO;
  2216. *(PVOID UNALIGNED *) &tdiPnPContext2.tdiPnPContextHeader.ContextData = SystemSpecific2;
  2217. IF_NBFDBG (NBF_DEBUG_PNP) {
  2218. NbfPrint1 ("TdiRegisterNetAddress on %S ", DeviceString.Buffer);
  2219. NbfPrint6 ("for %02x%02x%02x%02x%02x%02x\n",
  2220. NetBIOSAddress->NetbiosName[10],
  2221. NetBIOSAddress->NetbiosName[11],
  2222. NetBIOSAddress->NetbiosName[12],
  2223. NetBIOSAddress->NetbiosName[13],
  2224. NetBIOSAddress->NetbiosName[14],
  2225. NetBIOSAddress->NetbiosName[15]);
  2226. }
  2227. status = TdiRegisterNetAddress(pAddress,
  2228. &DeviceString,
  2229. (TDI_PNP_CONTEXT *) &tdiPnPContext2,
  2230. &DeviceContext->ReservedAddressHandle);
  2231. if (!NT_SUCCESS (status)) {
  2232. goto Cleanup;
  2233. }
  2234. // Put the creation reference back again
  2235. NbfReferenceDeviceContext ("Reload Succeeded", DeviceContext, DCREF_CREATION);
  2236. DeviceContext->CreateRefRemoved = FALSE;
  2237. status = NDIS_STATUS_SUCCESS;
  2238. Cleanup:
  2239. if (status != NDIS_STATUS_SUCCESS)
  2240. {
  2241. // Stop all internal timers
  2242. NbfStopTimerSystem (DeviceContext);
  2243. }
  2244. NbfDereferenceDeviceContext ("Reload Temp Use", DeviceContext, DCREF_TEMP_USE);
  2245. *NdisStatus = status;
  2246. IF_NBFDBG (NBF_DEBUG_PNP) {
  2247. NbfPrint2 ("LEAVE NbfReInitializeDeviceContext for %S with Status %08x\n",
  2248. ExportName->Buffer,
  2249. status);
  2250. }
  2251. return;
  2252. }