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.

1754 lines
52 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. Driver.c
  5. Abstract:
  6. This module implements the DRIVER_INITIALIZATION routine for the
  7. NBT Transport and other routines that are specific to the NT implementation
  8. of a driver.
  9. Author:
  10. Jim Stewart (Jimst) 10-2-92
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include <nbtioctl.h>
  15. #include "driver.tmh"
  16. #if DBG
  17. // allocate storage for the global debug flag NbtDebug
  18. //ULONG NbtDebug = NBT_DEBUG_KDPRINTS| NBT_DEBUG_NETBIOS_EX;
  19. ULONG NbtDebug = 0;
  20. #endif // DBG
  21. NTSTATUS
  22. DriverEntry(
  23. IN PDRIVER_OBJECT DriverObject,
  24. IN PUNICODE_STRING RegistryPath
  25. );
  26. NTSTATUS
  27. NbtDispatchCleanup(
  28. IN PDEVICE_OBJECT Device,
  29. IN PIRP pIrp
  30. );
  31. NTSTATUS
  32. NbtDispatchClose(
  33. IN PDEVICE_OBJECT device,
  34. IN PIRP pIrp
  35. );
  36. NTSTATUS
  37. NbtDispatchCreate(
  38. IN PDEVICE_OBJECT Device,
  39. IN PIRP pIrp
  40. );
  41. NTSTATUS
  42. NbtDispatchDevCtrl(
  43. IN PDEVICE_OBJECT device,
  44. IN PIRP pIrp
  45. );
  46. NTSTATUS
  47. NbtDispatchInternalCtrl(
  48. IN PDEVICE_OBJECT device,
  49. IN PIRP pIrp
  50. );
  51. #ifdef _PNP_POWER_
  52. VOID
  53. NbtUnload(
  54. IN PDRIVER_OBJECT device
  55. );
  56. #endif // _PNP_POWER_
  57. NTSTATUS
  58. NbtDispatchPnP(
  59. IN PDEVICE_OBJECT Device,
  60. IN PIRP pIrp
  61. );
  62. PFILE_FULL_EA_INFORMATION
  63. FindInEA(
  64. IN PFILE_FULL_EA_INFORMATION start,
  65. IN PCHAR wanted
  66. );
  67. VOID
  68. ReturnIrp(
  69. IN PIRP pIrp,
  70. IN int status
  71. );
  72. VOID
  73. MakePending(
  74. IN PIRP pIrp
  75. );
  76. NTSTATUS
  77. NbtCreateAdminSecurityDescriptor(
  78. IN PDEVICE_OBJECT dev
  79. );
  80. #ifdef _PNP_POWER_DBG_
  81. //
  82. //Debug Stuff for DbgBreakPoint -- REMOVE
  83. //
  84. NTSTATUS
  85. NbtOpenRegistry(
  86. IN HANDLE NbConfigHandle,
  87. IN PWSTR String,
  88. OUT PHANDLE pHandle
  89. );
  90. #endif // _PNP_POWER_DBG_
  91. #ifdef _PNP_POWER_
  92. HANDLE TdiClientHandle = NULL;
  93. HANDLE TdiProviderHandle = NULL;
  94. extern tTIMERQ TimerQ;
  95. #endif // _PNP_POWER_
  96. #ifdef _NETBIOSLESS
  97. tDEVICECONTEXT *pNbtSmbDevice = NULL;
  98. #endif // _NETBIOSLESS
  99. //******************* Pageable Routine Declarations ****************
  100. #ifdef ALLOC_PRAGMA
  101. #pragma CTEMakePageable(INIT, DriverEntry)
  102. #pragma CTEMakePageable(PAGE, NbtDispatchCleanup)
  103. #pragma CTEMakePageable(PAGE, NbtDispatchClose)
  104. #pragma CTEMakePageable(PAGE, NbtDispatchCreate)
  105. #pragma CTEMakePageable(PAGE, NbtDispatchDevCtrl)
  106. #pragma CTEMakePageable(PAGE, FindInEA)
  107. #pragma CTEMakePageable(PAGE, NbtUnload)
  108. #endif
  109. //******************* Pageable Routine Declarations ****************
  110. //----------------------------------------------------------------------------
  111. VOID
  112. CleanupDriverEntry(
  113. ULONG CleanupStage
  114. )
  115. {
  116. PSINGLE_LIST_ENTRY pSingleListEntry;
  117. PMDL pMdl;
  118. PVOID pBuffer;
  119. LIST_ENTRY *pListEntry;
  120. tDGRAM_SEND_TRACKING *pTracker;
  121. switch (CleanupStage)
  122. {
  123. case (6):
  124. NbtDestroyDevice (pWinsDeviceContext, FALSE);
  125. #ifdef RASAUTODIAL
  126. //
  127. // Unbind fron the RAS driver if we were bound
  128. //
  129. NbtAcdUnbind ();
  130. #endif // RASAUTODIAL
  131. // Fall through
  132. case (5):
  133. if (pNbtSmbDevice)
  134. {
  135. NbtDestroyDevice (pNbtSmbDevice, FALSE);
  136. pNbtSmbDevice = NULL;
  137. }
  138. if (NbtConfig.OutOfRsrc.pDpc)
  139. {
  140. CTEMemFree (NbtConfig.OutOfRsrc.pDpc);
  141. }
  142. if (NbtConfig.OutOfRsrc.pIrp)
  143. {
  144. IoFreeIrp (NbtConfig.OutOfRsrc.pIrp);
  145. }
  146. // Fall through
  147. case (4):
  148. while (NbtConfig.SessionMdlFreeSingleList.Next)
  149. {
  150. pSingleListEntry = PopEntryList(&NbtConfig.SessionMdlFreeSingleList);
  151. pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  152. pBuffer = MmGetMdlVirtualAddress (pMdl);
  153. CTEMemFree (pBuffer);
  154. IoFreeMdl (pMdl);
  155. }
  156. while (NbtConfig.DgramMdlFreeSingleList.Next)
  157. {
  158. pSingleListEntry = PopEntryList(&NbtConfig.DgramMdlFreeSingleList);
  159. pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  160. pBuffer = MmGetMdlVirtualAddress (pMdl);
  161. CTEMemFree (pBuffer);
  162. IoFreeMdl (pMdl);
  163. }
  164. // Fall through
  165. case (3):
  166. //
  167. // InitNotOs has been called
  168. //
  169. DestroyTimerQ();
  170. while (!IsListEmpty(&NbtConfig.DgramTrackerFreeQ))
  171. {
  172. pListEntry = RemoveHeadList(&NbtConfig.DgramTrackerFreeQ);
  173. pTracker = CONTAINING_RECORD(pListEntry,tDGRAM_SEND_TRACKING,Linkage);
  174. CTEMemFree (pTracker);
  175. }
  176. DestroyHashTables ();
  177. ExDeleteResourceLite (&NbtConfig.Resource); // Delete the resource
  178. // Fall through
  179. case (2):
  180. //
  181. // Read registry has been called!
  182. //
  183. CTEMemFree (NbtConfig.pLmHosts);
  184. CTEMemFree (NbtConfig.pScope);
  185. if (NbtConfig.pTcpBindName)
  186. {
  187. CTEMemFree (NbtConfig.pTcpBindName);
  188. }
  189. // Fall through
  190. case (1):
  191. CTEMemFree (NbtConfig.pRegistry.Buffer);
  192. default:
  193. break;
  194. }
  195. }
  196. //----------------------------------------------------------------------------
  197. NTSTATUS
  198. DriverEntry(
  199. IN PDRIVER_OBJECT DriverObject,
  200. IN PUNICODE_STRING RegistryPath
  201. )
  202. /*++
  203. Routine Description:
  204. This is the initialization routine for the NBT device driver.
  205. This routine creates the device object for the NBT
  206. device and calls a routine to perform other driver initialization.
  207. Arguments:
  208. DriverObject - Pointer to driver object created by the system.
  209. Return Value:
  210. NTSTATUS - The function value is the final status from the initialization
  211. operation.
  212. --*/
  213. {
  214. NTSTATUS status;
  215. tDEVICES *pBindDevices=NULL;
  216. tDEVICES *pExportDevices=NULL;
  217. tADDRARRAY *pAddrArray=NULL;
  218. PMDL pMdl;
  219. PSINGLE_LIST_ENTRY pSingleListEntry;
  220. UNICODE_STRING ucWinsDeviceBindName;
  221. UNICODE_STRING ucWinsDeviceExportName;
  222. UNICODE_STRING ucSmbDeviceBindName;
  223. UNICODE_STRING ucSmbDeviceExportName;
  224. UNICODE_STRING ucNetBTClientName;
  225. UNICODE_STRING ucNetBTProviderName;
  226. TDI_CLIENT_INTERFACE_INFO TdiClientInterface;
  227. #ifdef _PNP_POWER_DBG_
  228. //
  229. //Debug Stuff for DbgBreakPoint
  230. //
  231. OBJECT_ATTRIBUTES TmpObjectAttributes;
  232. HANDLE NbtConfigHandle;
  233. ULONG Disposition;
  234. PWSTR ParametersString = L"Parameters";
  235. HANDLE ParametersHandle;
  236. #endif // _PNP_POWER_DBG_
  237. CTEPagedCode();
  238. #ifdef _NBT_WMI_SOFTWARE_TRACING_
  239. WPP_INIT_TRACING(DriverObject, RegistryPath);
  240. #endif
  241. #ifdef _PNP_POWER_DBG_
  242. InitializeObjectAttributes (&TmpObjectAttributes,
  243. RegistryPath, // name
  244. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
  245. NULL, // root
  246. NULL); // security descriptor
  247. status = ZwCreateKey (&NbtConfigHandle,
  248. KEY_READ,
  249. &TmpObjectAttributes,
  250. 0, // title index
  251. NULL, // class
  252. 0, // create options
  253. &Disposition); // disposition
  254. if (!NT_SUCCESS(status))
  255. {
  256. NbtLogEvent (EVENT_NBT_CREATE_DRIVER, status, 0x109);
  257. return STATUS_UNSUCCESSFUL;
  258. }
  259. status = NbtOpenRegistry (NbtConfigHandle, ParametersString, &ParametersHandle);
  260. if (!NT_SUCCESS(status))
  261. {
  262. ZwClose(NbtConfigHandle);
  263. return (status);
  264. }
  265. if (CTEReadSingleIntParameter(ParametersHandle, ANSI_IF_VXD("Break"), 0, 0)) // disabled by default
  266. {
  267. KdPrint (("Nbt.DriverEntry: Registry-set Break!\n"));
  268. DbgBreakPoint();
  269. }
  270. ZwClose(ParametersHandle);
  271. ZwClose(NbtConfigHandle);
  272. #endif // _PNP_POWER_DBG_
  273. TdiInitialize();
  274. //
  275. // get the file system process for NBT since we need to know this for
  276. // allocating and freeing handles
  277. //
  278. NbtFspProcess =(PEPROCESS)PsGetCurrentProcess();
  279. //
  280. // Initialize the Configuration data structure
  281. //
  282. CTEZeroMemory(&NbtConfig,sizeof(tNBTCONFIG));
  283. NbtConfig.LoopbackIfContext = 0xffff;
  284. // save the driver object for event logging purposes
  285. //
  286. NbtConfig.DriverObject = DriverObject;
  287. // save the registry path for later use when DHCP asks us
  288. // to re-read the registry.
  289. //
  290. NbtConfig.pRegistry.MaximumLength = (USHORT) RegistryPath->MaximumLength;
  291. if (NbtConfig.pRegistry.Buffer = NbtAllocMem (RegistryPath->MaximumLength, NBT_TAG2('17')))
  292. {
  293. RtlCopyUnicodeString(&NbtConfig.pRegistry,RegistryPath);
  294. }
  295. else
  296. {
  297. return (STATUS_INSUFFICIENT_RESOURCES);
  298. }
  299. //
  300. // Initialize the driver object with this driver's entry points.
  301. //
  302. DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)NbtDispatchCreate;
  303. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)NbtDispatchDevCtrl;
  304. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)NbtDispatchInternalCtrl;
  305. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)NbtDispatchCleanup;
  306. DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)NbtDispatchClose;
  307. DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)NbtDispatchPnP;
  308. DriverObject->DriverUnload = NbtUnload;
  309. //
  310. // read in registry configuration data
  311. //
  312. status = NbtReadRegistry (&pBindDevices, &pExportDevices, &pAddrArray);
  313. if (!NT_SUCCESS(status))
  314. {
  315. //
  316. // There must have been some major problems with the registry, so
  317. // we will not load!
  318. //
  319. DbgPrint ("Nbt.DriverEntry[1]: Not loading because of failure to read registry = <%x>\n", status);
  320. CleanupDriverEntry (1);
  321. return(status);
  322. }
  323. //
  324. // Cleanup Allocated memory
  325. //
  326. NbtReadRegistryCleanup (&pBindDevices, &pExportDevices, &pAddrArray);
  327. //
  328. // Initialize NBT global data.
  329. //
  330. status = InitNotOs();
  331. if (!NT_SUCCESS(status))
  332. {
  333. NbtLogEvent (EVENT_NBT_NON_OS_INIT, status, 0x110);
  334. DbgPrint ("Nbt.DriverEntry[3]: Not loading because of failure to Initialize = <%x>\n",status);
  335. CleanupDriverEntry (3); // We may have done some partial initialization!
  336. return (status);
  337. }
  338. // create some MDLs, for session sends to speed up the sends.
  339. status = NbtInitMdlQ (&NbtConfig.SessionMdlFreeSingleList, eNBT_FREE_SESSION_MDLS);
  340. if (!NT_SUCCESS(status))
  341. {
  342. DbgPrint ("Nbt.DriverEntry[4]: Not loading because of failure to init Session MDL Q = <%x>\n",status);
  343. CleanupDriverEntry (4);
  344. return (status);
  345. }
  346. // create some MDLs for datagram sends
  347. status = NbtInitMdlQ( &NbtConfig.DgramMdlFreeSingleList, eNBT_DGRAM_MDLS);
  348. if (!NT_SUCCESS(status))
  349. {
  350. DbgPrint ("Nbt.DriverEntry[4]: Not loading because of failure to init Dgram MDL Q = <%x>\n", status);
  351. CleanupDriverEntry (4);
  352. return (status);
  353. }
  354. //---------------------------------------------------------------------------------------
  355. //
  356. // Create the SmbDevice object for Rdr/Srv
  357. //
  358. if ((NbtConfig.SMBDeviceEnabled) &&
  359. (!(pNbtSmbDevice = NbtCreateSmbDevice())))
  360. {
  361. KdPrint (("Nbt.DriverEntry: Failed to create SmbDevice!\n"));
  362. //
  363. // Allow the initialization to succeed even if this fails!
  364. //
  365. }
  366. //---------------------------------------------------------------------------------------
  367. //
  368. // Create the NBT device object for WINS to use
  369. //
  370. RtlInitUnicodeString (&ucWinsDeviceBindName, WC_WINS_DEVICE_BIND_NAME);
  371. ucWinsDeviceBindName.MaximumLength = sizeof (WC_WINS_DEVICE_BIND_NAME);
  372. RtlInitUnicodeString (&ucWinsDeviceExportName, WC_WINS_DEVICE_EXPORT_NAME);
  373. ucWinsDeviceExportName.MaximumLength = sizeof (WC_WINS_DEVICE_EXPORT_NAME);
  374. //
  375. // Try to export a DeviceObject for Wins, but do not add it to the list
  376. // of devices which we notify TDI about
  377. // Do not care about status because we want to continue even if we fail
  378. //
  379. status = NbtAllocAndInitDevice (&ucWinsDeviceBindName,
  380. &ucWinsDeviceExportName,
  381. &pWinsDeviceContext,
  382. NBT_DEVICE_WINS);
  383. if (!NT_SUCCESS(status))
  384. {
  385. DbgPrint ("Nbt.DriverEntry[5]: Not loading because of failure to create pWinsDevContext = <%x>\n",
  386. status);
  387. CleanupDriverEntry (5);
  388. return (status);
  389. }
  390. status = NbtCreateAdminSecurityDescriptor(&pWinsDeviceContext->DeviceObject);
  391. ASSERT(NT_SUCCESS(status));
  392. pWinsDeviceContext->IpAddress = 0;
  393. pWinsDeviceContext->DeviceRegistrationHandle = NULL;
  394. pWinsDeviceContext->NetAddressRegistrationHandle = NULL;
  395. pWinsDeviceContext->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
  396. //---------------------------------------------------------------------------------------
  397. #ifdef RASAUTODIAL
  398. //
  399. // Get the automatic connection driver
  400. // entry points.
  401. //
  402. NbtAcdBind();
  403. #endif
  404. //---------------------------------------------------------------------------------------
  405. //
  406. // Register ourselves as a Provider with Tdi
  407. //
  408. RtlInitUnicodeString(&ucNetBTProviderName, WC_NETBT_PROVIDER_NAME);
  409. ucNetBTProviderName.MaximumLength = sizeof (WC_NETBT_PROVIDER_NAME);
  410. status = TdiRegisterProvider (&ucNetBTProviderName, &TdiProviderHandle);
  411. if (NT_SUCCESS (status))
  412. {
  413. //
  414. // Register our Handlers with TDI
  415. //
  416. RtlInitUnicodeString(&ucNetBTClientName, WC_NETBT_CLIENT_NAME);
  417. ucNetBTClientName.MaximumLength = sizeof (WC_NETBT_CLIENT_NAME);
  418. RtlZeroMemory(&TdiClientInterface, sizeof(TdiClientInterface));
  419. TdiClientInterface.MajorTdiVersion = MAJOR_TDI_VERSION;
  420. TdiClientInterface.MinorTdiVersion = MINOR_TDI_VERSION;
  421. TdiClientInterface.ClientName = &ucNetBTClientName;
  422. TdiClientInterface.AddAddressHandlerV2 = TdiAddressArrival;
  423. TdiClientInterface.DelAddressHandlerV2 = TdiAddressDeletion;
  424. TdiClientInterface.BindingHandler = TdiBindHandler;
  425. TdiClientInterface.PnPPowerHandler = TdiPnPPowerHandler;
  426. status = TdiRegisterPnPHandlers (&TdiClientInterface, sizeof(TdiClientInterface), &TdiClientHandle);
  427. if (!NT_SUCCESS (status))
  428. {
  429. TdiDeregisterProvider (TdiProviderHandle);
  430. TdiProviderHandle = NULL;
  431. }
  432. }
  433. else
  434. {
  435. TdiProviderHandle = NULL;
  436. }
  437. if (!NT_SUCCESS (status))
  438. {
  439. DbgPrint ("Nbt.DriverEntry[6]: Not loading because of error = <%x>\n", status);
  440. CleanupDriverEntry (6);
  441. }
  442. //
  443. // Return to the caller.
  444. //
  445. return (status);
  446. }
  447. //----------------------------------------------------------------------------
  448. NTSTATUS
  449. NbtDispatchCleanup(
  450. IN PDEVICE_OBJECT Device,
  451. IN PIRP pIrp
  452. )
  453. /*++
  454. Routine Description:
  455. This is the NBT driver's dispatch function for IRP_MJ_CLEANUP
  456. requests.
  457. This function is called when the last reference to the handle is closed.
  458. Hence, an NtClose() results in an IRP_MJ_CLEANUP first, and then an
  459. IRP_MJ_CLOSE. This function runs down all activity on the object, and
  460. when the close comes in the object is actually deleted.
  461. Arguments:
  462. device - ptr to device object for target device
  463. pIrp - ptr to I/O request packet
  464. Return Value:
  465. STATUS_SUCCESS
  466. --*/
  467. {
  468. NTSTATUS status;
  469. PIO_STACK_LOCATION pIrpSp;
  470. tDEVICECONTEXT *pDeviceContext;
  471. CTEPagedCode();
  472. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  473. ASSERT(pIrpSp->MajorFunction == IRP_MJ_CLEANUP);
  474. pDeviceContext = (tDEVICECONTEXT *)Device;
  475. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  476. {
  477. // IF_DBG(NBT_DEBUG_DRIVER)
  478. KdPrint(("Nbt.NbtDispatchCleanup: Short-Ckt request --Device=<%x>, Context=<%x>, Context2=<%x>\n",
  479. pDeviceContext, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2));
  480. status = STATUS_SUCCESS;
  481. pIrp->IoStatus.Status = status;
  482. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  483. return (status);
  484. }
  485. // look at the context value that NBT put into the FSContext2 value to
  486. // decide what to do
  487. switch ((USHORT)pIrpSp->FileObject->FsContext2)
  488. {
  489. case NBT_ADDRESS_TYPE:
  490. // the client is closing the address file, so we must cleanup
  491. // and memory blocks associated with it.
  492. status = NTCleanUpAddress(pDeviceContext,pIrp);
  493. break;
  494. case NBT_CONNECTION_TYPE:
  495. // the client is closing a connection, so we must clean up any
  496. // memory blocks associated with it.
  497. status = NTCleanUpConnection(pDeviceContext,pIrp);
  498. break;
  499. case NBT_WINS_TYPE:
  500. //
  501. // This is synchronous with the Wins NtClose operation
  502. //
  503. status = NTCleanUpWinsAddr (pDeviceContext, pIrp);
  504. break;
  505. case NBT_CONTROL_TYPE:
  506. // there is nothing to do here....
  507. status = STATUS_SUCCESS;
  508. break;
  509. default:
  510. /*
  511. * complete the i/o successfully.
  512. */
  513. status = STATUS_SUCCESS;
  514. break;
  515. }
  516. //
  517. // Complete the Irp
  518. //
  519. ReturnIrp(pIrp, status);
  520. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  521. return(status);
  522. } // DispatchCleanup
  523. //----------------------------------------------------------------------------
  524. NTSTATUS
  525. NbtDispatchClose(
  526. IN PDEVICE_OBJECT Device,
  527. IN PIRP pIrp
  528. )
  529. /*++
  530. Routine Description:
  531. This is the NBT driver's dispatch function for IRP_MJ_CLOSE
  532. requests. This is called after Cleanup (above) is called.
  533. Arguments:
  534. device - ptr to device object for target device
  535. pIrp - ptr to I/O request packet
  536. Return Value:
  537. an NT status code.
  538. --*/
  539. {
  540. NTSTATUS status;
  541. PIO_STACK_LOCATION pIrpSp;
  542. tDEVICECONTEXT *pDeviceContext;
  543. CTEPagedCode();
  544. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  545. ASSERT(pIrpSp->MajorFunction == IRP_MJ_CLOSE);
  546. pDeviceContext = (tDEVICECONTEXT *)Device;
  547. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  548. {
  549. // IF_DBG(NBT_DEBUG_DRIVER)
  550. KdPrint(("Nbt.NbtDispatchClose: Short-Ckt request -- Device=<%x>, Context=<%x>, Context2=<%x>\n",
  551. pDeviceContext, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2));
  552. status = STATUS_SUCCESS;
  553. pIrp->IoStatus.Status = status;
  554. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  555. return (status);
  556. }
  557. //
  558. // close operations are synchronous.
  559. //
  560. pIrp->IoStatus.Status = STATUS_SUCCESS;
  561. pIrp->IoStatus.Information = 0;
  562. switch (PtrToUlong(pIrpSp->FileObject->FsContext2))
  563. {
  564. case NBT_ADDRESS_TYPE:
  565. status = NTCloseAddress(pDeviceContext,pIrp);
  566. break;
  567. case NBT_CONNECTION_TYPE:
  568. status = NTCloseConnection(pDeviceContext,pIrp);
  569. break;
  570. case NBT_WINS_TYPE:
  571. //
  572. // We don't need to set the DeviceContext here since we had
  573. // already saved it in pWinsInfo
  574. // This is an Asynchronous operation wrt the Wins server, hence
  575. // we should do only minimal work in this routine -- the
  576. // major cleanup should be in the DispatchCleanup routine
  577. //
  578. status = NTCloseWinsAddr(pDeviceContext,pIrp);
  579. break;
  580. case NBT_CONTROL_TYPE:
  581. // the client is closing the Control Object...
  582. // there is nothing to do here....
  583. status = STATUS_SUCCESS;
  584. break;
  585. default:
  586. KdPrint(("Nbt:Close Received for unknown object type = %X\n",
  587. pIrpSp->FileObject->FsContext2));
  588. status = STATUS_SUCCESS;
  589. break;
  590. }
  591. // NTCloseAddress can return Pending until the ref count actually gets
  592. // to zero.
  593. //
  594. if (status != STATUS_PENDING)
  595. {
  596. ReturnIrp(pIrp, status);
  597. }
  598. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  599. return(status);
  600. } // DispatchClose
  601. //----------------------------------------------------------------------------
  602. NTSTATUS
  603. NbtDispatchCreate(
  604. IN PDEVICE_OBJECT Device,
  605. IN PIRP pIrp
  606. )
  607. /*++
  608. Routine Description:
  609. This is the NBT driver's dispatch function for IRP_MJ_CREATE
  610. requests. It is called as a consequence of one of the following:
  611. a. TdiOpenConnection("\Device\Nbt_Elnkii0"),
  612. b. TdiOpenAddress("\Device\Nbt_Elnkii0"),
  613. Arguments:
  614. Device - ptr to device object being opened
  615. pIrp - ptr to I/O request packet
  616. pIrp->Status => return status
  617. pIrp->MajorFunction => IRP_MD_CREATE
  618. pIrp->MinorFunction => not used
  619. pIpr->FileObject => ptr to file obj created by I/O system. NBT fills in FsContext
  620. pIrp->AssociatedIrp.SystemBuffer => ptr to EA buffer with address of obj to open(Netbios Name)
  621. pIrp->Parameters.Create.EaLength => length of buffer specifying the Xport Addr.
  622. Return Value:
  623. STATUS_SUCCESS or STATUS_PENDING
  624. --*/
  625. {
  626. NTSTATUS status;
  627. PIO_STACK_LOCATION pIrpSp;
  628. PFILE_FULL_EA_INFORMATION ea, eabuf;
  629. tDEVICECONTEXT *pDeviceContext;
  630. UCHAR IrpFlags;
  631. tIPADDRESS UNALIGNED *pIpAddressU;
  632. tIPADDRESS IpAddress;
  633. CTEPagedCode();
  634. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  635. ASSERT(pIrpSp->MajorFunction == IRP_MJ_CREATE);
  636. //
  637. // If this device was destroyed, then reject all opens on it.
  638. // Ideally we would like the IO sub-system to guarantee that no
  639. // requests come down on IoDeleted devices, but.....
  640. //
  641. pDeviceContext = (tDEVICECONTEXT *)Device;
  642. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  643. {
  644. // IF_DBG(NBT_DEBUG_DRIVER)
  645. KdPrint(("Nbt.NbtDispatchCreate: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n",
  646. pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  647. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  648. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  649. return (STATUS_INVALID_DEVICE_STATE);
  650. }
  651. IrpFlags = pIrpSp->Control;
  652. //
  653. // set the pending flag here so that it is sure to be set BEFORE the
  654. // completion routine gets hit.
  655. //
  656. pIrp->IoStatus.Information = 0;
  657. pIrp->IoStatus.Status = STATUS_PENDING;
  658. IoMarkIrpPending(pIrp);
  659. /*
  660. * was this a TdiOpenConnection() or TdiOpenAddress()?
  661. * Get the Extended Attribute pointer and look at the text
  662. * value passed in for a match with "TransportAddress" or
  663. * "ConnectionContext" (in FindEa)
  664. */
  665. ea = (PFILE_FULL_EA_INFORMATION) pIrp->AssociatedIrp.SystemBuffer;
  666. IF_DBG(NBT_DEBUG_DRIVER)
  667. KdPrint(("Nbt.NbtDispatchCreate: Major:Minor=<%x:%x>, PFILE_FULL_EA_INFORMATION = <%x>\n",
  668. pIrpSp->MajorFunction, pIrpSp->MinorFunction, ea));
  669. if (!ea)
  670. {
  671. // a null ea means open the control object
  672. status = NTOpenControl(pDeviceContext,pIrp);
  673. }
  674. else if (eabuf = FindInEA(ea, TdiConnectionContext))
  675. {
  676. // not allowed to pass in both a Connect Request and a Transport Address
  677. ASSERT(!FindInEA(ea, TdiTransportAddress));
  678. status = NTOpenConnection(pDeviceContext, pIrp, eabuf);
  679. }
  680. else if (eabuf = FindInEA(ea, TdiTransportAddress))
  681. {
  682. status = NTOpenAddr(pDeviceContext, pIrp, eabuf);
  683. }
  684. else if (eabuf = FindInEA(ea, WINS_INTERFACE_NAME))
  685. {
  686. pIpAddressU = (tIPADDRESS UNALIGNED *) &ea->EaName[ea->EaNameLength+1];
  687. if (IpAddress = *pIpAddressU)
  688. {
  689. status = NTOpenWinsAddr(pDeviceContext, pIrp, IpAddress);
  690. }
  691. else
  692. {
  693. status = STATUS_INVALID_ADDRESS;
  694. }
  695. }
  696. else
  697. {
  698. status = STATUS_INVALID_EA_NAME;
  699. }
  700. // complete the irp if the status is anything EXCEPT status_pending
  701. // since the name query completion routine NTCompletIO completes pending
  702. // open addresses
  703. if (status != STATUS_PENDING)
  704. {
  705. #if DBG
  706. if (!NT_SUCCESS(status))
  707. {
  708. IF_DBG(NBT_DEBUG_NAMESRV)
  709. KdPrint(("Nbt.NbtDispatchCreate: Returning Error status = %X\n",status));
  710. }
  711. #endif
  712. // reset the pending returned bit, since we are NOT returning pending
  713. pIrpSp->Control = IrpFlags;
  714. ReturnIrp(pIrp,status);
  715. }
  716. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  717. return(status);
  718. }
  719. //----------------------------------------------------------------------------
  720. NTSTATUS
  721. NbtDispatchDevCtrl(
  722. IN PDEVICE_OBJECT Device,
  723. IN PIRP pIrp
  724. )
  725. /*++
  726. Routine Description:
  727. This is the NBT driver's dispatch function for all
  728. IRP_MJ_DEVICE_CONTROL requests.
  729. Arguments:
  730. device - ptr to device object for target device
  731. pIrp - ptr to I/O request packet
  732. Return Value:
  733. NTSTATUS -- Indicates whether the request was successfully queued.
  734. --*/
  735. {
  736. NTSTATUS status = STATUS_UNSUCCESSFUL;
  737. PIO_STACK_LOCATION pIrpSp;
  738. tDEVICECONTEXT *pDeviceContext;
  739. ULONG IoControlCode;
  740. PULONG_PTR pEntryPoint;
  741. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  742. ASSERT(pIrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
  743. //
  744. // If this device was destroyed, then reject all requests on it.
  745. // Ideally we would like the IO sub-system to guarantee that no
  746. // requests come down on IoDeleted devices, but.....
  747. //
  748. pDeviceContext = (tDEVICECONTEXT *)Device;
  749. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  750. {
  751. // IF_DBG(NBT_DEBUG_DRIVER)
  752. KdPrint(("Nbt.NbtDispatchDevCtrl: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n",
  753. pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  754. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  755. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  756. return (STATUS_INVALID_DEVICE_STATE);
  757. }
  758. /*
  759. * Initialize the I/O status block.
  760. */
  761. pIrp->IoStatus.Status = STATUS_PENDING;
  762. pIrp->IoStatus.Information = 0;
  763. IoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode; // Save the IoControl code
  764. IF_DBG(NBT_DEBUG_DRIVER)
  765. KdPrint(("Nbt.NbtDispatchDevCtrl: IoControlCode = <%x>\n",
  766. pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  767. /*
  768. * if possible, convert the (external) device control into internal
  769. * format, then treat it as if it had arrived that way.
  770. */
  771. if (STATUS_SUCCESS == TdiMapUserRequest(Device, pIrp, pIrpSp))
  772. {
  773. status = NbtDispatchInternalCtrl (Device, pIrp);
  774. }
  775. #if FAST_DISP
  776. // Check if upper layer is querying for fast send path
  777. else if (pIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER)
  778. {
  779. if (pEntryPoint = pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer)
  780. {
  781. if (pIrp->RequestorMode != KernelMode) // Bug# 120649: Make sure data + the Address type are good
  782. {
  783. try
  784. {
  785. ProbeForWrite (pEntryPoint, sizeof(PVOID *), sizeof(BYTE));
  786. *pEntryPoint = (ULONG_PTR) NTSend;
  787. status = STATUS_SUCCESS;
  788. }
  789. except(EXCEPTION_EXECUTE_HANDLER)
  790. {
  791. // status = STATUS_UNSUCCESSFUL by default
  792. }
  793. }
  794. else
  795. {
  796. *pEntryPoint = (ULONG_PTR) NTSend;
  797. status = STATUS_SUCCESS;
  798. }
  799. }
  800. IF_DBG(NBT_DEBUG_DRIVER)
  801. KdPrint(("Nbt.NbtDispatchDevCtrl: direct send handler query %x\n", pEntryPoint));
  802. ReturnIrp(pIrp, status);
  803. }
  804. #endif
  805. else
  806. {
  807. status = DispatchIoctls (pDeviceContext, pIrp, pIrpSp);
  808. }
  809. //
  810. // Dereference this DeviceContext, unless it was to destroy the Device!
  811. //
  812. if (IoControlCode != IOCTL_NETBT_DELETE_INTERFACE)
  813. {
  814. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  815. }
  816. return (status);
  817. } // NbtDispatchDevCtrl
  818. //----------------------------------------------------------------------------
  819. NTSTATUS
  820. NbtDispatchInternalCtrl(
  821. IN PDEVICE_OBJECT Device,
  822. IN PIRP pIrp
  823. )
  824. /*++
  825. Routine Description:
  826. This is the driver's dispatch function for all
  827. IRP_MJ_INTERNAL_DEVICE_CONTROL requests.
  828. Arguments:
  829. device - ptr to device object for target device
  830. pIrp - ptr to I/O request packet
  831. Return Value:
  832. NTSTATUS -- Indicates whether the request was successfully queued.
  833. --*/
  834. {
  835. tDEVICECONTEXT *pDeviceContext;
  836. PIO_STACK_LOCATION pIrpSp;
  837. NTSTATUS status;
  838. UCHAR IrpFlags;
  839. pDeviceContext = (tDEVICECONTEXT *)Device;
  840. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  841. ASSERT(pIrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
  842. //
  843. // this check is first to optimize the Send path
  844. //
  845. if (pIrpSp->MinorFunction ==TDI_SEND)
  846. {
  847. //
  848. // this routine decides if it should complete the pIrp or not
  849. // It never returns status pending, so we can turn off the
  850. // pending bit
  851. //
  852. status = NTSend (pDeviceContext,pIrp);
  853. return status;
  854. }
  855. //
  856. // If this device was destroyed, then reject all operations on it.
  857. // Ideally we would like the IO sub-system to guarantee that no
  858. // requests come down on IoDeleted devices, but.....
  859. //
  860. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  861. {
  862. // IF_DBG(NBT_DEBUG_DRIVER)
  863. KdPrint(("Nbt.NbtDispatchInternalCtrl: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n",
  864. pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  865. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  866. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  867. return (STATUS_INVALID_DEVICE_STATE);
  868. }
  869. IrpFlags = pIrpSp->Control;
  870. IF_DBG(NBT_DEBUG_DRIVER)
  871. KdPrint(("Nbt.NbtDispatchInternalCtrl: MajorFunction:MinorFunction = <%x:%x>\n",
  872. pIrpSp->MajorFunction, pIrpSp->MinorFunction));
  873. switch (pIrpSp->MinorFunction)
  874. {
  875. case TDI_ACCEPT:
  876. MakePending(pIrp);
  877. status = NTAccept(pDeviceContext,pIrp);
  878. break;
  879. case TDI_ASSOCIATE_ADDRESS:
  880. MakePending(pIrp);
  881. status = NTAssocAddress(pDeviceContext,pIrp);
  882. break;
  883. case TDI_DISASSOCIATE_ADDRESS:
  884. MakePending(pIrp);
  885. status = NTDisAssociateAddress(pDeviceContext,pIrp);
  886. break;
  887. case TDI_CONNECT:
  888. MakePending(pIrp);
  889. status = NTConnect(pDeviceContext,pIrp);
  890. break;
  891. case TDI_DISCONNECT:
  892. MakePending(pIrp);
  893. status = NTDisconnect(pDeviceContext,pIrp);
  894. break;
  895. case TDI_LISTEN:
  896. status = NTListen(pDeviceContext,pIrp);
  897. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  898. return(status);
  899. break;
  900. case TDI_QUERY_INFORMATION:
  901. status = NTQueryInformation(pDeviceContext,pIrp);
  902. #if DBG
  903. if (!NT_SUCCESS(status))
  904. {
  905. IF_DBG(NBT_DEBUG_NAMESRV)
  906. KdPrint(("Nbt.NbtDispatchInternalCtrl: Bad status from NTQueryInformation = %x\n",status));
  907. }
  908. #endif
  909. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  910. return(status);
  911. break;
  912. case TDI_RECEIVE:
  913. status = NTReceive(pDeviceContext,pIrp);
  914. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  915. return(status);
  916. break;
  917. case TDI_RECEIVE_DATAGRAM:
  918. status = NTReceiveDatagram(pDeviceContext,pIrp);
  919. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  920. return(status);
  921. break;
  922. case TDI_SEND_DATAGRAM:
  923. status = NTSendDatagram(pDeviceContext,pIrp);
  924. #if DBG
  925. if (!NT_SUCCESS(status))
  926. {
  927. IF_DBG(NBT_DEBUG_NAMESRV)
  928. KdPrint(("Nbt.NbtDispatchInternalCtrl: Bad status from NTSendDatagram = %x\n",status));
  929. }
  930. #endif
  931. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  932. return(status);
  933. break;
  934. case TDI_SET_EVENT_HANDLER:
  935. MakePending(pIrp);
  936. status = NTSetEventHandler(pDeviceContext,pIrp);
  937. break;
  938. case TDI_SET_INFORMATION:
  939. MakePending(pIrp);
  940. status = NTSetInformation(pDeviceContext,pIrp);
  941. break;
  942. #if DBG
  943. //
  944. // 0x7f is a request by the redirector to put a "magic bullet" out on
  945. // the wire, to trigger the Network General Sniffer.
  946. //
  947. case 0x7f:
  948. KdPrint(("NBT.DispatchInternalCtrl: - 07f minor function code\n"));
  949. ReturnIrp(pIrp, STATUS_NOT_SUPPORTED);
  950. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  951. return(STATUS_NOT_SUPPORTED);
  952. #endif /* DBG */
  953. default:
  954. KdPrint(("Nbt.DispatchInternalCtrl: Invalid minor function %X\n",
  955. pIrpSp->MinorFunction));
  956. ReturnIrp(pIrp, STATUS_INVALID_DEVICE_REQUEST);
  957. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  958. return(STATUS_INVALID_DEVICE_REQUEST);
  959. }
  960. // if the returned status is pending, then we do not complete the IRP
  961. // here since it will be completed elsewhere in the code...
  962. //
  963. if (status != STATUS_PENDING)
  964. {
  965. #if DBG
  966. // *TODO* for debug...
  967. if (!NT_SUCCESS(status))
  968. {
  969. IF_DBG(NBT_DEBUG_NAMESRV)
  970. KdPrint(("Nbt.NbtDispatchInternalCtrl: Returning Error status = %X,MinorFunc = %X\n",
  971. status,pIrpSp->MinorFunction));
  972. // ASSERTMSG("An error Status reported from NBT",0L);
  973. }
  974. #endif
  975. pIrpSp->Control = IrpFlags;
  976. ReturnIrp(pIrp,status);
  977. }
  978. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  979. return(status);
  980. } // NbtDispatchInternalCtrl
  981. //----------------------------------------------------------------------------
  982. ULONG
  983. CompleteTimerAndWorkerRequests(
  984. )
  985. {
  986. CTELockHandle OldIrq;
  987. tDEVICECONTEXT *pDeviceContext;
  988. LIST_ENTRY *pTimerQEntry;
  989. tTIMERQENTRY *pTimer;
  990. LIST_ENTRY *pWorkerQEntry;
  991. NBT_WORK_ITEM_CONTEXT *pContext;
  992. PNBT_WORKER_THREAD_ROUTINE pCompletionRoutine;
  993. ULONG NumTimerRequests = 0;
  994. ULONG NumDelayedRequests = 0;
  995. NTSTATUS status;
  996. //
  997. // First remove any active Device Contexts if they are still present
  998. //
  999. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1000. while (!IsListEmpty(&NbtConfig.DeviceContexts))
  1001. {
  1002. pDeviceContext = CONTAINING_RECORD(NbtConfig.DeviceContexts.Flink, tDEVICECONTEXT, Linkage);
  1003. NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  1004. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1005. NbtDestroyDevice (pDeviceContext, FALSE); // Don't wait since the Worker threads will not fire
  1006. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1007. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  1008. }
  1009. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1010. if (pNbtSmbDevice)
  1011. {
  1012. NbtDestroyDevice (pNbtSmbDevice, FALSE); // Don't wait since the Worker threads will not fire
  1013. pNbtSmbDevice = NULL;
  1014. }
  1015. NbtDestroyDevice (pWinsDeviceContext, FALSE); // Don't wait since the Worker threads will not fire
  1016. StopInitTimers();
  1017. KeClearEvent (&NbtConfig.TimerQLastEvent);
  1018. //
  1019. // if any other timers are active, stop them
  1020. //
  1021. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1022. while (!IsListEmpty(&TimerQ.ActiveHead))
  1023. {
  1024. pTimerQEntry = RemoveHeadList(&TimerQ.ActiveHead);
  1025. pTimer = CONTAINING_RECORD(pTimerQEntry,tTIMERQENTRY,Linkage);
  1026. InitializeListHead (&pTimer->Linkage); // in case the Linkage is touched again
  1027. IF_DBG(NBT_DEBUG_PNP_POWER)
  1028. KdPrint (("CompleteTimerAndWorkerRequests[%d]: Completing request <%x>\n",
  1029. NumTimerRequests, pTimer));
  1030. StopTimer (pTimer, NULL, NULL);
  1031. NumTimerRequests++;
  1032. }
  1033. //
  1034. // See if there are any Timers currently executing, and if so, wait for
  1035. // them to complete
  1036. //
  1037. if (NbtConfig.NumTimersRunning)
  1038. {
  1039. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1040. status = KeWaitForSingleObject(&NbtConfig.TimerQLastEvent, // Object to wait on.
  1041. Executive, // Reason for waiting
  1042. KernelMode, // Processor mode
  1043. FALSE, // Alertable
  1044. NULL); // Timeout
  1045. ASSERT(status == STATUS_SUCCESS);
  1046. }
  1047. else
  1048. {
  1049. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1050. }
  1051. //
  1052. // See if there are any worker threads currently executing, and if so, wait for
  1053. // them to complete
  1054. //
  1055. KeClearEvent (&NbtConfig.WorkerQLastEvent);
  1056. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  1057. if (NbtConfig.NumWorkerThreadsQueued)
  1058. {
  1059. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  1060. status = KeWaitForSingleObject(&NbtConfig.WorkerQLastEvent, // Object to wait on.
  1061. Executive, // Reason for waiting
  1062. KernelMode, // Processor mode
  1063. FALSE, // Alertable
  1064. NULL); // Timeout
  1065. ASSERT(status == STATUS_SUCCESS);
  1066. }
  1067. else
  1068. {
  1069. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  1070. }
  1071. //
  1072. // Dequeue each of the requests in the Worker Queue and complete them
  1073. //
  1074. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  1075. while (!IsListEmpty(&NbtConfig.WorkerQList))
  1076. {
  1077. pWorkerQEntry = RemoveHeadList(&NbtConfig.WorkerQList);
  1078. pContext = CONTAINING_RECORD(pWorkerQEntry, NBT_WORK_ITEM_CONTEXT, NbtConfigLinkage);
  1079. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq); // To get back to non-raised Irql!
  1080. pCompletionRoutine = pContext->WorkerRoutine;
  1081. IF_DBG(NBT_DEBUG_PNP_POWER)
  1082. KdPrint (("CompleteTimerAndWorkerRequests[%d]: Completing request <%x>\n",
  1083. NumDelayedRequests, pCompletionRoutine));
  1084. (*pCompletionRoutine) (pContext->pTracker,
  1085. pContext->pClientContext,
  1086. pContext->ClientCompletion,
  1087. pContext->pDeviceContext);
  1088. CTEMemFree ((PVOID) pContext);
  1089. NumDelayedRequests++;
  1090. //
  1091. // Acquire Lock again to check if we have completed all the requests
  1092. //
  1093. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  1094. }
  1095. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  1096. //
  1097. // Now destroy the Devices queued on the Free'ed list since there are no more Worker threads or
  1098. // Timers pending!
  1099. //
  1100. while (!IsListEmpty(&NbtConfig.DevicesAwaitingDeletion))
  1101. {
  1102. pDeviceContext = CONTAINING_RECORD(NbtConfig.DevicesAwaitingDeletion.Flink, tDEVICECONTEXT, Linkage);
  1103. ASSERT (pDeviceContext->RefCount == 0);
  1104. KdPrint(("Nbt.CompleteTimerAndWorkerRequests: *** Destroying Device *** \n\t%wZ\n",
  1105. &pDeviceContext->ExportName));
  1106. RemoveEntryList (&pDeviceContext->Linkage); // Remove the Device from the to-be-free'ed list
  1107. CTEMemFree (pDeviceContext->ExportName.Buffer);
  1108. IoDeleteDevice((PDEVICE_OBJECT)pDeviceContext);
  1109. }
  1110. ASSERT (IsListEmpty(&NbtConfig.AddressHead));
  1111. KdPrint(("Nbt.CompleteTimerAndWorkerRequests: Completed <%d> Timer and <%d> Delayed requests\n",
  1112. NumTimerRequests, NumDelayedRequests));
  1113. return (NumTimerRequests + NumDelayedRequests);
  1114. }
  1115. //----------------------------------------------------------------------------
  1116. VOID
  1117. NbtUnload(
  1118. IN PDRIVER_OBJECT DriverObject
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. This is the NBT driver's dispatch function for Unload requests
  1123. Arguments:
  1124. DriverObject - Pointer to driver object created by the system.
  1125. Return Value:
  1126. None
  1127. --*/
  1128. {
  1129. NTSTATUS status;
  1130. CTEPagedCode();
  1131. KdPrint(("Nbt.NbtUnload: Unloading ...\n"));
  1132. //
  1133. // After setting the following flag, no new requests should be queued on to
  1134. // the WorkerQ NbtConfig.WorkerQLastEvent will be set when all the current
  1135. // requests have finished executing
  1136. //
  1137. NbtConfig.Unloading = TRUE;
  1138. //
  1139. // Unbind fron the RAS driver if we were bound
  1140. //
  1141. NbtAcdUnbind ();
  1142. status = TdiDeregisterPnPHandlers(TdiClientHandle);
  1143. IF_DBG(NBT_DEBUG_PNP_POWER)
  1144. KdPrint (("NbtUnload: TdiDeregisterPnPHandlers returned <%x>\n", status));
  1145. status = TdiDeregisterProvider (TdiProviderHandle);
  1146. IF_DBG(NBT_DEBUG_PNP_POWER)
  1147. KdPrint (("NbtUnload: TdiDeregisterProvider returned <%x>\n", status));
  1148. //
  1149. // Dequeue each of the requests in the Timer and NbtConfigWorker Queues and complete them
  1150. //
  1151. CompleteTimerAndWorkerRequests();
  1152. //
  1153. // Now cleanup the rest of the static allocations
  1154. //
  1155. CleanupDriverEntry (5);
  1156. ASSERT (IsListEmpty (&NbtConfig.PendingNameQueries));
  1157. if (NbtConfig.pServerBindings) {
  1158. CTEFreeMem (NbtConfig.pServerBindings);
  1159. NbtConfig.pServerBindings = NULL;
  1160. }
  1161. if (NbtConfig.pClientBindings) {
  1162. CTEFreeMem (NbtConfig.pClientBindings);
  1163. NbtConfig.pClientBindings = NULL;
  1164. }
  1165. #ifdef _NBT_WMI_SOFTWARE_TRACING_
  1166. WPP_CLEANUP(DriverObject);
  1167. #endif
  1168. }
  1169. //----------------------------------------------------------------------------
  1170. NTSTATUS
  1171. NbtDispatchPnP(
  1172. IN PDEVICE_OBJECT Device,
  1173. IN PIRP pIrp
  1174. )
  1175. {
  1176. tDEVICECONTEXT *pDeviceContext;
  1177. PIO_STACK_LOCATION pIrpSp, pIrpSpNext;
  1178. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  1179. tCONNECTELE *pConnectEle;
  1180. tLOWERCONNECTION *pLowerConn;
  1181. KIRQL OldIrq1, OldIrq2;
  1182. PDEVICE_OBJECT pTcpDeviceObject;
  1183. PFILE_OBJECT pTcpFileObject;
  1184. tFILE_OBJECTS *pFileObjectsContext;
  1185. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1186. //
  1187. // If this device was destroyed, then reject all operations on it.
  1188. // Ideally we would like the IO sub-system to guarantee that no
  1189. // requests come down on IoDeleted devices, but.....
  1190. //
  1191. pDeviceContext = (tDEVICECONTEXT *)Device;
  1192. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  1193. {
  1194. IF_DBG(NBT_DEBUG_DRIVER)
  1195. KdPrint(("Nbt.NbtDispatchPnP: Short-Ckt request -- Device=<%x>\n", pDeviceContext));
  1196. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  1197. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  1198. return (STATUS_INVALID_DEVICE_STATE);
  1199. }
  1200. switch (pIrpSp->MinorFunction)
  1201. {
  1202. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1203. {
  1204. if (pIrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation)
  1205. {
  1206. if (PtrToUlong(pIrpSp->FileObject->FsContext2) == NBT_CONNECTION_TYPE)
  1207. {
  1208. // pass to transport to get the PDO
  1209. //
  1210. pConnectEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  1211. if (NBT_VERIFY_HANDLE2 (pConnectEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1212. {
  1213. CTESpinLock(pConnectEle, OldIrq1);
  1214. pLowerConn = (tLOWERCONNECTION *)pConnectEle->pLowerConnId;
  1215. if (NBT_VERIFY_HANDLE (pLowerConn, NBT_VERIFY_LOWERCONN))
  1216. {
  1217. CTESpinLock(pLowerConn, OldIrq2);
  1218. NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_DEVICE_REL);
  1219. CTESpinFree(pLowerConn, OldIrq2);
  1220. CTESpinFree(pConnectEle, OldIrq1);
  1221. if ((pTcpFileObject = pLowerConn->pFileObject) &&
  1222. (pTcpDeviceObject = IoGetRelatedDeviceObject (pLowerConn->pFileObject)))
  1223. {
  1224. //
  1225. // Simply pass the Irp on by to the Transport, and let it
  1226. // fill in the info
  1227. //
  1228. pIrpSpNext = IoGetNextIrpStackLocation (pIrp);
  1229. *pIrpSpNext = *pIrpSp;
  1230. IoSetCompletionRoutine (pIrp, NULL, NULL, FALSE, FALSE, FALSE);
  1231. pIrpSpNext->FileObject = pTcpFileObject;
  1232. pIrpSpNext->DeviceObject = pTcpDeviceObject;
  1233. status = IoCallDriver(pTcpDeviceObject, pIrp);
  1234. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  1235. return status;
  1236. }
  1237. else
  1238. {
  1239. status = STATUS_INVALID_HANDLE;
  1240. }
  1241. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_DEVICE_REL, FALSE);
  1242. }
  1243. else
  1244. {
  1245. status = STATUS_CONNECTION_INVALID;
  1246. CTESpinFree(pConnectEle, OldIrq1);
  1247. }
  1248. }
  1249. else
  1250. {
  1251. status = STATUS_INVALID_HANDLE;
  1252. }
  1253. }
  1254. else if ( PtrToUlong(pIrpSp->FileObject->FsContext2) == NBT_ADDRESS_TYPE)
  1255. {
  1256. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  1257. if ((pDeviceContext->IpAddress) &&
  1258. (pFileObjectsContext = pDeviceContext->pFileObjects) &&
  1259. (pTcpFileObject = pFileObjectsContext->pDgramFileObject) &&
  1260. (pTcpDeviceObject = pFileObjectsContext->pDgramDeviceObject))
  1261. {
  1262. pFileObjectsContext->RefCount++; // Dereferenced after the Query has completed
  1263. //
  1264. // pass the Irp to transport to get the PDO
  1265. //
  1266. pIrpSpNext = IoGetNextIrpStackLocation (pIrp);
  1267. *pIrpSpNext = *pIrpSp;
  1268. IoSetCompletionRoutine (pIrp, NULL, NULL, FALSE, FALSE, FALSE);
  1269. pIrpSpNext->FileObject = pTcpFileObject;
  1270. pIrpSpNext->DeviceObject = pTcpDeviceObject;
  1271. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  1272. status = IoCallDriver(pTcpDeviceObject, pIrp);
  1273. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  1274. if (--pFileObjectsContext->RefCount == 0)
  1275. {
  1276. CTEQueueForNonDispProcessing(DelayedNbtCloseFileHandles,
  1277. NULL,
  1278. pFileObjectsContext,
  1279. NULL,
  1280. NULL,
  1281. TRUE);
  1282. }
  1283. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, TRUE);
  1284. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  1285. return status;
  1286. }
  1287. else
  1288. {
  1289. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  1290. status = STATUS_INVALID_DEVICE_REQUEST;
  1291. }
  1292. }
  1293. else
  1294. {
  1295. ASSERT (0);
  1296. }
  1297. }
  1298. break;
  1299. }
  1300. default:
  1301. {
  1302. break;
  1303. }
  1304. }
  1305. ReturnIrp(pIrp, status);
  1306. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  1307. return status;
  1308. }
  1309. //----------------------------------------------------------------------------
  1310. PFILE_FULL_EA_INFORMATION
  1311. FindInEA(
  1312. IN PFILE_FULL_EA_INFORMATION start,
  1313. IN PCHAR wanted
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. This function check for the "Wanted" string in the Ea structure and
  1318. returns a pointer to the extended attribute structure
  1319. representing the given extended attribute name.
  1320. Arguments:
  1321. device - ptr to device object for target device
  1322. pIrp - ptr to I/O request packet
  1323. Return Value:
  1324. pointer to the extended attribute structure, or NULL if not found.
  1325. --*/
  1326. {
  1327. PFILE_FULL_EA_INFORMATION eabuf;
  1328. CTEPagedCode();
  1329. //
  1330. // Bug # 225668: advance eabug ptr by typecasting it to UCHAR
  1331. //
  1332. for (eabuf = start; eabuf; eabuf = (PFILE_FULL_EA_INFORMATION) ((PUCHAR)eabuf + eabuf->NextEntryOffset))
  1333. {
  1334. if (strncmp(eabuf->EaName,wanted,eabuf->EaNameLength) == 0)
  1335. {
  1336. return eabuf;
  1337. }
  1338. if (eabuf->NextEntryOffset == 0)
  1339. {
  1340. return((PFILE_FULL_EA_INFORMATION) NULL);
  1341. }
  1342. }
  1343. return((PFILE_FULL_EA_INFORMATION) NULL);
  1344. } // FindEA
  1345. //----------------------------------------------------------------------------
  1346. VOID
  1347. ReturnIrp(
  1348. IN PIRP pIrp,
  1349. IN int status
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This function completes an IRP, and arranges for return parameters,
  1354. if any, to be copied.
  1355. Although somewhat a misnomer, this function is named after a similar
  1356. function in the SpiderSTREAMS emulator.
  1357. Arguments:
  1358. pIrp - pointer to the IRP to complete
  1359. status - completion status of the IRP
  1360. Return Value:
  1361. number of bytes copied back to the user.
  1362. --*/
  1363. {
  1364. KIRQL oldlevel;
  1365. CCHAR priboost;
  1366. //
  1367. // pIrp->IoStatus.Information is meaningful only for STATUS_SUCCESS
  1368. //
  1369. // set the Irps cancel routine to null or the system may bugcheck
  1370. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
  1371. //
  1372. // refer to IoCancelIrp() ..\ntos\io\iosubs.c
  1373. //
  1374. IoAcquireCancelSpinLock(&oldlevel);
  1375. IoSetCancelRoutine(pIrp,NULL);
  1376. IoReleaseCancelSpinLock(oldlevel);
  1377. pIrp->IoStatus.Status = status;
  1378. priboost = (CCHAR) ((status == STATUS_SUCCESS) ?
  1379. IO_NETWORK_INCREMENT : IO_NO_INCREMENT);
  1380. IoCompleteRequest(pIrp, priboost);
  1381. return;
  1382. }
  1383. //----------------------------------------------------------------------------
  1384. VOID
  1385. MakePending(
  1386. IN PIRP pIrp
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. This function marks an irp pending and sets the correct status.
  1391. Arguments:
  1392. pIrp - pointer to the IRP to complete
  1393. status - completion status of the IRP
  1394. Return Value:
  1395. --*/
  1396. {
  1397. IoMarkIrpPending(pIrp);
  1398. pIrp->IoStatus.Status = STATUS_PENDING;
  1399. pIrp->IoStatus.Information = 0;
  1400. }
  1401. #ifdef _NBT_WMI_SOFTWARE_TRACING_
  1402. int nbtlog_strnlen(char *p, int n)
  1403. {
  1404. int i;
  1405. for (i = 0; (i < n) && *p; i++, p++) {
  1406. }
  1407. return i;
  1408. }
  1409. #endif