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.

1926 lines
47 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. file.c
  5. Abstract:
  6. This module contains code which defines the NetBIOS driver's
  7. file control block object.
  8. Author:
  9. Colin Watson (ColinW) 13-Mar-1991
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "nb.h"
  15. //#include "ntos.h"
  16. //#include <zwapi.h>
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, NewFcb)
  19. #pragma alloc_text(PAGE, CleanupFcb)
  20. #pragma alloc_text(PAGE, OpenLana)
  21. #pragma alloc_text(PAGE, NbBindHandler)
  22. #pragma alloc_text(PAGE, NbPowerHandler)
  23. #pragma alloc_text(PAGE, NbTdiBindHandler)
  24. #pragma alloc_text(PAGE, NbTdiUnbindHandler)
  25. #endif
  26. #if AUTO_RESET
  27. VOID
  28. NotifyUserModeNetbios(
  29. IN PFCB_ENTRY pfe
  30. );
  31. #endif
  32. VOID
  33. DumpDeviceList(
  34. IN PFCB pfcb
  35. );
  36. NTSTATUS
  37. NewFcb(
  38. IN PDEVICE_CONTEXT DeviceContext,
  39. IN PIO_STACK_LOCATION IrpSp
  40. )
  41. /*++
  42. Routine Description:
  43. This routine is called when the dll opens \Device\Netbios. It
  44. creates all the lana structures and adds the name for the "burnt
  45. in" prom address on each adapter. Note the similarity to the routine
  46. NbAstat when looking at this function.
  47. Arguments:
  48. IrpSp - Pointer to current IRP stack frame.
  49. Return Value:
  50. The function value is the status of the operation.
  51. --*/
  52. {
  53. //
  54. // Allocate the user context and store it in the DeviceObject.
  55. //
  56. PFILE_OBJECT FileObject = IrpSp->FileObject;
  57. PFCB NewFcb = NULL;
  58. UCHAR ucIndex;
  59. NTSTATUS Status;
  60. PFCB_ENTRY pfe = NULL;
  61. BOOLEAN bCleanupResource = FALSE;
  62. PAGED_CODE();
  63. do
  64. {
  65. //
  66. // allocate FCB
  67. //
  68. NewFcb = ExAllocatePoolWithTag (NonPagedPool, sizeof(FCB), 'fSBN');
  69. FileObject->FsContext2 = NewFcb;
  70. if ( NewFcb == NULL )
  71. {
  72. NbPrint( ( "Netbios : NewFcb : Failed to allocate FCB\n" ) );
  73. Status = STATUS_INSUFFICIENT_RESOURCES;
  74. break;
  75. }
  76. RtlZeroMemory( NewFcb, sizeof( FCB ) );
  77. NewFcb->Signature = FCB_SIGNATURE;
  78. NewFcb->TimerRunning = FALSE;
  79. NewFcb-> RegistrySpace = NULL;
  80. //
  81. // Allocate for the LanaInfo array
  82. //
  83. NewFcb->ppLana = ExAllocatePoolWithTag (
  84. NonPagedPool,
  85. sizeof(PLANA_INFO) * (MAX_LANA + 1),
  86. 'fSBN'
  87. );
  88. if ( NewFcb->ppLana == NULL )
  89. {
  90. NbPrint( ( "Netbios : NewFcb : Failed to allocate Lana info list\n" ) );
  91. Status = STATUS_INSUFFICIENT_RESOURCES;
  92. break;
  93. }
  94. //
  95. // Allocate for driver name list
  96. //
  97. NewFcb-> pDriverName = ExAllocatePoolWithTag (
  98. NonPagedPool,
  99. sizeof(UNICODE_STRING) * (MAX_LANA + 1),
  100. 'fSBN'
  101. );
  102. if ( NewFcb-> pDriverName == NULL )
  103. {
  104. NbPrint( ( "Netbios : NewFcb : Failed to allocate device name list\n" ) );
  105. Status = STATUS_INSUFFICIENT_RESOURCES;
  106. break;
  107. }
  108. //
  109. // Initialize Lana info list, driver name list
  110. //
  111. for ( ucIndex = 0; ucIndex <= MAX_LANA; ucIndex++ )
  112. {
  113. NewFcb->ppLana[ ucIndex ] = NULL;
  114. RtlInitUnicodeString( &NewFcb-> pDriverName[ ucIndex ], NULL );
  115. }
  116. //
  117. // allocate and initialize FCB list entry
  118. //
  119. pfe = ExAllocatePoolWithTag( NonPagedPool, sizeof( FCB_ENTRY ), 'fSBN' );
  120. if ( pfe == NULL )
  121. {
  122. NbPrint( ( "Netbios : NewFcb : Failed to allocate FCB list entry\n" ) );
  123. Status = STATUS_INSUFFICIENT_RESOURCES;
  124. break;
  125. }
  126. InitializeListHead( &pfe-> leList );
  127. #if AUTO_RESET
  128. InitializeListHead( &pfe-> leResetList );
  129. InitializeListHead( &pfe-> leResetIrp );
  130. #endif
  131. pfe-> pfcb = NewFcb;
  132. pfe-> peProcess = PsGetCurrentProcess();
  133. //
  134. // Initialize locks
  135. //
  136. KeInitializeSpinLock( &NewFcb->SpinLock );
  137. ExInitializeResourceLite( &NewFcb->Resource );
  138. ExInitializeResourceLite( &NewFcb->AddResource );
  139. bCleanupResource = TRUE;
  140. //
  141. // allocate work item
  142. //
  143. NewFcb->WorkEntry = IoAllocateWorkItem( (PDEVICE_OBJECT)DeviceContext );
  144. if ( NewFcb->WorkEntry == NULL )
  145. {
  146. NbPrint( ( "Netbios : NewFcb : Failed to allocate work ite,\n" ) );
  147. Status = STATUS_INSUFFICIENT_RESOURCES;
  148. break;
  149. }
  150. //
  151. // retrieve global info
  152. //
  153. LOCK_GLOBAL();
  154. NewFcb-> MaxLana = g_ulMaxLana;
  155. RtlCopyMemory( &NewFcb-> LanaEnum, &g_leLanaEnum, sizeof( LANA_ENUM ) );
  156. //
  157. // copy all active device names
  158. //
  159. Status = STATUS_SUCCESS;
  160. for ( ucIndex = 0; ucIndex <= g_ulMaxLana; ucIndex++ )
  161. {
  162. if ( ( g_pusActiveDeviceList[ ucIndex ].MaximumLength != 0 ) &&
  163. ( g_pusActiveDeviceList[ ucIndex ].Buffer != NULL ) )
  164. {
  165. Status = AllocateAndCopyUnicodeString(
  166. &NewFcb-> pDriverName[ ucIndex ],
  167. &g_pusActiveDeviceList[ ucIndex ]
  168. );
  169. if ( !NT_SUCCESS( Status ) )
  170. {
  171. NbPrint( (
  172. "Netbios : failed to allocate device name for lana %d\n",
  173. ucIndex
  174. ) );
  175. break;
  176. }
  177. }
  178. }
  179. if ( !NT_SUCCESS( Status ) )
  180. {
  181. UNLOCK_GLOBAL();
  182. break;
  183. }
  184. //
  185. // Add FCB to global list of FCBs
  186. //
  187. InsertHeadList( &g_leFCBList, &pfe-> leList );
  188. UNLOCK_GLOBAL();
  189. IF_NBDBG (NB_DEBUG_FILE)
  190. {
  191. NbPrint(("Enumeration of transports completed:\n"));
  192. NbFormattedDump( (PUCHAR)&NewFcb->LanaEnum, sizeof(LANA_ENUM));
  193. }
  194. return STATUS_SUCCESS;
  195. } while ( FALSE );
  196. //
  197. // error condition. cleanup all allocations.
  198. //
  199. if ( NewFcb != NULL )
  200. {
  201. //
  202. // free the list of driver names
  203. //
  204. if ( NewFcb-> pDriverName != NULL )
  205. {
  206. for ( ucIndex = 0; ucIndex <= MAX_LANA; ucIndex++ )
  207. {
  208. if ( NewFcb-> pDriverName[ ucIndex ].Buffer != NULL )
  209. {
  210. ExFreePool( NewFcb-> pDriverName[ ucIndex ].Buffer );
  211. }
  212. }
  213. ExFreePool( NewFcb-> pDriverName );
  214. }
  215. //
  216. // free the lana list
  217. //
  218. if ( NewFcb-> ppLana != NULL )
  219. {
  220. ExFreePool( NewFcb-> ppLana );
  221. }
  222. //
  223. // Free the work item
  224. //
  225. if ( NewFcb->WorkEntry != NULL )
  226. {
  227. IoFreeWorkItem( NewFcb->WorkEntry );
  228. }
  229. //
  230. // Delete resources
  231. //
  232. if ( bCleanupResource )
  233. {
  234. ExDeleteResourceLite( &NewFcb-> Resource );
  235. ExDeleteResourceLite( &NewFcb-> AddResource );
  236. }
  237. //
  238. // free the FCB
  239. //
  240. ExFreePool( NewFcb );
  241. //
  242. // free the global FCB entry
  243. //
  244. }
  245. if ( pfe != NULL )
  246. {
  247. ExFreePool( pfe ) ;
  248. }
  249. FileObject->FsContext2 = NULL;
  250. return Status;
  251. } /* NewFcb */
  252. VOID
  253. OpenLana(
  254. IN PDNCB pdncb,
  255. IN PIRP Irp,
  256. IN PIO_STACK_LOCATION IrpSp
  257. )
  258. /*++
  259. Routine Description:
  260. This routine is called when an application resets an adapter allocating
  261. resources. It creates all the lana structure and adds the name for the
  262. "burnt in" prom address as well as finding the broadcast address.
  263. Note the similarity to the routine NbAstat when looking at this function.
  264. Arguments:
  265. pdncb - Pointer to the NCB.
  266. Irp - Pointer to the request packet representing the I/O request.
  267. IrpSp - Pointer to current IRP stack frame.
  268. Return Value:
  269. The function value is the status of the operation.
  270. --*/
  271. {
  272. NTSTATUS Status = STATUS_SUCCESS;
  273. PFILE_OBJECT FileObject = IrpSp->FileObject;
  274. PFCB pfcb = IrpSp->FileObject->FsContext2;
  275. KEVENT Event1;
  276. PLANA_INFO plana;
  277. HANDLE TdiHandle;
  278. PFILE_OBJECT TdiObject;
  279. PDEVICE_OBJECT DeviceObject;
  280. PMDL SaveMdl;
  281. int temp;
  282. PRESET_PARAMETERS InParameters;
  283. PRESET_PARAMETERS OutParameters;
  284. UCHAR Sessions;
  285. UCHAR Commands;
  286. UCHAR Names;
  287. BOOLEAN Exclusive;
  288. UCHAR ucInd = 0;
  289. UNICODE_STRING usDeviceName;
  290. //
  291. // Ncb and associated buffer to be used in adapter status to get the
  292. // prom address.
  293. //
  294. DNCB ncb;
  295. struct _AdapterStatus {
  296. ADAPTER_STATUS AdapterInformation;
  297. NAME_BUFFER Nb;
  298. } AdapterStatus;
  299. PMDL AdapterStatusMdl = NULL;
  300. struct _BroadcastName {
  301. TRANSPORT_ADDRESS Address;
  302. UCHAR Padding[NCBNAMSZ];
  303. } BroadcastName;
  304. PMDL BroadcastMdl = NULL;
  305. PAGED_CODE();
  306. RtlInitUnicodeString( &usDeviceName, NULL);
  307. LOCK_RESOURCE( pfcb );
  308. //
  309. // check lana specified is valid
  310. //
  311. if ( ( pdncb->ncb_lana_num > pfcb->MaxLana) ||
  312. ( pfcb-> pDriverName[ pdncb-> ncb_lana_num ].MaximumLength == 0 ) ||
  313. ( pfcb-> pDriverName[ pdncb-> ncb_lana_num ].Buffer == NULL ) )
  314. {
  315. UNLOCK_RESOURCE( pfcb );
  316. NCB_COMPLETE( pdncb, NRC_BRIDGE );
  317. return;
  318. }
  319. //
  320. // since no locks are held when invoking NbOpenAddress, no fields of
  321. // pfcb should be passed to it. This is because pfcb might be
  322. // modified by a bind or unbind notification
  323. //
  324. Status = AllocateAndCopyUnicodeString(
  325. &usDeviceName, &pfcb-> pDriverName[ pdncb-> ncb_lana_num ]
  326. );
  327. if ( !NT_SUCCESS( Status ) )
  328. {
  329. NCB_COMPLETE( pdncb, NRC_NORES );
  330. UNLOCK_RESOURCE( pfcb );
  331. goto exit;
  332. }
  333. UNLOCK_RESOURCE( pfcb );
  334. //
  335. // Calculate the lana limits from the users NCB.
  336. //
  337. InParameters = (PRESET_PARAMETERS)&pdncb->ncb_callname;
  338. OutParameters = (PRESET_PARAMETERS)&pdncb->ncb_name;
  339. if ( InParameters->sessions == 0 ) {
  340. Sessions = 16;
  341. } else {
  342. if ( InParameters->sessions > MAXIMUM_CONNECTION ) {
  343. Sessions = MAXIMUM_CONNECTION;
  344. } else {
  345. Sessions = InParameters->sessions;
  346. }
  347. }
  348. if ( InParameters->commands == 0 ) {
  349. Commands = 16;
  350. } else {
  351. Commands = InParameters->commands;
  352. }
  353. if ( InParameters->names == 0 ) {
  354. Names = 8;
  355. } else {
  356. if ( InParameters->names > MAXIMUM_ADDRESS-2 ) {
  357. Names = MAXIMUM_ADDRESS-2;
  358. } else {
  359. Names = InParameters->names;
  360. }
  361. }
  362. Exclusive = (BOOLEAN)(InParameters->name0_reserved != 0);
  363. // Copy the parameters back into the NCB
  364. ASSERT( sizeof(RESET_PARAMETERS) == 16);
  365. RtlZeroMemory( OutParameters, sizeof( RESET_PARAMETERS ));
  366. OutParameters->sessions = Sessions;
  367. OutParameters->commands = Commands;
  368. OutParameters->names = Names;
  369. OutParameters->name0_reserved = (UCHAR)Exclusive;
  370. // Set all the configuration limits to their maximum.
  371. OutParameters->load_sessions = 255;
  372. OutParameters->load_commands = 255;
  373. OutParameters->load_names = MAXIMUM_ADDRESS;
  374. OutParameters->load_stations = 255;
  375. OutParameters->load_remote_names = 255;
  376. IF_NBDBG (NB_DEBUG_FILE) {
  377. NbPrint(("Lana:%x Sessions:%x Names:%x Commands:%x Reserved:%x\n",
  378. pdncb->ncb_lana_num,
  379. Sessions,
  380. Names,
  381. Commands,
  382. Exclusive));
  383. }
  384. //
  385. // Build the internal datastructures.
  386. //
  387. AdapterStatusMdl = IoAllocateMdl( &AdapterStatus,
  388. sizeof( AdapterStatus ),
  389. FALSE, // Secondary Buffer
  390. FALSE, // Charge Quota
  391. NULL);
  392. if ( AdapterStatusMdl == NULL ) {
  393. NCB_COMPLETE( pdncb, NRC_NORESOURCES );
  394. return;
  395. }
  396. BroadcastMdl = IoAllocateMdl( &BroadcastName,
  397. sizeof( BroadcastName ),
  398. FALSE, // Secondary Buffer
  399. FALSE, // Charge Quota
  400. NULL);
  401. if ( BroadcastMdl == NULL ) {
  402. IoFreeMdl( AdapterStatusMdl );
  403. NCB_COMPLETE( pdncb, NRC_NORESOURCES );
  404. return;
  405. }
  406. MmBuildMdlForNonPagedPool (AdapterStatusMdl);
  407. MmBuildMdlForNonPagedPool (BroadcastMdl);
  408. KeInitializeEvent (
  409. &Event1,
  410. SynchronizationEvent,
  411. FALSE);
  412. //
  413. // For each potential network, open the device driver and
  414. // obtain the reserved name and the broadcast address.
  415. //
  416. //
  417. // Open a handle for doing control functions
  418. //
  419. Status = NbOpenAddress (
  420. &TdiHandle, (PVOID*)&TdiObject,
  421. &usDeviceName, pdncb->ncb_lana_num, NULL
  422. );
  423. if (!NT_SUCCESS(Status)) {
  424. // Adapter not installed
  425. NCB_COMPLETE( pdncb, NRC_BRIDGE );
  426. goto exit;
  427. }
  428. LOCK_RESOURCE( pfcb );
  429. //
  430. // verify that device still exists. Here you cannot check the
  431. // Lana info structure for the lana (correponding to the device),
  432. // since it is expected to be NULL. Instead check that the device
  433. // name is valid.
  434. //
  435. if ( pfcb-> pDriverName[ pdncb->ncb_lana_num ].Buffer == NULL )
  436. {
  437. //
  438. // device presumed removed on account of unbind.
  439. //
  440. NCB_COMPLETE( pdncb, NRC_BRIDGE );
  441. UNLOCK_RESOURCE( pfcb );
  442. NbAddressClose( TdiHandle, TdiObject );
  443. goto exit;
  444. }
  445. if ( pfcb->ppLana[pdncb->ncb_lana_num] != NULL ) {
  446. // Attempting to open the lana twice in 2 threads.
  447. UNLOCK_RESOURCE( pfcb );
  448. NCB_COMPLETE( pdncb, NRC_TOOMANY );
  449. NbAddressClose( TdiHandle, TdiObject );
  450. goto exit;
  451. }
  452. plana = pfcb->ppLana[pdncb->ncb_lana_num] =
  453. ExAllocatePoolWithTag (NonPagedPool,
  454. sizeof(LANA_INFO), 'lSBN');
  455. if ( plana == (PLANA_INFO) NULL ) {
  456. UNLOCK_RESOURCE( pfcb );
  457. NCB_COMPLETE( pdncb, NRC_NORESOURCES );
  458. NbAddressClose( TdiHandle, TdiObject );
  459. goto exit;
  460. }
  461. plana->Signature = LANA_INFO_SIGNATURE;
  462. plana->Status = NB_INITIALIZING;
  463. plana->pFcb = pfcb;
  464. plana->ControlChannel = TdiHandle;
  465. for ( temp = 0; temp <= MAXIMUM_CONNECTION; temp++ ) {
  466. plana->ConnectionBlocks[temp] = NULL;
  467. }
  468. for ( temp = 0; temp <= MAXIMUM_ADDRESS; temp++ ) {
  469. plana->AddressBlocks[temp] = NULL;
  470. }
  471. InitializeListHead( &plana->LanAlertList);
  472. // Record the user specified limits in the Lana datastructure.
  473. plana->NextConnection = 1;
  474. plana->ConnectionCount = 0;
  475. plana->MaximumConnection = Sessions;
  476. plana->NextAddress = 2;
  477. plana->AddressCount = 0;
  478. plana->MaximumAddresses = Names;
  479. DeviceObject = IoGetRelatedDeviceObject( TdiObject );
  480. plana->ControlFileObject = TdiObject;
  481. plana->ControlDeviceObject = DeviceObject;
  482. SaveMdl = Irp->MdlAddress; // TdiBuildQuery modifies MdlAddress
  483. if ( Exclusive == TRUE ) {
  484. IF_NBDBG (NB_DEBUG_FILE) {
  485. NbPrint(("Query adapter status\n" ));
  486. }
  487. TdiBuildQueryInformation( Irp,
  488. DeviceObject,
  489. TdiObject,
  490. NbCompletionEvent,
  491. &Event1,
  492. TDI_QUERY_ADAPTER_STATUS,
  493. AdapterStatusMdl);
  494. Status = IoCallDriver (DeviceObject, Irp);
  495. if ( Status == STATUS_PENDING ) {
  496. do {
  497. Status = KeWaitForSingleObject(
  498. &Event1, Executive, KernelMode, TRUE, NULL
  499. );
  500. } while (Status == STATUS_ALERTED);
  501. if (!NT_SUCCESS(Status)) {
  502. NbAddressClose( TdiHandle, TdiObject );
  503. ExFreePool( plana );
  504. pfcb->ppLana[pdncb->ncb_lana_num] = NULL;
  505. UNLOCK_RESOURCE( pfcb );
  506. NCB_COMPLETE( pdncb, NRC_SYSTEM );
  507. goto exit;
  508. }
  509. Status = Irp->IoStatus.Status;
  510. }
  511. //
  512. // The transport may have extra names added so the buffer may be too short.
  513. // Ignore the too short problem since we will have all the data we require.
  514. //
  515. if (Status == STATUS_BUFFER_OVERFLOW) {
  516. Status = STATUS_SUCCESS;
  517. }
  518. }
  519. //
  520. // Now discover the broadcast address.
  521. //
  522. IF_NBDBG (NB_DEBUG_FILE) {
  523. NbPrint(("Query broadcast address\n" ));
  524. }
  525. if (NT_SUCCESS(Status)) {
  526. TdiBuildQueryInformation( Irp,
  527. DeviceObject,
  528. TdiObject,
  529. NbCompletionEvent,
  530. &Event1,
  531. TDI_QUERY_BROADCAST_ADDRESS,
  532. BroadcastMdl);
  533. Status = IoCallDriver (DeviceObject, Irp);
  534. if ( Status == STATUS_PENDING ) {
  535. do {
  536. Status = KeWaitForSingleObject(
  537. &Event1, Executive, KernelMode, TRUE, NULL
  538. );
  539. } while ( Status == STATUS_ALERTED );
  540. if (!NT_SUCCESS(Status)) {
  541. NbAddressClose( TdiHandle, TdiObject );
  542. ExFreePool( plana );
  543. pfcb->ppLana[pdncb->ncb_lana_num] = NULL;
  544. UNLOCK_RESOURCE( pfcb );
  545. NCB_COMPLETE( pdncb, NRC_SYSTEM );
  546. goto exit;
  547. }
  548. Status = Irp->IoStatus.Status;
  549. }
  550. }
  551. IF_NBDBG (NB_DEBUG_FILE) {
  552. NbPrint(("Query broadcast address returned:\n" ));
  553. NbFormattedDump(
  554. (PUCHAR)&BroadcastName,
  555. sizeof(BroadcastName) );
  556. }
  557. // Cleanup the callers Irp
  558. Irp->IoStatus.Status = STATUS_SUCCESS;
  559. Irp->MdlAddress = SaveMdl;
  560. if ( !NT_SUCCESS( Status )) {
  561. IF_NBDBG (NB_DEBUG_FILE) {
  562. NbPrint((" Astat or query broadcast returned error: %lx\n", Status ));
  563. }
  564. NbAddressClose( TdiHandle, TdiObject );
  565. ExFreePool( plana );
  566. pfcb->ppLana[pdncb->ncb_lana_num] = NULL;
  567. UNLOCK_RESOURCE( pfcb );
  568. NCB_COMPLETE( pdncb, NRC_SYSTEM );
  569. goto exit;
  570. }
  571. if ( Exclusive == TRUE) {
  572. int i;
  573. //
  574. // Grab exclusive access to the reserved address
  575. //
  576. //
  577. // We now have an adapter status structure containing the
  578. // prom address. Move the address to where NewAb looks and
  579. // pretend an addname has just been requested.
  580. //
  581. ncb.ncb_command = NCBADDRESERVED;
  582. ncb.ncb_lana_num = pdncb->ncb_lana_num;
  583. ncb.ncb_retcode = NRC_PENDING;
  584. for ( i=0; i<10 ; i++ ) {
  585. ncb.ncb_name[i] = '\0';
  586. }
  587. RtlMoveMemory( ncb.ncb_name+10,
  588. AdapterStatus.AdapterInformation.adapter_address,
  589. 6);
  590. //
  591. // It appears that NewAb is called while holding pfcb-> Resource.
  592. //
  593. NewAb( IrpSp, &ncb );
  594. if ( ncb.ncb_retcode != NRC_GOODRET ) {
  595. IF_NBDBG (NB_DEBUG_FILE) {
  596. NbPrint((" Add of reserved name failed Lana:%x\n", pdncb->ncb_lana_num));
  597. }
  598. plana->Status = NB_ABANDONED;
  599. UNLOCK_RESOURCE( pfcb );
  600. CleanupLana( pfcb, pdncb->ncb_lana_num, TRUE);
  601. NCB_COMPLETE( pdncb, NRC_SYSTEM );
  602. goto exit;
  603. }
  604. }
  605. //
  606. // Add the broadcast address. Use a special command code
  607. // to ensure address 255 is used.
  608. //
  609. ncb.ncb_length = BroadcastName.Address.Address[0].AddressLength;
  610. ncb.ncb_command = NCBADDBROADCAST;
  611. ncb.ncb_lana_num = pdncb->ncb_lana_num;
  612. ncb.ncb_retcode = NRC_PENDING;
  613. ncb.ncb_cmd_cplt = NRC_PENDING;
  614. RtlMoveMemory( ncb.ncb_name,
  615. ((PTDI_ADDRESS_NETBIOS)&BroadcastName.Address.Address[0].Address)->NetbiosName,
  616. NCBNAMSZ );
  617. //
  618. // It appears that NewAb is called while holding pfcb-> Resource.
  619. //
  620. NewAb( IrpSp, &ncb );
  621. if ( ncb.ncb_retcode != NRC_GOODRET ) {
  622. IF_NBDBG (NB_DEBUG_FILE) {
  623. NbPrint((" Add of broadcast name failed Lana:%x\n", pdncb->ncb_lana_num));
  624. }
  625. plana->Status = NB_ABANDONED;
  626. UNLOCK_RESOURCE( pfcb );
  627. CleanupLana( pfcb, pdncb->ncb_lana_num, TRUE);
  628. NCB_COMPLETE( pdncb, NRC_SYSTEM );
  629. goto exit;
  630. }
  631. plana->Status = NB_INITIALIZED;
  632. NCB_COMPLETE( pdncb, NRC_GOODRET );
  633. UNLOCK_RESOURCE( pfcb );
  634. exit:
  635. if ( AdapterStatusMdl != NULL )
  636. {
  637. IoFreeMdl( AdapterStatusMdl );
  638. }
  639. if ( BroadcastMdl != NULL )
  640. {
  641. IoFreeMdl( BroadcastMdl );
  642. }
  643. if ( usDeviceName.Buffer != NULL )
  644. {
  645. ExFreePool( usDeviceName.Buffer );
  646. }
  647. return;
  648. }
  649. VOID
  650. CleanupFcb(
  651. IN PIO_STACK_LOCATION IrpSp,
  652. IN PFCB pfcb
  653. )
  654. /*++
  655. Routine Description:
  656. This deletes any Connection Blocks pointed to by the File Control Block
  657. and then deletes the File Control Block. This routine is only called
  658. when a close IRP has been received.
  659. Arguments:
  660. IrpSp - Pointer to current IRP stack frame.
  661. pfcb - Pointer to the Fcb to be deallocated.
  662. Return Value:
  663. nothing.
  664. --*/
  665. {
  666. NTSTATUS nsStatus;
  667. ULONG lana_index;
  668. PLIST_ENTRY ple = NULL;
  669. PFCB_ENTRY pfe = NULL;
  670. PAGED_CODE();
  671. //
  672. // To receive a Close Irp, the IO system has determined that there
  673. // are no handles open in the driver. To avoid some race conditions
  674. // in this area, we always have an Irp when queueing work to the Fsp.
  675. // this prevents structures disappearing on the Fsp and also makes
  676. // it easier to cleanup in this routine.
  677. //
  678. //
  679. // for each network adapter that is allocated, close all addresses
  680. // and connections, deleting any memory that is allocated.
  681. //
  682. IF_NBDBG (NB_DEBUG_FILE) {
  683. NbPrint(("CleanupFcb:%lx\n", pfcb ));
  684. }
  685. //
  686. // remove FCB pointer from the global list of FCB pointers
  687. //
  688. LOCK_GLOBAL();
  689. for ( ple = g_leFCBList.Flink; ple != &g_leFCBList; ple = ple-> Flink )
  690. {
  691. pfe = (PFCB_ENTRY) CONTAINING_RECORD( ple, FCB_ENTRY, leList );
  692. if ( pfe-> pfcb == pfcb )
  693. {
  694. RemoveEntryList( ple );
  695. ExFreePool( pfe );
  696. IF_NBDBG (NB_DEBUG_CREATE_FILE)
  697. {
  698. NbPrint( ("Netbios FCB entry removed from global list\n" ) );
  699. }
  700. break;
  701. }
  702. }
  703. UNLOCK_GLOBAL();
  704. //
  705. // FCB pointed to by pfcb is now free from access by bind/unbind handlers.
  706. //
  707. LOCK_RESOURCE( pfcb );
  708. if ( pfcb->TimerRunning == TRUE ) {
  709. KEVENT TimerCancelled;
  710. KeInitializeEvent (
  711. &TimerCancelled,
  712. SynchronizationEvent,
  713. FALSE);
  714. pfcb->TimerCancelled = &TimerCancelled;
  715. pfcb->TimerRunning = FALSE;
  716. UNLOCK_RESOURCE( pfcb );
  717. if ( KeCancelTimer (&pfcb->Timer) == FALSE ) {
  718. //
  719. // The timeout was in the Dpc queue. Wait for it to be
  720. // processed before continuing.
  721. //
  722. do {
  723. nsStatus = KeWaitForSingleObject(
  724. &TimerCancelled, Executive, KernelMode,
  725. TRUE, NULL
  726. );
  727. } while (nsStatus == STATUS_ALERTED);
  728. }
  729. } else {
  730. UNLOCK_RESOURCE( pfcb );
  731. }
  732. for ( lana_index = 0; lana_index <= pfcb->MaxLana; lana_index++ ) {
  733. CleanupLana( pfcb, lana_index, TRUE);
  734. if ( pfcb-> pDriverName[ lana_index ].Buffer != NULL )
  735. {
  736. ExFreePool( pfcb-> pDriverName[ lana_index ].Buffer );
  737. }
  738. }
  739. ExDeleteResourceLite( &pfcb->Resource );
  740. ExDeleteResourceLite( &pfcb->AddResource );
  741. IrpSp->FileObject->FsContext2 = NULL;
  742. ExFreePool( pfcb-> pDriverName );
  743. ExFreePool( pfcb->ppLana );
  744. //
  745. // Free the work item
  746. //
  747. IoFreeWorkItem( pfcb->WorkEntry );
  748. ExFreePool( pfcb );
  749. }
  750. VOID
  751. CleanupLana(
  752. IN PFCB pfcb,
  753. IN ULONG lana_index,
  754. IN BOOLEAN delete
  755. )
  756. /*++
  757. Routine Description:
  758. This routine completes all the requests on a particular adapter. It
  759. removes all connections and addresses.
  760. Arguments:
  761. pfcb - Pointer to the Fcb to be deallocated.
  762. lana_index - supplies the adapter to be cleaned.
  763. delete - if TRUE the memory for the lana structure should be freed.
  764. Return Value:
  765. nothing.
  766. --*/
  767. {
  768. PLANA_INFO plana;
  769. int index;
  770. KIRQL OldIrql; // Used when SpinLock held.
  771. PDNCB pdncb;
  772. LOCK( pfcb, OldIrql );
  773. plana = pfcb->ppLana[lana_index];
  774. if ( plana != NULL ) {
  775. IF_NBDBG (NB_DEBUG_FILE) {
  776. NbPrint((" CleanupLana pfcb: %lx lana %lx\n", pfcb, lana_index ));
  777. }
  778. if (( plana->Status == NB_INITIALIZING ) ||
  779. ( plana->Status == NB_DELETING )) {
  780. // Possibly trying to reset it twice?
  781. UNLOCK( pfcb, OldIrql );
  782. return;
  783. }
  784. plana->Status = NB_DELETING;
  785. // Cleanup the control channel and abandon any tdi-action requests.
  786. if ( plana->ControlChannel != NULL ) {
  787. UNLOCK_SPINLOCK( pfcb, OldIrql );
  788. IF_NBDBG( NB_DEBUG_CALL )
  789. {
  790. NbPrint( (
  791. "NbAddressClose : Close file invoked for %d\n",
  792. lana_index
  793. ) );
  794. NbPrint( ( "Control channel\n" ) );
  795. }
  796. NbAddressClose( plana->ControlChannel, plana->ControlFileObject );
  797. LOCK_SPINLOCK( pfcb, OldIrql );
  798. plana->ControlChannel = NULL;
  799. }
  800. while ( (pdncb = DequeueRequest( &plana->LanAlertList)) != NULL ) {
  801. //
  802. // Any error will do since the user is closing \Device\Netbios
  803. // and is therefore exiting.
  804. //
  805. NCB_COMPLETE( pdncb, NRC_SCLOSED );
  806. pdncb->irp->IoStatus.Information = FIELD_OFFSET( DNCB, ncb_cmd_cplt );
  807. NbCompleteRequest( pdncb->irp, STATUS_SUCCESS );
  808. }
  809. for ( index = 0; index <= MAXIMUM_CONNECTION; index++) {
  810. if ( plana->ConnectionBlocks[index] != NULL ) {
  811. IF_NBDBG (NB_DEBUG_FILE) {
  812. NbPrint(("Call CleanupCb Lana:%x Lsn: %x\n", lana_index, index ));
  813. }
  814. plana->ConnectionBlocks[index]->DisconnectReported = TRUE;
  815. UNLOCK_SPINLOCK( pfcb, OldIrql ); // Allow NtClose in Cleanup routines.
  816. CleanupCb( &plana->ConnectionBlocks[index], NULL );
  817. LOCK_SPINLOCK( pfcb, OldIrql ); // Allow NtClose in Cleanup routines.
  818. }
  819. }
  820. for ( index = 0; index <= MAXIMUM_ADDRESS; index++ ) {
  821. if ( plana->AddressBlocks[index] != NULL ) {
  822. IF_NBDBG (NB_DEBUG_FILE) {
  823. NbPrint((" CleanupAb Lana:%x index: %x\n", lana_index, index ));
  824. }
  825. UNLOCK_SPINLOCK( pfcb, OldIrql ); // Allow NtClose in Cleanup routines.
  826. CleanupAb( &plana->AddressBlocks[index], TRUE );
  827. LOCK_SPINLOCK( pfcb, OldIrql ); // Allow NtClose in Cleanup routines.
  828. }
  829. }
  830. if ( delete == TRUE ) {
  831. pfcb->ppLana[lana_index] = NULL;
  832. ExFreePool( plana );
  833. }
  834. }
  835. UNLOCK( pfcb, OldIrql );
  836. }
  837. //----------------------------------------------------------------------------
  838. // NbTdiBindHandler
  839. //
  840. // Call back function that process a TDI bind notification that indicates
  841. // a new device has been created.
  842. //----------------------------------------------------------------------------
  843. VOID
  844. NbBindHandler(
  845. IN TDI_PNP_OPCODE PnPOpcode,
  846. IN PUNICODE_STRING DeviceName,
  847. IN PWSTR MultiSZBindList
  848. )
  849. {
  850. PWSTR pwCur = NULL;
  851. if ( PnPOpcode == TDI_PNP_OP_ADD )
  852. {
  853. NbTdiBindHandler( DeviceName, MultiSZBindList );
  854. }
  855. else if ( PnPOpcode == TDI_PNP_OP_DEL )
  856. {
  857. NbTdiUnbindHandler( DeviceName );
  858. }
  859. }
  860. //----------------------------------------------------------------------------
  861. // NbTdiPowerHandler
  862. //
  863. // Call back function that process a TDI bind notification that indicates
  864. // a new device has been created.
  865. //----------------------------------------------------------------------------
  866. NTSTATUS
  867. NbPowerHandler(
  868. IN PUNICODE_STRING pusDeviceName,
  869. IN PNET_PNP_EVENT pnpeEvent,
  870. IN PTDI_PNP_CONTEXT ptpcContext1,
  871. IN PTDI_PNP_CONTEXT ptpcContext2
  872. )
  873. {
  874. return STATUS_SUCCESS;
  875. }
  876. //----------------------------------------------------------------------------
  877. // NbTdiBindHandler
  878. //
  879. // Call back function that process a TDI bind notification that indicates
  880. // a new device has been created.
  881. //----------------------------------------------------------------------------
  882. VOID
  883. NbTdiBindHandler(
  884. IN PUNICODE_STRING pusDeviceName,
  885. IN PWSTR pwszMultiSZBindList
  886. )
  887. {
  888. NTSTATUS nsStatus;
  889. UCHAR ucInd = 0, ucIndex = 0, ucNewLana = 0, ucLana = 0;
  890. BOOLEAN bRes = FALSE;
  891. ULONG ulMaxLana = 0;
  892. PWSTR pwszBind = NULL;
  893. UNICODE_STRING usCurDevice;
  894. PKEY_VALUE_FULL_INFORMATION pkvfi = NULL;
  895. PLANA_MAP pLanaMap = NULL;
  896. PLIST_ENTRY ple = NULL;
  897. PFCB_ENTRY pfe = NULL;
  898. PFCB pfcb = NULL;
  899. #if AUTO_RESET
  900. PRESET_LANA_ENTRY prle;
  901. #endif
  902. PAGED_CODE();
  903. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  904. {
  905. NbPrint( (
  906. "\n++++ Netbios : TdiBindHandler : entered for device : %ls ++++\n",
  907. pusDeviceName-> Buffer
  908. ) );
  909. }
  910. do
  911. {
  912. //
  913. // read the registry for the Lana Map
  914. //
  915. nsStatus = GetLanaMap( &g_usRegistryPath, &pkvfi );
  916. if ( !NT_SUCCESS( nsStatus ) )
  917. {
  918. NbPrint( (
  919. "Netbios : GetLanaMap failed with status %lx\n", nsStatus
  920. ) );
  921. break;
  922. }
  923. pLanaMap = (PLANA_MAP) ( (PUCHAR) pkvfi + pkvfi-> DataOffset );
  924. //
  925. // get Max Lana
  926. //
  927. nsStatus = GetMaxLana( &g_usRegistryPath, &ulMaxLana );
  928. if ( !NT_SUCCESS( nsStatus ) )
  929. {
  930. NbPrint( (
  931. "Netbios : GetMaxLana failed with status %lx\n", nsStatus
  932. ) );
  933. break;
  934. }
  935. //
  936. // figure out Lana for this device. Verify that it is enumerated.
  937. //
  938. ucIndex = 0;
  939. pwszBind = pwszMultiSZBindList;
  940. while ( *pwszBind != 0 )
  941. {
  942. RtlInitUnicodeString( &usCurDevice, pwszBind );
  943. if ( !RtlCompareUnicodeString(
  944. &usCurDevice,
  945. pusDeviceName,
  946. FALSE
  947. ) )
  948. {
  949. //
  950. // new device found
  951. //
  952. bRes = TRUE;
  953. break;
  954. }
  955. ucIndex++;
  956. pwszBind += wcslen( pwszBind ) + 1;
  957. }
  958. //
  959. // if device was not found error out
  960. //
  961. if ( !bRes )
  962. {
  963. NbPrint( (
  964. "Netbios : device %ls not found in bind string\n",
  965. pusDeviceName-> Buffer
  966. ) );
  967. break;
  968. }
  969. //
  970. // verify lana number is valid
  971. //
  972. if ( pLanaMap[ ucIndex ].Lana > ulMaxLana )
  973. {
  974. NbPrint( (
  975. "Netbios : Device lana %d, Max Lana %d\n",
  976. pLanaMap[ ucIndex ].Lana, ulMaxLana
  977. ) );
  978. break;
  979. }
  980. //
  981. // open device to ensure that it works.
  982. //
  983. bRes = NbCheckLana ( pusDeviceName );
  984. if ( !bRes )
  985. {
  986. NbPrint( (
  987. "Netbios : NbCheckLana failed to open device %ls\n",
  988. pusDeviceName-> Buffer
  989. ) );
  990. break;
  991. }
  992. //
  993. // create a copy of this device name.
  994. //
  995. nsStatus = AllocateAndCopyUnicodeString(
  996. &usCurDevice,
  997. pusDeviceName
  998. );
  999. if ( !NT_SUCCESS( nsStatus ) )
  1000. {
  1001. NbPrint( (
  1002. "Netbios : Failed to allocate for global device name %x\n",
  1003. nsStatus
  1004. ) );
  1005. break;
  1006. }
  1007. ucNewLana = pLanaMap[ ucIndex ].Lana;
  1008. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1009. {
  1010. NbPrint( ("Netbios : Lana for device is %d\n", ucNewLana ) );
  1011. }
  1012. //
  1013. // update global info.
  1014. //
  1015. LOCK_GLOBAL();
  1016. //
  1017. // verify that lana is not previously used.
  1018. //
  1019. if ( g_pusActiveDeviceList[ ucNewLana ].Buffer != NULL )
  1020. {
  1021. NbPrint( (
  1022. "Netbios : Lana %d already in use by %ls\n",
  1023. ucNewLana, g_pusActiveDeviceList[ ucNewLana ].Buffer
  1024. ) );
  1025. UNLOCK_GLOBAL();
  1026. ExFreePool(usCurDevice.Buffer);
  1027. break;
  1028. }
  1029. //
  1030. // update maxlana
  1031. // update lana enum if device is enumerated.
  1032. //
  1033. g_ulMaxLana = ulMaxLana;
  1034. if ( pLanaMap[ ucIndex ].Enum )
  1035. {
  1036. g_leLanaEnum.lana[ g_leLanaEnum.length ] = ucNewLana;
  1037. g_leLanaEnum.length++;
  1038. }
  1039. //
  1040. // add to active device list
  1041. //
  1042. RtlInitUnicodeString(
  1043. &g_pusActiveDeviceList[ ucNewLana ], usCurDevice.Buffer
  1044. );
  1045. //
  1046. // for each FCB
  1047. // Acquire locks
  1048. // update MaxLana
  1049. // update LanaEnum
  1050. // update driver list
  1051. //
  1052. for ( ple = g_leFCBList.Flink; ple != &g_leFCBList; ple = ple-> Flink )
  1053. {
  1054. pfe = (PFCB_ENTRY) CONTAINING_RECORD( ple, FCB_ENTRY, leList );
  1055. pfcb = pfe-> pfcb;
  1056. LOCK_RESOURCE( pfcb );
  1057. //
  1058. // Add device name to list of drivers for this FCB.
  1059. // If allocation fails for any FCB stop adding to any further
  1060. // FCBs you are out of memory
  1061. //
  1062. nsStatus = AllocateAndCopyUnicodeString(
  1063. &pfcb-> pDriverName[ ucNewLana ],
  1064. pusDeviceName
  1065. );
  1066. if ( !NT_SUCCESS( nsStatus ) )
  1067. {
  1068. NbPrint( (
  1069. "Netbios : Failed to allocate for device name %x\n",
  1070. nsStatus
  1071. ) );
  1072. UNLOCK_RESOURCE( pfcb );
  1073. break;
  1074. }
  1075. else
  1076. {
  1077. pfcb-> MaxLana = ulMaxLana;
  1078. pfcb-> LanaEnum.lana[ pfcb-> LanaEnum.length ] = ucNewLana;
  1079. pfcb-> LanaEnum.length++;
  1080. }
  1081. IF_NBDBG( NB_DEBUG_LIST_LANA )
  1082. {
  1083. DumpDeviceList( pfcb );
  1084. }
  1085. UNLOCK_RESOURCE( pfcb );
  1086. #if AUTO_RESET
  1087. //
  1088. // add this list of lana to be reset
  1089. //
  1090. prle = ExAllocatePoolWithTag(
  1091. NonPagedPool, sizeof( RESET_LANA_ENTRY ), 'fSBN'
  1092. );
  1093. if ( prle == NULL )
  1094. {
  1095. NbPrint( ("Failed to allocate RESET_LANA_ENTRY\n") );
  1096. continue;
  1097. }
  1098. InitializeListHead( &prle-> leList );
  1099. prle-> ucLanaNum = ucNewLana;
  1100. InsertTailList( &pfe-> leResetList, &prle-> leList );
  1101. //
  1102. // Notify the user mode apps that a new LANA has been added.
  1103. //
  1104. NotifyUserModeNetbios( pfe );
  1105. #endif
  1106. }
  1107. UNLOCK_GLOBAL();
  1108. } while ( FALSE );
  1109. //
  1110. // deallocate LanaMap
  1111. //
  1112. if ( pkvfi != NULL )
  1113. {
  1114. ExFreePool( pkvfi );
  1115. }
  1116. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1117. {
  1118. NbPrint( (
  1119. "\n---- Netbios : TdiBindHandler exited for device : %ls ----\n",
  1120. pusDeviceName-> Buffer
  1121. ) );
  1122. }
  1123. return;
  1124. }
  1125. //----------------------------------------------------------------------------
  1126. // NbTdiUnbindHandler
  1127. //
  1128. // Call back function that process a TDI unbind notification that indicates
  1129. // a device has been removed.
  1130. //----------------------------------------------------------------------------
  1131. VOID
  1132. NbTdiUnbindHandler(
  1133. IN PUNICODE_STRING pusDeviceName
  1134. )
  1135. {
  1136. UCHAR ucLana = 0, ucInd = 0;
  1137. ULONG ulMaxLana;
  1138. PLIST_ENTRY ple = NULL;
  1139. PFCB_ENTRY pfe = NULL;
  1140. PFCB pfcb = NULL;
  1141. NTSTATUS nsStatus;
  1142. PAGED_CODE();
  1143. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1144. {
  1145. NbPrint( (
  1146. "\n++++ Netbios : TdiUnbindHandler : entered for device : %ls ++++\n",
  1147. pusDeviceName-> Buffer
  1148. ) );
  1149. }
  1150. do
  1151. {
  1152. //
  1153. // Acquire Global lock
  1154. //
  1155. LOCK_GLOBAL();
  1156. //
  1157. // find device in global active device list and remove it.
  1158. //
  1159. for ( ucLana = 0; ucLana <= g_ulMaxLana; ucLana++ )
  1160. {
  1161. if ( g_pusActiveDeviceList[ ucLana ].Buffer == NULL )
  1162. {
  1163. continue;
  1164. }
  1165. if ( !RtlCompareUnicodeString(
  1166. &g_pusActiveDeviceList[ ucLana ],
  1167. pusDeviceName,
  1168. FALSE
  1169. ) )
  1170. {
  1171. ExFreePool( g_pusActiveDeviceList[ ucLana ].Buffer );
  1172. RtlInitUnicodeString( &g_pusActiveDeviceList[ ucLana ], NULL );
  1173. break;
  1174. }
  1175. }
  1176. //
  1177. // device was not found. There is nothing more to be done.
  1178. //
  1179. if ( ucLana > g_ulMaxLana )
  1180. {
  1181. UNLOCK_GLOBAL();
  1182. NbPrint( (
  1183. "Netbios : device not found %ls\n", pusDeviceName-> Buffer
  1184. ) );
  1185. break;
  1186. }
  1187. //
  1188. // Update Max Lana
  1189. //
  1190. nsStatus = GetMaxLana( &g_usRegistryPath, &g_ulMaxLana );
  1191. if ( !NT_SUCCESS( nsStatus ) )
  1192. {
  1193. UNLOCK_GLOBAL();
  1194. NbPrint( (
  1195. "Netbios : GetMaxLana failed with status %lx\n", nsStatus
  1196. ) );
  1197. break;
  1198. }
  1199. //
  1200. // update global Lana enum
  1201. //
  1202. for ( ucInd = 0; ucInd < g_leLanaEnum.length; ucInd++ )
  1203. {
  1204. if ( ucLana == g_leLanaEnum.lana[ ucInd ] )
  1205. {
  1206. break;
  1207. }
  1208. }
  1209. if ( ucInd < g_leLanaEnum.length )
  1210. {
  1211. //
  1212. // device present in Lana Enum. Remove it
  1213. // by sliding over the rest of the lana enum.
  1214. //
  1215. RtlCopyBytes(
  1216. &g_leLanaEnum.lana[ ucInd ],
  1217. &g_leLanaEnum.lana[ ucInd + 1],
  1218. g_leLanaEnum.length - ucInd - 1
  1219. );
  1220. g_leLanaEnum.length--;
  1221. }
  1222. //
  1223. // Walk the list of FCB and remove this device from each FCB.
  1224. // clean up for this resource.
  1225. //
  1226. for ( ple = g_leFCBList.Flink; ple != &g_leFCBList; ple = ple-> Flink )
  1227. {
  1228. pfe = (PFCB_ENTRY) CONTAINING_RECORD( ple, FCB_ENTRY, leList );
  1229. pfcb = pfe-> pfcb;
  1230. //
  1231. // update max lana, lana enum.
  1232. // delete device name and cleanup lana
  1233. //
  1234. LOCK_RESOURCE( pfcb );
  1235. //
  1236. // update global structures
  1237. //
  1238. pfcb-> MaxLana = g_ulMaxLana;
  1239. RtlCopyMemory( &pfcb-> LanaEnum, &g_leLanaEnum, sizeof( LANA_ENUM ) );
  1240. //
  1241. // remove device from list of active device
  1242. //
  1243. if ( pfcb-> pDriverName[ ucLana ].Buffer != NULL )
  1244. {
  1245. ExFreePool( pfcb-> pDriverName[ ucLana ].Buffer );
  1246. RtlInitUnicodeString( &pfcb-> pDriverName[ ucLana ], NULL );
  1247. }
  1248. IF_NBDBG( NB_DEBUG_LIST_LANA )
  1249. {
  1250. DumpDeviceList( pfcb );
  1251. }
  1252. //
  1253. // clean up lana info for this device.
  1254. //
  1255. if ( pfcb-> ppLana[ ucLana ] != NULL )
  1256. {
  1257. UNLOCK_RESOURCE( pfcb );
  1258. CleanupLana( pfcb, ucLana, TRUE );
  1259. }
  1260. else
  1261. {
  1262. UNLOCK_RESOURCE( pfcb );
  1263. }
  1264. }
  1265. UNLOCK_GLOBAL();
  1266. } while ( FALSE );
  1267. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1268. {
  1269. NbPrint( (
  1270. "\n---- Netbios : TdiUnbindHandler : exited for device : %ls ----\n",
  1271. pusDeviceName-> Buffer
  1272. ) );
  1273. }
  1274. return;
  1275. }
  1276. #if AUTO_RESET
  1277. VOID
  1278. NotifyUserModeNetbios(
  1279. IN PFCB_ENTRY pfe
  1280. )
  1281. /*++
  1282. Description :
  1283. This routine notifies the mode component of NETBIOS in NETAPI32.DLL
  1284. of new LANAs that have been bound to NETBIOS. This is done by
  1285. completing IRPs that have been pended with the kernel mode component.
  1286. Arguements :
  1287. pfe - Pointer to FCB entry.
  1288. Return Value :
  1289. None
  1290. Environment :
  1291. Called in the context of the TDI bind handler. Assumes that the GLOBAL
  1292. resource lock is held when invoking this call.
  1293. --*/
  1294. {
  1295. NTSTATUS ntStatus = STATUS_SUCCESS;
  1296. PIRP pIrp;
  1297. KIRQL irql;
  1298. PLIST_ENTRY ple, pleNode;
  1299. PRESET_LANA_ENTRY prle;
  1300. PNCB pUsersNCB;
  1301. #if defined(_WIN64)
  1302. PNCB32 pUsersNCB32;
  1303. #endif
  1304. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1305. {
  1306. NbPrint(
  1307. ("\n++++ Netbios : ENTERED NotifyUserModeNetbios : %p ++++\n", pfe)
  1308. );
  1309. }
  1310. //
  1311. // Complete each of the pending IRPs to signal the reset lana event.
  1312. // This causes netapi32.dll to reset the specified LANA
  1313. //
  1314. if ( !IsListEmpty( &pfe-> leResetIrp ) )
  1315. {
  1316. //
  1317. // get the first LANA that needs resetting
  1318. //
  1319. ple = RemoveHeadList( &pfe-> leResetList );
  1320. prle = CONTAINING_RECORD( ple, RESET_LANA_ENTRY, leList );
  1321. //
  1322. // Acquire the spin lock for the IRP
  1323. //
  1324. IoAcquireCancelSpinLock( &irql );
  1325. pleNode = RemoveHeadList( &pfe-> leResetIrp );
  1326. pIrp = CONTAINING_RECORD( pleNode, IRP, Tail.Overlay.ListEntry );
  1327. IoSetCancelRoutine( pIrp, NULL );
  1328. pIrp->IoStatus.Status = STATUS_SUCCESS;
  1329. //
  1330. // Return the LANA number.
  1331. //
  1332. #if defined(_WIN64)
  1333. if (IoIs32bitProcess(pIrp))
  1334. {
  1335. pUsersNCB32 = (PNCB32) pIrp-> AssociatedIrp.SystemBuffer;
  1336. pUsersNCB32->ncb_lana_num = prle-> ucLanaNum;
  1337. pIrp->IoStatus.Information = sizeof( NCB32 );
  1338. }
  1339. else
  1340. #else
  1341. {
  1342. pUsersNCB = (PNCB) pIrp-> AssociatedIrp.SystemBuffer;
  1343. pUsersNCB->ncb_lana_num = prle-> ucLanaNum;
  1344. pIrp->IoStatus.Information = sizeof( NCB );
  1345. }
  1346. #endif
  1347. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1348. {
  1349. NbPrint(
  1350. ("\n++++ Netbios : IRP %p, LANA %d\n", pIrp, prle-> ucLanaNum)
  1351. );
  1352. NbPrint(
  1353. ("Output Buffer %p, System Buffer %p ++++\n",
  1354. pIrp-> UserBuffer, pIrp-> AssociatedIrp.SystemBuffer )
  1355. );
  1356. }
  1357. //
  1358. // release lock to complete the IRP
  1359. //
  1360. IoReleaseCancelSpinLock( irql );
  1361. IoCompleteRequest( pIrp, IO_NETWORK_INCREMENT );
  1362. }
  1363. IF_NBDBG( NB_DEBUG_CREATE_FILE )
  1364. {
  1365. NbPrint(
  1366. ("\n++++ Netbios : EXITING NotifyUserModeNetbios : %p ++++\n", pfe)
  1367. );
  1368. }
  1369. }
  1370. #endif
  1371. VOID
  1372. DumpDeviceList(
  1373. IN PFCB pfcb
  1374. )
  1375. {
  1376. UCHAR ucInd = 0, ucInd1 = 0;
  1377. //
  1378. // for each Lana, print device name, lana, enumerated or not.
  1379. //
  1380. NbPrint( (
  1381. "\n++++ Netbios : list of current devices ++++\n"
  1382. ) );
  1383. for ( ucInd = 0; ucInd <= pfcb-> MaxLana; ucInd++ )
  1384. {
  1385. if ( pfcb-> pDriverName[ucInd].Buffer == NULL )
  1386. {
  1387. continue;
  1388. }
  1389. NbPrint( ( "Lana : %d\t", ucInd ) );
  1390. for ( ucInd1 = 0; ucInd1 < pfcb-> LanaEnum.length; ucInd1++ )
  1391. {
  1392. if ( pfcb-> LanaEnum.lana[ ucInd1 ] == ucInd )
  1393. {
  1394. break;
  1395. }
  1396. }
  1397. if ( ucInd1 < pfcb-> LanaEnum.length )
  1398. {
  1399. NbPrint( ( "Enabled \t" ) );
  1400. }
  1401. else
  1402. {
  1403. NbPrint( ( "Disabled\t" ) );
  1404. }
  1405. NbPrint( ( "%ls\n", pfcb-> pDriverName[ ucInd ].Buffer ) );
  1406. }
  1407. NbPrint( ("++++++++++++++++++++++++++++++++++++++++++++++++++\n" ) );
  1408. }