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.

1029 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. Driver.c
  5. Abstract:
  6. This module implements the DRIVER_INITIALIZATION routine for the
  7. SMB Transport and other routines that are specific to the NT implementation
  8. of a driver.
  9. Author:
  10. Jiandong Ruan
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "ip2netbios.h"
  15. #include "driver2.tmh"
  16. BOOL
  17. IsNetBTSmbEnabled(
  18. IN PUNICODE_STRING RegistryPath
  19. );
  20. NTSTATUS
  21. NotifyNetBT(
  22. IN DWORD dwNetBTAction
  23. );
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(INIT, SmbDriverEntry)
  26. #pragma alloc_text(INIT, IsNetBTSmbEnabled)
  27. #pragma alloc_text(PAGE, NotifyNetBT)
  28. #pragma alloc_text(PAGE, SmbDispatchCleanup)
  29. #pragma alloc_text(PAGE, SmbDispatchClose)
  30. #pragma alloc_text(PAGE, SmbDispatchCreate)
  31. #pragma alloc_text(PAGE, SmbDispatchDevCtrl)
  32. #pragma alloc_text(PAGE, SmbDispatchPnP)
  33. #pragma alloc_text(PAGE, SmbUnload)
  34. #endif
  35. NTSTATUS
  36. NotifyNetBT(
  37. IN DWORD dwNetBTAction
  38. )
  39. {
  40. UNICODE_STRING uncWinsDeviceName = { 0 };
  41. PFILE_OBJECT pWinsFileObject = NULL;
  42. PDEVICE_OBJECT pWinsDeviceObject = NULL;
  43. PIRP pIrp = NULL;
  44. IO_STATUS_BLOCK IoStatusBlock = { 0 };
  45. KEVENT Event = { 0 };
  46. NTSTATUS status = STATUS_UNSUCCESSFUL;
  47. PAGED_CODE();
  48. KeInitializeEvent(&Event, NotificationEvent, FALSE);
  49. //
  50. // Notify NetBT to destroy its NetbiosSmb
  51. //
  52. RtlInitUnicodeString(&uncWinsDeviceName, L"\\Device\\NetBt_Wins_Export");
  53. status = IoGetDeviceObjectPointer(
  54. &uncWinsDeviceName,
  55. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  56. &pWinsFileObject,
  57. &pWinsDeviceObject
  58. );
  59. if (STATUS_SUCCESS != status) {
  60. goto error;
  61. }
  62. pIrp = IoBuildDeviceIoControlRequest (
  63. IOCTL_NETBT_ENABLE_DISABLE_NETBIOS_SMB,
  64. pWinsDeviceObject,
  65. &dwNetBTAction,
  66. sizeof(dwNetBTAction),
  67. NULL,
  68. 0,
  69. FALSE,
  70. &Event,
  71. &IoStatusBlock
  72. );
  73. if (NULL == pIrp) {
  74. status = STATUS_INSUFFICIENT_RESOURCES;
  75. goto error;
  76. }
  77. status = IoCallDriver(pWinsDeviceObject, pIrp);
  78. if (STATUS_PENDING == status) {
  79. ASSERT (0);
  80. KeWaitForSingleObject(
  81. &Event,
  82. Executive,
  83. KernelMode,
  84. FALSE,
  85. NULL
  86. );
  87. status = IoStatusBlock.Status;
  88. }
  89. error:
  90. if (pWinsFileObject != NULL) {
  91. ObDereferenceObject(pWinsFileObject);
  92. pWinsFileObject = NULL;
  93. }
  94. return status;
  95. }
  96. BOOL
  97. IsNetBTSmbEnabled(
  98. IN PUNICODE_STRING RegistryPath
  99. )
  100. {
  101. OBJECT_ATTRIBUTES ObAttr = { 0 };
  102. NTSTATUS status = STATUS_SUCCESS;
  103. HANDLE hRootKey = NULL;
  104. HANDLE hKey = NULL;
  105. UNICODE_STRING uncParams = { 0 };
  106. BOOL fUseSmbFromNetBT = FALSE;
  107. PAGED_CODE();
  108. //
  109. // Construct the registry path for the HKLM\System\CCS\Services
  110. //
  111. uncParams = RegistryPath[0];
  112. while(uncParams.Length > 0 && uncParams.Buffer[uncParams.Length/sizeof(WCHAR) - 1] != L'\\') {
  113. uncParams.Length -= sizeof(WCHAR);
  114. }
  115. uncParams.Length -= sizeof(WCHAR);
  116. InitializeObjectAttributes (
  117. &ObAttr,
  118. &uncParams,
  119. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  120. NULL,
  121. NULL
  122. );
  123. status = ZwOpenKey (&hRootKey, KEY_READ | KEY_WRITE, &ObAttr);
  124. BAIL_OUT_ON_ERROR(status);
  125. RtlInitUnicodeString(&uncParams, L"NetBT");
  126. InitializeObjectAttributes (
  127. &ObAttr,
  128. &uncParams,
  129. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  130. hRootKey,
  131. NULL
  132. );
  133. status = ZwOpenKey(&hKey, KEY_READ | KEY_WRITE, &ObAttr);
  134. ZwClose(hRootKey);
  135. hRootKey = hKey;
  136. hKey = NULL;
  137. BAIL_OUT_ON_ERROR(status);
  138. fUseSmbFromNetBT = TRUE;
  139. //
  140. // From now on, an error means NetBT's Smb enabled
  141. //
  142. RtlInitUnicodeString(&uncParams, L"Parameters");
  143. InitializeObjectAttributes (
  144. &ObAttr,
  145. &uncParams,
  146. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  147. hRootKey,
  148. NULL
  149. );
  150. status = ZwOpenKey (&hKey, KEY_READ | KEY_WRITE, &ObAttr);
  151. ZwClose(hRootKey);
  152. hRootKey = hKey;
  153. hKey = NULL;
  154. BAIL_OUT_ON_ERROR(status);
  155. fUseSmbFromNetBT = !(SmbReadULong(hRootKey, L"UseNewSmb", 0, 0));
  156. if (fUseSmbFromNetBT) {
  157. goto cleanup;
  158. }
  159. status = NotifyNetBT(NETBT_DISABLE_NETBIOS_SMB);
  160. status = STATUS_SUCCESS;
  161. cleanup:
  162. if (hRootKey != NULL) {
  163. ZwClose(hRootKey);
  164. }
  165. if (hKey != NULL) {
  166. ZwClose(hKey);
  167. }
  168. return fUseSmbFromNetBT;
  169. }
  170. static KTIMER DelayedInitTimer;
  171. static KDPC DelayedInitDpc;
  172. static WORK_QUEUE_ITEM DelayedInitWorkItem;
  173. static VOID
  174. SmbDelayedInitRtn(
  175. PVOID pvUnused1
  176. )
  177. {
  178. NTSTATUS status = STATUS_SUCCESS;
  179. status = SmbInitTdi();
  180. ObDereferenceObject(&(SmbCfg.SmbDeviceObject->DeviceObject));
  181. }
  182. static VOID
  183. SmbDelayedInitTimeoutRtn(
  184. IN PKDPC Dpc,
  185. IN PVOID Ctx,
  186. IN PVOID SystemArg1,
  187. IN PVOID SystemArg2
  188. )
  189. {
  190. ExInitializeWorkItem(&DelayedInitWorkItem, SmbDelayedInitRtn, NULL);
  191. ExQueueWorkItem(&DelayedInitWorkItem, DelayedWorkQueue);
  192. }
  193. static NTSTATUS
  194. SmbDelayedInitTdi(
  195. DWORD dwDelayedTime
  196. )
  197. {
  198. NTSTATUS status = STATUS_SUCCESS;
  199. LARGE_INTEGER DueTime = { 0 };
  200. KeInitializeTimer(&DelayedInitTimer);
  201. KeInitializeDpc(&DelayedInitDpc, SmbDelayedInitTimeoutRtn, NULL);
  202. DueTime.QuadPart = UInt32x32To64(dwDelayedTime,(LONG)10000);
  203. DueTime.QuadPart = -DueTime.QuadPart;
  204. ObReferenceObject(&(SmbCfg.SmbDeviceObject->DeviceObject));
  205. KeSetTimer(&DelayedInitTimer, DueTime, &DelayedInitDpc);
  206. return status;
  207. }
  208. NTSTATUS
  209. SmbDriverEntry(
  210. IN PDRIVER_OBJECT DriverObject,
  211. IN PUNICODE_STRING RegistryPath,
  212. IN OUT PDEVICE_OBJECT *SmbDevice
  213. )
  214. /*++
  215. Routine Description:
  216. This is the initialization routine for the SMB device driver.
  217. This routine creates the device object for the SMB
  218. device and calls a routine to perform other driver initialization.
  219. Arguments:
  220. DriverObject - Pointer to driver object created by the system.
  221. Return Value:
  222. NTSTATUS - The function value is the final status from the initialization
  223. operation.
  224. --*/
  225. {
  226. NTSTATUS status;
  227. PAGED_CODE();
  228. RtlZeroMemory(&SmbCfg, sizeof(SmbCfg));
  229. if (SmbDevice) {
  230. *SmbDevice = NULL;
  231. }
  232. SmbCfg.DriverObject = DriverObject;
  233. InitializeListHead(&SmbCfg.IPDeviceList);
  234. InitializeListHead(&SmbCfg.PendingDeleteIPDeviceList);
  235. KeInitializeSpinLock(&SmbCfg.UsedIrpsLock);
  236. InitializeListHead(&SmbCfg.UsedIrps);
  237. KeInitializeSpinLock(&SmbCfg.Lock);
  238. SmbCfg.FspProcess =(PEPROCESS)PsGetCurrentProcess();
  239. status = ExInitializeResourceLite(&SmbCfg.Resource);
  240. BAIL_OUT_ON_ERROR(status);
  241. status = SmbInitRegistry(RegistryPath);
  242. BAIL_OUT_ON_ERROR(status);
  243. #if DBG
  244. if (SmbReadULong(SmbCfg.ParametersKey, L"Break", 0, 0)) {
  245. DbgBreakPoint();
  246. }
  247. SmbCfg.DebugFlag = SmbReadULong(SmbCfg.ParametersKey, L"DebugFlag", 0, 0);
  248. #endif
  249. #ifdef STANDALONE_SMB
  250. if (IsNetBTSmbEnabled(RegistryPath)) {
  251. SmbPrint(SMB_TRACE_PNP, ("Abort the initialization of SMB since NetBT's Smb device is enabled\n"));
  252. SmbTrace(SMB_TRACE_PNP, ("Abort the initialization of SMB since NetBT's Smb device is enabled"));
  253. return STATUS_UNSUCCESSFUL;
  254. }
  255. #endif
  256. SmbCfg.EnableNagling = SmbReadULong (
  257. SmbCfg.ParametersKey,
  258. SMB_REG_ENABLE_NAGLING,
  259. 0, // Disabled by default
  260. 0
  261. );
  262. SmbCfg.DnsTimeout = SmbReadULong (
  263. SmbCfg.ParametersKey,
  264. SMB_REG_DNS_TIME_OUT,
  265. SMB_REG_DNS_TIME_OUT_DEFAULT,
  266. SMB_REG_DNS_TIME_OUT_MIN
  267. );
  268. SmbCfg.DnsMaxResolver = SmbReadLong (
  269. SmbCfg.ParametersKey,
  270. SMB_REG_DNS_MAX_RESOLVER,
  271. SMB_REG_DNS_RESOLVER_DEFAULT,
  272. SMB_REG_DNS_RESOLVER_MIN
  273. );
  274. if (SmbCfg.DnsMaxResolver > DNS_MAX_RESOLVER) {
  275. SmbCfg.DnsMaxResolver = DNS_MAX_RESOLVER;
  276. }
  277. SmbCfg.uIPv6Protection = SmbReadULong(
  278. SmbCfg.ParametersKey,
  279. SMB_REG_IPV6_PROTECTION,
  280. SMB_REG_IPV6_PROTECTION_DEFAULT,
  281. 0
  282. );
  283. SmbCfg.bIPv6EnableOutboundGlobal = SmbReadULong(
  284. SmbCfg.ParametersKey,
  285. SMB_REG_IPV6_ENABLE_OUTBOUND_GLOBAL,
  286. FALSE, // default value
  287. 0
  288. );
  289. #ifndef NO_LOOKASIDE_LIST
  290. //
  291. // Initialize Lookaside Lists
  292. //
  293. ExInitializeNPagedLookasideList(
  294. &SmbCfg.ConnectObjectPool,
  295. NULL,
  296. NULL,
  297. 0,
  298. sizeof(SMB_CONNECT),
  299. CONNECT_OBJECT_POOL_TAG,
  300. 0
  301. );
  302. SmbCfg.ConnectObjectPoolInitialized = TRUE;
  303. ExInitializeNPagedLookasideList(
  304. &SmbCfg.TcpContextPool,
  305. NULL,
  306. NULL,
  307. 0,
  308. sizeof(SMB_TCP_CONTEXT),
  309. TCP_CONTEXT_POOL_TAG,
  310. 0
  311. );
  312. SmbCfg.TcpContextPoolInitialized = TRUE;
  313. #endif
  314. #ifdef STANDALONE_SMB
  315. TdiInitialize();
  316. #endif
  317. status = SmbCreateSmbDevice(&SmbCfg.SmbDeviceObject, SMB_TCP_PORT, SMB_ENDPOINT_NAME);
  318. BAIL_OUT_ON_ERROR(status);
  319. status = SmbInitDnsResolver();
  320. BAIL_OUT_ON_ERROR(status);
  321. status = SmbInitIPv6NetbiosMappingTable();
  322. BAIL_OUT_ON_ERROR(status);
  323. #ifdef STANDALONE_SMB
  324. status = SmbDelayedInitTdi(1000);
  325. BAIL_OUT_ON_ERROR(status);
  326. #endif
  327. if (SmbDevice) {
  328. *SmbDevice = &(SmbCfg.SmbDeviceObject->DeviceObject);
  329. }
  330. return (status);
  331. cleanup:
  332. SmbUnload(DriverObject);
  333. return status;
  334. }
  335. //----------------------------------------------------------------------------
  336. NTSTATUS
  337. SmbDispatchCleanup(
  338. IN PSMB_DEVICE Device,
  339. IN PIRP Irp
  340. )
  341. /*++
  342. Routine Description:
  343. This is the SMB driver's dispatch function for IRP_MJ_CLEANUP
  344. requests.
  345. This function is called when the last reference to the handle is closed.
  346. Hence, an NtClose() results in an IRP_MJ_CLEANUP first, and then an
  347. IRP_MJ_CLOSE. This function runs down all activity on the object, and
  348. when the close comes in the object is actually deleted.
  349. Arguments:
  350. device - ptr to device object for target device
  351. pIrp - ptr to I/O request packet
  352. Return Value:
  353. STATUS_SUCCESS
  354. --*/
  355. {
  356. NTSTATUS status = STATUS_SUCCESS;
  357. PIO_STACK_LOCATION IrpSp;
  358. PAGED_CODE();
  359. if (SmbCfg.Unloading) {
  360. status = STATUS_INVALID_DEVICE_REQUEST;
  361. }
  362. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  363. ASSERT(IrpSp->MajorFunction == IRP_MJ_CLEANUP);
  364. Irp->IoStatus.Status = status;
  365. Irp->IoStatus.Information = 0;
  366. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  367. return(status);
  368. }
  369. //----------------------------------------------------------------------------
  370. NTSTATUS
  371. SmbDispatchClose(
  372. IN PSMB_DEVICE Device,
  373. IN PIRP Irp
  374. )
  375. /*++
  376. Routine Description:
  377. This is the SMB driver's dispatch function for IRP_MJ_CLOSE
  378. requests. This is called after Cleanup (above) is called.
  379. Arguments:
  380. device - ptr to device object for target device
  381. pIrp - ptr to I/O request packet
  382. Return Value:
  383. an NT status code.
  384. --*/
  385. {
  386. NTSTATUS status;
  387. PIO_STACK_LOCATION IrpSp;
  388. PAGED_CODE();
  389. if (SmbCfg.Unloading) {
  390. status = STATUS_INVALID_DEVICE_REQUEST;
  391. goto cleanup;
  392. }
  393. ASSERT(Device == SmbCfg.SmbDeviceObject);
  394. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  395. ASSERT(IrpSp->MajorFunction == IRP_MJ_CLOSE);
  396. switch(PtrToUlong(IrpSp->FileObject->FsContext2)) {
  397. case SMB_TDI_CONTROL:
  398. status = SmbCloseControl(Device, Irp);
  399. break;
  400. case SMB_TDI_CLIENT:
  401. status = SmbCloseClient(Device, Irp);
  402. break;
  403. case SMB_TDI_CONNECT:
  404. status = SmbCloseConnection(Device, Irp);
  405. break;
  406. default:
  407. status = STATUS_SUCCESS;
  408. }
  409. ASSERT(status != STATUS_PENDING);
  410. cleanup:
  411. Irp->IoStatus.Status = status;
  412. Irp->IoStatus.Information = 0;
  413. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  414. return status;
  415. }
  416. PFILE_FULL_EA_INFORMATION
  417. SmbFindInEA(
  418. IN PFILE_FULL_EA_INFORMATION eabuf,
  419. IN PCHAR wanted
  420. );
  421. #pragma alloc_text(PAGE, SmbFindInEA)
  422. PFILE_FULL_EA_INFORMATION
  423. SmbFindInEA(
  424. IN PFILE_FULL_EA_INFORMATION eabuf,
  425. IN PCHAR wanted
  426. )
  427. /*++
  428. Routine Description:
  429. This function check for the "Wanted" string in the Ea structure and
  430. returns a pointer to the extended attribute structure
  431. representing the given extended attribute name.
  432. Arguments:
  433. Return Value:
  434. pointer to the extended attribute structure, or NULL if not found.
  435. --*/
  436. {
  437. PAGED_CODE();
  438. while(1) {
  439. if (strncmp(eabuf->EaName, wanted, eabuf->EaNameLength) == 0) {
  440. return eabuf;
  441. }
  442. if (0 == eabuf->NextEntryOffset) {
  443. return NULL;
  444. }
  445. eabuf = (PFILE_FULL_EA_INFORMATION) ((PUCHAR)eabuf + eabuf->NextEntryOffset);
  446. }
  447. }
  448. NTSTATUS
  449. SmbDispatchCreate(
  450. IN PSMB_DEVICE Device,
  451. IN PIRP Irp
  452. )
  453. /*++
  454. Routine Description:
  455. This is the SMB driver's dispatch function for IRP_MJ_CREATE
  456. requests. It is called as a consequence of one of the following:
  457. a. TdiOpenConnection("\Device\Smb_Elnkii0"),
  458. b. TdiOpenAddress("\Device\Smb_Elnkii0"),
  459. Arguments:
  460. Device - ptr to device object being opened
  461. pIrp - ptr to I/O request packet
  462. pIrp->Status => return status
  463. pIrp->MajorFunction => IRP_MD_CREATE
  464. pIrp->MinorFunction => not used
  465. pIrp->FileObject => ptr to file obj created by I/O system. SMB fills in FsContext
  466. pIrp->AssociatedIrp.SystemBuffer => ptr to EA buffer with address of obj to open(Netbios Name)
  467. pIrp->Parameters.Create.EaLength => length of buffer specifying the Xport Addr.
  468. Return Value:
  469. STATUS_SUCCESS or STATUS_PENDING
  470. --*/
  471. {
  472. NTSTATUS status = STATUS_SUCCESS;
  473. PIO_STACK_LOCATION IrpSp;
  474. PFILE_FULL_EA_INFORMATION ea, wanted_ea;
  475. PAGED_CODE();
  476. if (SmbCfg.Unloading) {
  477. SmbPrint(SMB_TRACE_PNP, ("DispatchCreate: Smb is unloading\n"));
  478. status = STATUS_INVALID_DEVICE_REQUEST;
  479. goto cleanup;
  480. }
  481. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  482. ASSERT(Device == SmbCfg.SmbDeviceObject);
  483. ASSERT(IrpSp->MajorFunction == IRP_MJ_CREATE);
  484. ea = Irp->AssociatedIrp.SystemBuffer;
  485. if (NULL == ea || KernelMode != Irp->RequestorMode) {
  486. status = SmbCreateControl(Device, Irp);
  487. } else if (NULL != (wanted_ea = SmbFindInEA(ea, TdiConnectionContext))) {
  488. // Not allow to pass in both a connection request and a transport address request
  489. ASSERT(!SmbFindInEA(ea, TdiTransportAddress));
  490. status = SmbCreateConnection(Device, Irp, wanted_ea);
  491. } else if (NULL != (wanted_ea = SmbFindInEA(ea, TdiTransportAddress))) {
  492. // Not allow to pass in both a connection request and a transport address request
  493. ASSERT(!SmbFindInEA(ea, TdiConnectionContext));
  494. status = SmbCreateClient(Device, Irp, wanted_ea);
  495. } else {
  496. status = STATUS_INVALID_EA_NAME;
  497. }
  498. cleanup:
  499. ASSERT(status != STATUS_PENDING);
  500. Irp->IoStatus.Status = status;
  501. Irp->IoStatus.Information = 0;
  502. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  503. return(status);
  504. }
  505. NTSTATUS
  506. SmbDispatchDevCtrl(
  507. IN PSMB_DEVICE Device,
  508. IN PIRP Irp
  509. )
  510. /*++
  511. Routine Description:
  512. This is the SMB driver's dispatch function for all
  513. IRP_MJ_DEVICE_CONTROL requests.
  514. Arguments:
  515. device - ptr to device object for target device
  516. pIrp - ptr to I/O request packet
  517. Return Value:
  518. NTSTATUS -- Indicates whether the request was successfully queued.
  519. --*/
  520. {
  521. NTSTATUS status = STATUS_SUCCESS;
  522. PIO_STACK_LOCATION IrpSp;
  523. if (SmbCfg.Unloading) {
  524. SmbPrint(SMB_TRACE_PNP, ("DispatchDevCtrl: Smb is unloading\n"));
  525. status = STATUS_INVALID_DEVICE_REQUEST;
  526. goto cleanup;
  527. }
  528. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  529. switch(IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  530. case IOCTL_SMB_START:
  531. SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_START"));
  532. SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_START\n"));
  533. status = SmbTdiRegister(Device);
  534. break;
  535. case IOCTL_SMB_STOP:
  536. SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_STOP"));
  537. SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_STOP\n"));
  538. status = SmbTdiDeregister(Device);
  539. break;
  540. case IOCTL_SMB_DNS:
  541. status = SmbNewResolver(Device, Irp);
  542. break;
  543. case IOCTL_SMB_ENABLE_NAGLING:
  544. SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_ENABLE_NAGLING"));
  545. SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_ENABLE_NAGLING\n"));
  546. SmbCfg.EnableNagling = TRUE;
  547. status = STATUS_SUCCESS;
  548. TODO("Turn on nagling for each connection in the pool");
  549. break;
  550. case IOCTL_SMB_DISABLE_NAGLING:
  551. SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_DISABLE_NAGLING"));
  552. SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_DISABLE_NAGLING\n"));
  553. SmbCfg.EnableNagling = FALSE;
  554. status = STATUS_SUCCESS;
  555. TODO("Turn off nagling for each connection in the pool");
  556. break;
  557. case IOCTL_SMB_SET_IPV6_PROTECTION_LEVEL:
  558. //
  559. // Set IPv6 Protection level
  560. //
  561. status = IoctlSetIPv6Protection(Device, Irp, IrpSp);
  562. break;
  563. case IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER:
  564. SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER"));
  565. SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER\n"));
  566. if (Irp->RequestorMode != KernelMode) {
  567. //
  568. // There is no point for usermode application to query FastSend
  569. //
  570. status = STATUS_ACCESS_DENIED;
  571. break;
  572. }
  573. (PVOID)(IrpSp->Parameters.DeviceIoControl.Type3InputBuffer) = (PVOID)SmbSend;
  574. status = STATUS_SUCCESS;
  575. break;
  576. //
  577. // Legacy NetBT stuff
  578. // The following Ioctl is used by the Rdr/Srv to add/remove addresses from the SmbDevice
  579. //
  580. case IOCTL_NETBT_SET_SMBDEVICE_BIND_INFO:
  581. status = SmbSetBindingInfo(Device, Irp);
  582. break;
  583. //
  584. // Used by Srv service
  585. //
  586. case IOCTL_NETBT_SET_TCP_CONNECTION_INFO:
  587. status = SmbClientSetTcpInfo(Device, Irp);
  588. break;
  589. //
  590. // Who is going to use this?
  591. //
  592. case IOCTL_NETBT_GET_CONNECTIONS:
  593. status = STATUS_NOT_SUPPORTED;
  594. break;
  595. default:
  596. status = STATUS_NOT_SUPPORTED;
  597. break;
  598. }
  599. cleanup:
  600. if (status != STATUS_PENDING) {
  601. Irp->IoStatus.Status = status;
  602. Irp->IoStatus.Information = 0;
  603. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  604. }
  605. return status;
  606. }
  607. NTSTATUS
  608. SmbDispatchInternalCtrl(
  609. IN PSMB_DEVICE Device,
  610. IN PIRP Irp
  611. )
  612. /*++
  613. Routine Description:
  614. This is the driver's dispatch function for all
  615. IRP_MJ_INTERNAL_DEVICE_CONTROL requests.
  616. Arguments:
  617. device - ptr to device object for target device
  618. pIrp - ptr to I/O request packet
  619. Return Value:
  620. NTSTATUS -- Indicates whether the request was successfully queued.
  621. --*/
  622. {
  623. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  624. PIO_STACK_LOCATION IrpSp = NULL;
  625. BOOL bShouldCompleteIrp = TRUE;
  626. if (SmbCfg.Unloading) {
  627. SmbPrint(SMB_TRACE_PNP, ("DispatchIntDevCtrl: Smb is unloading\n"));
  628. status = STATUS_INVALID_DEVICE_REQUEST;
  629. goto cleanup;
  630. }
  631. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  632. switch(IrpSp->MinorFunction) {
  633. case TDI_ACCEPT:
  634. status = SmbAccept(Device, Irp);
  635. break;
  636. case TDI_LISTEN:
  637. status = SmbListen(Device, Irp);
  638. break;
  639. case TDI_ASSOCIATE_ADDRESS:
  640. status = SmbAssociateAddress(Device, Irp);
  641. break;
  642. case TDI_DISASSOCIATE_ADDRESS:
  643. status = SmbDisAssociateAddress(Device, Irp);
  644. break;
  645. case TDI_CONNECT:
  646. status = SmbConnect(Device, Irp);
  647. break;
  648. case TDI_DISCONNECT:
  649. status = SmbDisconnect(Device, Irp);
  650. break;
  651. case TDI_SEND:
  652. status = SmbSend(Device, Irp);
  653. break;
  654. case TDI_RECEIVE:
  655. status = SmbReceive(Device, Irp);
  656. break;
  657. case TDI_SEND_DATAGRAM:
  658. status = SmbSendDatagram(Device, Irp);
  659. break;
  660. case TDI_RECEIVE_DATAGRAM:
  661. status = SmbReceiveDatagram(Device, Irp);
  662. break;
  663. case TDI_QUERY_INFORMATION:
  664. status = SmbQueryInformation(Device, Irp, &bShouldCompleteIrp);
  665. break;
  666. case TDI_SET_EVENT_HANDLER:
  667. status = SmbSetEventHandler(Device, Irp);
  668. break;
  669. case TDI_SET_INFORMATION:
  670. status = SmbSetInformation(Device, Irp);
  671. break;
  672. #if DBG
  673. //
  674. // 0x7f is a request by the Redir to put a "magic bullet" out
  675. // on the wire, to trigger the Network General Sniffer.
  676. //
  677. case 0x7f:
  678. #endif
  679. default:
  680. status = STATUS_NOT_SUPPORTED;
  681. break;
  682. }
  683. cleanup:
  684. if (status != STATUS_PENDING && bShouldCompleteIrp) {
  685. Irp->IoStatus.Status = status;
  686. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  687. } else {
  688. //
  689. // Don't mark IRP pending here because it could have been completed.
  690. //
  691. }
  692. return(status);
  693. } // SmbDispatchInternalCtrl
  694. NTSTATUS
  695. SmbQueryTargetDeviceRelationForConnection(
  696. PSMB_CONNECT ConnectObject,
  697. PIRP Irp
  698. )
  699. {
  700. PFILE_OBJECT TcpFileObject = NULL;
  701. PDEVICE_OBJECT TcpDeviceObject = NULL;
  702. PIO_STACK_LOCATION IrpSp = NULL, IrpSpNext = NULL;
  703. KIRQL Irql;
  704. NTSTATUS status = STATUS_CONNECTION_INVALID;
  705. SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
  706. if (NULL == ConnectObject->TcpContext) {
  707. TcpFileObject = NULL;
  708. } else {
  709. TcpFileObject = ConnectObject->TcpContext->Connect.ConnectObject;
  710. ASSERT(TcpFileObject != NULL);
  711. TcpDeviceObject = IoGetRelatedDeviceObject (TcpFileObject);
  712. if (NULL == TcpDeviceObject) {
  713. TcpFileObject = NULL;
  714. } else {
  715. ObReferenceObject(TcpFileObject);
  716. }
  717. }
  718. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  719. SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
  720. if (NULL == TcpFileObject) {
  721. status = STATUS_CONNECTION_INVALID;
  722. goto cleanup;
  723. }
  724. //
  725. // Simply pass the Irp on by to the Transport, and let it
  726. // fill in the info
  727. //
  728. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  729. IrpSpNext = IoGetNextIrpStackLocation (Irp);
  730. *IrpSpNext = *IrpSp;
  731. IoSetCompletionRoutine (Irp, NULL, NULL, FALSE, FALSE, FALSE);
  732. IrpSpNext->FileObject = TcpFileObject;
  733. IrpSpNext->DeviceObject = TcpDeviceObject;
  734. status = IoCallDriver(TcpDeviceObject, Irp);
  735. ObDereferenceObject(TcpFileObject);
  736. //
  737. // Irp could be completed. Don't access it anymore
  738. //
  739. return status;
  740. cleanup:
  741. Irp->IoStatus.Status = status;
  742. Irp->IoStatus.Information = 0;
  743. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  744. return status;
  745. }
  746. NTSTATUS
  747. SmbDispatchPnP(
  748. IN PSMB_DEVICE Device,
  749. IN PIRP Irp
  750. )
  751. {
  752. PIO_STACK_LOCATION IrpSp = NULL;
  753. PSMB_CLIENT_ELEMENT ClientObject = NULL;
  754. PSMB_CONNECT ConnectObject = NULL;
  755. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  756. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  757. switch (IrpSp->MinorFunction) {
  758. case IRP_MN_QUERY_DEVICE_RELATIONS:
  759. if (IrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation) {
  760. ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_TDI);
  761. ClientObject = SmbVerifyAndReferenceClient(IrpSp->FileObject, SMB_REF_TDI);
  762. if (ConnectObject != NULL) {
  763. ASSERT(ClientObject == NULL);
  764. return SmbQueryTargetDeviceRelationForConnection(ConnectObject, Irp);
  765. } else if (ClientObject != NULL) {
  766. SmbDereferenceClient(ClientObject, SMB_REF_TDI);
  767. status = STATUS_NOT_SUPPORTED;
  768. } else {
  769. ASSERT (0);
  770. }
  771. }
  772. break;
  773. default:
  774. break;
  775. }
  776. Irp->IoStatus.Status = status;
  777. Irp->IoStatus.Information = 0;
  778. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  779. return status;
  780. }
  781. VOID
  782. SmbUnload(
  783. IN PDRIVER_OBJECT DriverObject
  784. )
  785. /*++
  786. Routine Description:
  787. This is the SMB driver's dispatch function for Unload requests
  788. Arguments:
  789. DriverObject - Pointer to driver object created by the system.
  790. Return Value:
  791. None
  792. --*/
  793. {
  794. PAGED_CODE();
  795. SmbCfg.Unloading = TRUE;
  796. if (NULL == SmbCfg.DriverObject) {
  797. return;
  798. }
  799. #ifdef STANDALONE_SMB
  800. SmbShutdownTdi();
  801. #endif
  802. SmbShutdownRegistry();
  803. SmbShutdownDnsResolver();
  804. SmbShutdownIPv6NetbiosMappingTable();
  805. SmbDestroySmbDevice(SmbCfg.SmbDeviceObject);
  806. SmbCfg.SmbDeviceObject = NULL;
  807. #ifndef NO_LOOKASIDE_LIST
  808. if (SmbCfg.ConnectObjectPoolInitialized) {
  809. ExDeleteNPagedLookasideList(&SmbCfg.ConnectObjectPool);
  810. SmbCfg.ConnectObjectPoolInitialized = FALSE;
  811. }
  812. if (SmbCfg.TcpContextPoolInitialized) {
  813. ExDeleteNPagedLookasideList(&SmbCfg.TcpContextPool);
  814. SmbCfg.TcpContextPoolInitialized = FALSE;
  815. }
  816. #endif
  817. SmbCfg.DriverObject = NULL;
  818. ExDeleteResourceLite(&SmbCfg.Resource);
  819. NotifyNetBT(NETBT_RESTORE_NETBIOS_SMB);
  820. }