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.

3788 lines
110 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. fsctl.c
  5. Abstract:
  6. This module implements the NtDeviceIoControlFile API's for the NT datagram
  7. receiver (bowser).
  8. Author:
  9. Larry Osterman (larryo) 6-May-1991
  10. Revision History:
  11. 6-May-1991 larryo
  12. Created
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <stddef.h> // offsetof
  17. PEPROCESS
  18. RxGetRDBSSProcess();
  19. NTSTATUS
  20. BowserCommonDeviceIoControlFile (
  21. IN BOOLEAN Wait,
  22. IN BOOLEAN InFsd,
  23. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  24. IN PIRP Irp
  25. );
  26. NTSTATUS
  27. StartBowser (
  28. IN BOOLEAN Wait,
  29. IN BOOLEAN InFsd,
  30. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  31. IN PLMDR_REQUEST_PACKET InputBuffer,
  32. IN ULONG InputBufferLength
  33. );
  34. NTSTATUS
  35. BowserEnumTransports (
  36. IN BOOLEAN Wait,
  37. IN BOOLEAN InFsd,
  38. IN PLMDR_REQUEST_PACKET InputBuffer,
  39. IN PULONG InputBufferLength,
  40. OUT PVOID OutputBuffer,
  41. IN OUT ULONG OutputBufferLength,
  42. IN ULONG_PTR OutputBufferDisplacement
  43. );
  44. NTSTATUS
  45. EnumNames (
  46. IN BOOLEAN Wait,
  47. IN BOOLEAN InFsd,
  48. IN PLMDR_REQUEST_PACKET InputBuffer,
  49. IN PULONG InputBufferLength,
  50. OUT PVOID OutputBuffer,
  51. IN OUT ULONG OutputBufferLength,
  52. IN ULONG_PTR OutputBufferDisplacement
  53. );
  54. NTSTATUS
  55. BowserBindToTransport (
  56. IN BOOLEAN Wait,
  57. IN BOOLEAN InFsd,
  58. IN PLMDR_REQUEST_PACKET InputBuffer,
  59. IN ULONG InputBufferLength
  60. );
  61. NTSTATUS
  62. UnbindFromTransport (
  63. IN BOOLEAN Wait,
  64. IN BOOLEAN InFsd,
  65. IN PLMDR_REQUEST_PACKET InputBuffer,
  66. IN ULONG InputBufferLength
  67. );
  68. NTSTATUS
  69. AddBowserName (
  70. IN BOOLEAN Wait,
  71. IN BOOLEAN InFsd,
  72. IN PLMDR_REQUEST_PACKET InputBuffer,
  73. IN ULONG InputBufferLength
  74. );
  75. NTSTATUS
  76. StopBowser (
  77. IN BOOLEAN Wait,
  78. IN BOOLEAN InFsd,
  79. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  80. IN PLMDR_REQUEST_PACKET InputBuffer,
  81. IN ULONG InputBufferLength
  82. );
  83. NTSTATUS
  84. DeleteName (
  85. IN BOOLEAN Wait,
  86. IN BOOLEAN InFsd,
  87. IN PLMDR_REQUEST_PACKET InputBuffer,
  88. IN ULONG InputBufferLength
  89. );
  90. NTSTATUS
  91. EnumServers (
  92. IN BOOLEAN Wait,
  93. IN BOOLEAN InFsd,
  94. IN PLMDR_REQUEST_PACKET InputBuffer,
  95. IN PULONG InputBufferLength,
  96. OUT PVOID OutputBuffer,
  97. IN OUT ULONG OutputBufferLength,
  98. IN ULONG_PTR OutputBufferDisplacement
  99. );
  100. NTSTATUS
  101. WaitForBrowserRoleChange (
  102. IN PIRP Irp,
  103. IN PLMDR_REQUEST_PACKET InputBuffer,
  104. IN ULONG InputBufferLength
  105. );
  106. NTSTATUS
  107. WaitForNewMaster (
  108. IN PIRP Irp,
  109. IN PLMDR_REQUEST_PACKET InputBuffer,
  110. IN ULONG InputBufferLength
  111. );
  112. NTSTATUS
  113. HandleBecomeBackup (
  114. IN PIRP Irp,
  115. IN PLMDR_REQUEST_PACKET InputBuffer,
  116. IN ULONG InputBufferLength
  117. );
  118. NTSTATUS
  119. BecomeMaster (
  120. IN PIRP Irp,
  121. IN PLMDR_REQUEST_PACKET InputBuffer,
  122. IN ULONG InputBufferLength
  123. );
  124. NTSTATUS
  125. WaitForMasterAnnounce (
  126. IN PIRP Irp,
  127. IN PLMDR_REQUEST_PACKET InputBuffer,
  128. IN ULONG InputBufferLength
  129. );
  130. NTSTATUS
  131. WriteMailslot (
  132. IN PIRP Irp,
  133. IN PLMDR_REQUEST_PACKET InputBuffer,
  134. IN ULONG InputBufferLength,
  135. IN PVOID OutputBuffer,
  136. IN ULONG OutputBufferLength
  137. );
  138. NTSTATUS
  139. UpdateStatus (
  140. IN PIRP Irp,
  141. IN BOOLEAN InFsd,
  142. IN PLMDR_REQUEST_PACKET InputBuffer,
  143. IN ULONG InputBufferLength
  144. );
  145. NTSTATUS
  146. GetBrowserServerList(
  147. IN PIRP Irp,
  148. IN BOOLEAN Wait,
  149. IN BOOLEAN InFsd,
  150. IN PLMDR_REQUEST_PACKET InputBuffer,
  151. IN OUT PULONG InputBufferLength,
  152. IN PVOID OutputBuffer,
  153. IN ULONG OutputBufferLength,
  154. IN ULONG_PTR OutputBufferDisplacement
  155. );
  156. NTSTATUS
  157. QueryStatistics(
  158. IN PIRP Irp,
  159. OUT PBOWSER_STATISTICS OutputBuffer,
  160. IN OUT PULONG OutputBufferLength
  161. );
  162. NTSTATUS
  163. ResetStatistics(
  164. VOID
  165. );
  166. NTSTATUS
  167. BowserIpAddressChanged(
  168. IN PLMDR_REQUEST_PACKET InputBuffer
  169. );
  170. NTSTATUS
  171. BowserIpAddressChangedWorker(
  172. PTRANSPORT Transport,
  173. PVOID Context
  174. );
  175. NTSTATUS
  176. EnableDisableTransport (
  177. IN PLMDR_REQUEST_PACKET InputBuffer,
  178. IN ULONG InputBufferLength
  179. );
  180. NTSTATUS
  181. BowserRenameDomain (
  182. IN PLMDR_REQUEST_PACKET InputBuffer,
  183. IN ULONG InputBufferLength
  184. );
  185. PLMDR_REQUEST_PACKET
  186. RequestPacket32to64 (
  187. IN PLMDR_REQUEST_PACKET32 RequestPacket32,
  188. IN OUT PLMDR_REQUEST_PACKET RequestPacket);
  189. #ifdef ALLOC_PRAGMA
  190. #pragma alloc_text(PAGE, BowserCommonDeviceIoControlFile)
  191. #pragma alloc_text(PAGE, BowserFspDeviceIoControlFile)
  192. #pragma alloc_text(PAGE, BowserFsdDeviceIoControlFile)
  193. #pragma alloc_text(PAGE, StartBowser)
  194. #pragma alloc_text(PAGE, BowserEnumTransports)
  195. #pragma alloc_text(PAGE, EnumNames)
  196. #pragma alloc_text(PAGE, BowserBindToTransport)
  197. #pragma alloc_text(PAGE, UnbindFromTransport)
  198. #pragma alloc_text(PAGE, AddBowserName)
  199. #pragma alloc_text(PAGE, StopBowser)
  200. #pragma alloc_text(PAGE, DeleteName)
  201. #pragma alloc_text(PAGE, EnumServers)
  202. #pragma alloc_text(PAGE, WaitForBrowserRoleChange)
  203. #pragma alloc_text(PAGE, HandleBecomeBackup)
  204. #pragma alloc_text(PAGE, BecomeMaster)
  205. #pragma alloc_text(PAGE, WaitForMasterAnnounce)
  206. #pragma alloc_text(PAGE, WriteMailslot)
  207. #pragma alloc_text(PAGE, UpdateStatus)
  208. #pragma alloc_text(PAGE, BowserStopProcessingAnnouncements)
  209. #pragma alloc_text(PAGE, GetBrowserServerList)
  210. #pragma alloc_text(PAGE, WaitForNewMaster)
  211. #pragma alloc_text(PAGE, BowserIpAddressChanged)
  212. #pragma alloc_text(PAGE, BowserIpAddressChangedWorker)
  213. #pragma alloc_text(PAGE, EnableDisableTransport)
  214. #pragma alloc_text(PAGE, BowserRenameDomain )
  215. #pragma alloc_text(PAGE4BROW, QueryStatistics)
  216. #pragma alloc_text(PAGE4BROW, ResetStatistics)
  217. #pragma alloc_text(PAGE, RequestPacket32to64)
  218. #if DBG
  219. #pragma alloc_text(PAGE, BowserDebugCall)
  220. #endif
  221. #endif
  222. NTSTATUS
  223. BowserFspDeviceIoControlFile (
  224. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  225. IN PIRP Irp
  226. )
  227. /*++
  228. Routine Description:
  229. This routine is called when the last handle to the NT Bowser device
  230. driver is closed.
  231. Arguments:
  232. IN PDEVICE_OBJECT DeviceObject - Supplies a device object for the request.
  233. IN PIRP Irp - Supplies an IRP for the create request.
  234. Return Value:
  235. NTSTATUS - Final Status of operation
  236. --*/
  237. {
  238. NTSTATUS Status;
  239. PAGED_CODE();
  240. Status = BowserCommonDeviceIoControlFile(TRUE,
  241. FALSE,
  242. DeviceObject,
  243. Irp);
  244. return Status;
  245. }
  246. NTSTATUS
  247. BowserFsdDeviceIoControlFile (
  248. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  249. IN PIRP Irp
  250. )
  251. /*++
  252. Routine Description:
  253. This routine is called when the last handle to the NT Bowser device
  254. driver is closed.
  255. Arguments:
  256. IN PDEVICE_OBJECT DeviceObject - Supplies a device object for the request.
  257. IN PIRP Irp - Supplies an IRP for the create request.
  258. Return Value:
  259. NTSTATUS - Final Status of operation
  260. --*/
  261. {
  262. NTSTATUS Status;
  263. PAGED_CODE();
  264. #ifndef PRODUCT1
  265. FsRtlEnterFileSystem();
  266. #endif
  267. //
  268. // Call the routine shared by the FSD/FSP.
  269. //
  270. // Even though this is the FSD, indicate we're in the FSP if our caller
  271. // is in the system process. This allows us to avoid posting this
  272. // request to a worker thread if we're already in one.
  273. //
  274. Status = BowserCommonDeviceIoControlFile(
  275. IoIsOperationSynchronous(Irp),
  276. (BOOLEAN)(IoGetCurrentProcess() != BowserFspProcess),
  277. DeviceObject,
  278. Irp);
  279. #ifndef PRODUCT1
  280. FsRtlExitFileSystem();
  281. #endif
  282. return Status;
  283. }
  284. NTSTATUS
  285. BowserCommonDeviceIoControlFile (
  286. IN BOOLEAN Wait,
  287. IN BOOLEAN InFsd,
  288. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  289. IN PIRP Irp
  290. )
  291. /*++
  292. Routine Description:
  293. This routine is called when the last handle to the NT Bowser device
  294. driver is closed.
  295. Arguments:
  296. IN PDEVICE_OBJECT DeviceObject - Supplies a device object for the request.
  297. IN PIRP Irp - Supplies an IRP for the create request.
  298. Return Value:
  299. NTSTATUS - Final Status of operation
  300. --*/
  301. {
  302. NTSTATUS Status = STATUS_SUCCESS;
  303. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  304. PVOID InputBuffer;
  305. ULONG InputBufferLength;
  306. PVOID OutputBuffer = NULL;
  307. ULONG OutputBufferLength;
  308. ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  309. ULONG MinorFunction = IrpSp->MinorFunction;
  310. LPBYTE OriginalInputBuffer = NULL;
  311. BOOLEAN CopyEnumResultsToCaller = FALSE;
  312. BOOLEAN fThunk32bit;
  313. LMDR_REQUEST_PACKET ReqPacketBuffer;
  314. // Local Definitions
  315. #define BOWSECURITYCHECK( _irp, _irpsp, _status) \
  316. if (_irp->RequestorMode != KernelMode && \
  317. !IoIsSystemThread ( _irp->Tail.Overlay.Thread) && \
  318. !BowserSecurityCheck(_irp, _irpsp, &_status)){ \
  319. try_return (_status = (NT_SUCCESS(_status) ? STATUS_ACCESS_DENIED : _status) ); \
  320. }
  321. PAGED_CODE();
  322. try {
  323. //
  324. // Before we call the worker functions, prep the parameters to those
  325. // functions.
  326. //
  327. //
  328. // Is caller in 32bit process?
  329. // we'll process irp field size calculations depending on this knowledge.
  330. //
  331. #ifdef _WIN64
  332. fThunk32bit = IoIs32bitProcess(Irp);
  333. //
  334. // Filter out all IOCTLs we do not support:
  335. // Since the browser is getting phased out, we would support only those
  336. // IOCTLs used only for NetServerEnum.
  337. //
  338. if ( fThunk32bit &&
  339. IoControlCode != IOCTL_LMDR_ENUMERATE_TRANSPORTS &&
  340. IoControlCode != IOCTL_LMDR_GET_BROWSER_SERVER_LIST ) {
  341. // Only these ioctl's are supported in thunking mode
  342. try_return(Status = STATUS_NOT_IMPLEMENTED);
  343. }
  344. #else
  345. // If we're in 32 bit (e.g. call above isn't available), use unchanged functionality
  346. // i.e. pure new-64-bit == pure old-32-bit == homogeneous environment. Thus, set to FALSE.
  347. fThunk32bit = FALSE;
  348. #endif
  349. //
  350. // The input buffer is either in Irp->AssociatedIrp.SystemBuffer, or
  351. // in the Type3InputBuffer for type 3 IRP's.
  352. //
  353. InputBuffer = Irp->AssociatedIrp.SystemBuffer;
  354. //
  355. // The lengths of the various buffers are easy to find, they're in the
  356. // Irp stack location.
  357. //
  358. OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  359. InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  360. //
  361. // Input buffer length sanity
  362. // * Wow64 -- support 32 bit clients on 64 bit systems (see bug 454130)
  363. //
  364. if ( InputBufferLength != 0 ) {
  365. // use 32 bit struct
  366. if ( fThunk32bit ) {
  367. if ( InputBufferLength < offsetof( LMDR_REQUEST_PACKET32,Parameters ) ) {
  368. dlog(DPRT_FSCTL, ("IoControlFile: input buffer too short %d (32 bit)\n",
  369. InputBufferLength));
  370. try_return(Status = STATUS_INVALID_PARAMETER);
  371. }
  372. //
  373. // Convert buffer to 64 presentation
  374. //
  375. if (InputBuffer) {
  376. #if DBG
  377. //
  378. // Temporary:
  379. // We're not aware of any such cases where there are 32 bit ioctl conversions
  380. // in FSP. Print out a debug notice for debugging/tracing.
  381. //
  382. DbgPrint("[mrxsmb!fsctl.c] Converting 32 bit ioctl 0x%x in FSP\n",
  383. IoControlCode);
  384. #endif
  385. // sanity on buffer
  386. ENSURE_BUFFER_BOUNDARIES(InputBuffer, &(((PLMDR_REQUEST_PACKET32)InputBuffer)->TransportName));
  387. ENSURE_BUFFER_BOUNDARIES(InputBuffer, &(((PLMDR_REQUEST_PACKET32)InputBuffer)->EmulatedDomainName));
  388. // convert buffer
  389. OriginalInputBuffer = (LPBYTE)InputBuffer;
  390. InputBuffer = (PVOID)RequestPacket32to64(
  391. (PLMDR_REQUEST_PACKET32)InputBuffer,
  392. &ReqPacketBuffer);
  393. // fix length
  394. InputBufferLength += sizeof(LMDR_REQUEST_PACKET) - sizeof(LMDR_REQUEST_PACKET32);
  395. }
  396. }
  397. // use homogeneous environment struct
  398. if (InputBufferLength < offsetof( LMDR_REQUEST_PACKET,Parameters ) ) {
  399. dlog(DPRT_FSCTL, ("IoControlFile: input buffer too short %d\n", InputBufferLength));
  400. try_return(Status = STATUS_INVALID_PARAMETER);
  401. }
  402. } // inputbufferlength != 0
  403. //
  404. // If we are in the FSD, then the input buffer is in Type3InputBuffer
  405. // on type 3 api's, not in SystemBuffer.
  406. //
  407. // Capture the type 3 buffer.
  408. //
  409. if (InputBuffer == NULL &&
  410. InputBufferLength != 0) {
  411. //
  412. // This had better be a type 3 IOCTL.
  413. //
  414. if ((IoControlCode & 3) == METHOD_NEITHER) {
  415. PLMDR_REQUEST_PACKET RequestPacket;
  416. //
  417. // Capture the input buffer.
  418. //
  419. OriginalInputBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  420. Status = BowserConvertType3IoControlToType2IoControl( Irp, IrpSp);
  421. if ( !NT_SUCCESS(Status) ) {
  422. try_return( Status );
  423. }
  424. //
  425. // Relocate all the pointers in the input buffer.
  426. // (Don't validate the pointers here. Not all function codes
  427. // initialize these fields. For such function codes,
  428. // this "relocation" may be changing the uninitialized garbage.)
  429. //
  430. RequestPacket = Irp->AssociatedIrp.SystemBuffer;
  431. //
  432. // Protect against callers that didn't specify an input buffer.
  433. //
  434. if ( RequestPacket == NULL ) {
  435. try_return(Status = STATUS_INVALID_PARAMETER);
  436. }
  437. if (fThunk32bit) {
  438. // convert buffer
  439. RequestPacket = (PVOID)RequestPacket32to64(
  440. (PLMDR_REQUEST_PACKET32)RequestPacket,
  441. &ReqPacketBuffer);
  442. // fix length
  443. InputBufferLength += sizeof(LMDR_REQUEST_PACKET) - sizeof(LMDR_REQUEST_PACKET32);
  444. // remark: sanity on buffers is done immediately below.
  445. // (cannot apply ENSURE_BUFFER_BOUNDARIES test to type3 ioctl)
  446. }
  447. //
  448. // Initialize the embedded unicode strings to NULL for IOCTLs which
  449. // don't reference them. The user-mode components don't always
  450. // initialize buffers to zero.
  451. //
  452. if (IoControlCode == IOCTL_LMDR_START ||
  453. IoControlCode == IOCTL_LMDR_STOP) {
  454. RtlInitUnicodeString(&RequestPacket->EmulatedDomainName,NULL);
  455. RtlInitUnicodeString(&RequestPacket->TransportName,NULL);
  456. }
  457. if (RequestPacket->Version == LMDR_REQUEST_PACKET_VERSION_DOM ||
  458. RequestPacket->Version == LMDR_REQUEST_PACKET_VERSION) {
  459. //
  460. // Relocate the transport name associated with this request.
  461. //
  462. if (RequestPacket->TransportName.Length != 0) {
  463. PCHAR BufferStart = (PCHAR)RequestPacket->TransportName.Buffer;
  464. PCHAR BufferEnd = ((PCHAR)RequestPacket->TransportName.Buffer)+
  465. RequestPacket->TransportName.Length;
  466. //
  467. // Verify that the entire buffer indicated is contained within the input buffer.
  468. //
  469. if ((BufferStart < OriginalInputBuffer) ||
  470. (BufferStart > OriginalInputBuffer + InputBufferLength) ||
  471. (BufferEnd < OriginalInputBuffer) ||
  472. (BufferEnd > OriginalInputBuffer + InputBufferLength)) {
  473. //
  474. // An invalid input string was specified.
  475. //
  476. try_return(Status = STATUS_INVALID_PARAMETER);
  477. }
  478. //
  479. // The name in within bounds, so convert it.
  480. //
  481. RequestPacket->TransportName.Buffer = (PWSTR)
  482. (((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer)+
  483. (((ULONG_PTR)BufferStart) -
  484. ((ULONG_PTR)OriginalInputBuffer)));
  485. } else {
  486. RequestPacket->TransportName.MaximumLength = 0;
  487. RequestPacket->TransportName.Buffer = NULL;
  488. }
  489. //
  490. // Relocate the EmulatedDomain name associated with this request.
  491. //
  492. if (RequestPacket->EmulatedDomainName.Length != 0 &&
  493. RequestPacket->Version != LMDR_REQUEST_PACKET_VERSION) {
  494. PCHAR BufferStart = (PCHAR)RequestPacket->EmulatedDomainName.Buffer;
  495. PCHAR BufferEnd = ((PCHAR)RequestPacket->EmulatedDomainName.Buffer)+
  496. RequestPacket->EmulatedDomainName.Length;
  497. //
  498. // Verify that the entire buffer indicated is contained within the input buffer.
  499. //
  500. if ((BufferStart < OriginalInputBuffer) ||
  501. (BufferStart > OriginalInputBuffer + InputBufferLength) ||
  502. (BufferEnd < OriginalInputBuffer) ||
  503. (BufferEnd > OriginalInputBuffer + InputBufferLength)) {
  504. //
  505. // An invalid input string was specified.
  506. //
  507. try_return(Status = STATUS_INVALID_PARAMETER);
  508. }
  509. //
  510. // The name in within bounds, so convert it.
  511. //
  512. RequestPacket->EmulatedDomainName.Buffer = (PWSTR)
  513. (((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer)+
  514. (((ULONG_PTR)BufferStart) -
  515. ((ULONG_PTR)OriginalInputBuffer)));
  516. } else {
  517. RequestPacket->EmulatedDomainName.MaximumLength = 0;
  518. RequestPacket->EmulatedDomainName.Buffer = NULL;
  519. }
  520. } else {
  521. try_return(Status = STATUS_INVALID_PARAMETER);
  522. }
  523. //
  524. // Use the newly allocated input buffer from now on
  525. //
  526. InputBuffer = RequestPacket;
  527. } else {
  528. try_return(Status = STATUS_INVALID_PARAMETER);
  529. }
  530. }
  531. //
  532. // Probe/lock the output buffer in memory, or is
  533. // available in the input buffer.
  534. //
  535. try {
  536. PLMDR_REQUEST_PACKET RequestPacket = InputBuffer;
  537. if (OutputBufferLength != 0) {
  538. BowserMapUsersBuffer(Irp, &OutputBuffer, OutputBufferLength);
  539. if (OutputBuffer == NULL)
  540. {
  541. //
  542. // Error: Could not map user buffer (out of resources?)
  543. //
  544. try_return (Status = STATUS_INSUFFICIENT_RESOURCES);
  545. }
  546. }
  547. //
  548. // Convert old version requests to new version requests.
  549. //
  550. if (RequestPacket != NULL) {
  551. if (InputBufferLength < offsetof( LMDR_REQUEST_PACKET,Parameters )) {
  552. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  553. }
  554. if (RequestPacket->Version == LMDR_REQUEST_PACKET_VERSION ) {
  555. RtlInitUnicodeString( &RequestPacket->EmulatedDomainName, NULL );
  556. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  557. }
  558. }
  559. } except (BR_EXCEPTION) {
  560. try_return (Status = GetExceptionCode());
  561. }
  562. switch (MinorFunction) {
  563. //
  564. // The NT redirector does not support local physical media, all
  565. // such IoControlFile requests are unsupported.
  566. //
  567. case IRP_MN_USER_FS_REQUEST:
  568. //
  569. // If we're not starting the bowser,
  570. // make sure it is started.
  571. //
  572. ExAcquireResourceSharedLite(&BowserDataResource, TRUE);
  573. if ( IoControlCode != IOCTL_LMDR_START ) {
  574. if (BowserData.Initialized != TRUE) {
  575. dlog(DPRT_FSCTL, ("Bowser not started.\n"));
  576. ExReleaseResourceLite(&BowserDataResource);
  577. Status = STATUS_REDIRECTOR_NOT_STARTED;
  578. break;
  579. }
  580. }
  581. //
  582. // Ensure a IOCTL_LMDR_STOP doesn't come in while
  583. // we're working.
  584. //
  585. InterlockedIncrement( &BowserOperationCount );
  586. ExReleaseResourceLite(&BowserDataResource);
  587. switch (IoControlCode) {
  588. case IOCTL_LMDR_START:
  589. Status = StartBowser(Wait, InFsd, DeviceObject, InputBuffer, InputBufferLength);
  590. break;
  591. case IOCTL_LMDR_STOP:
  592. Status = StopBowser(Wait, InFsd, DeviceObject, InputBuffer, InputBufferLength);
  593. break;
  594. case IOCTL_LMDR_BIND_TO_TRANSPORT:
  595. case IOCTL_LMDR_BIND_TO_TRANSPORT_DOM:
  596. BOWSECURITYCHECK ( Irp, IrpSp, Status );
  597. Status = BowserBindToTransport(Wait, InFsd, InputBuffer, InputBufferLength);
  598. break;
  599. case IOCTL_LMDR_UNBIND_FROM_TRANSPORT:
  600. case IOCTL_LMDR_UNBIND_FROM_TRANSPORT_DOM:
  601. Status = UnbindFromTransport(Wait, InFsd, InputBuffer, InputBufferLength);
  602. break;
  603. case IOCTL_LMDR_ENUMERATE_TRANSPORTS:
  604. Status = BowserEnumTransports(Wait, InFsd,
  605. InputBuffer, &InputBufferLength,
  606. OutputBuffer, OutputBufferLength,
  607. (PUCHAR)OutputBuffer - (PUCHAR)Irp->UserBuffer);
  608. CopyEnumResultsToCaller = TRUE;
  609. break;
  610. case IOCTL_LMDR_ENUMERATE_NAMES:
  611. Status = EnumNames(Wait, InFsd,
  612. InputBuffer, &InputBufferLength,
  613. OutputBuffer, OutputBufferLength,
  614. (PUCHAR)OutputBuffer - (PUCHAR)Irp->UserBuffer);
  615. CopyEnumResultsToCaller = TRUE;
  616. break;
  617. case IOCTL_LMDR_ADD_NAME:
  618. case IOCTL_LMDR_ADD_NAME_DOM:
  619. BOWSECURITYCHECK(Irp, IrpSp, Status);
  620. Status = AddBowserName(Wait, InFsd, InputBuffer, InputBufferLength);
  621. break;
  622. case IOCTL_LMDR_DELETE_NAME:
  623. case IOCTL_LMDR_DELETE_NAME_DOM:
  624. Status = DeleteName (Wait, InFsd, InputBuffer, InputBufferLength);
  625. break;
  626. case IOCTL_LMDR_ENUMERATE_SERVERS:
  627. Status = EnumServers(Wait, InFsd,
  628. InputBuffer, &InputBufferLength,
  629. OutputBuffer, OutputBufferLength,
  630. (PUCHAR)OutputBuffer - (PUCHAR)Irp->UserBuffer);
  631. CopyEnumResultsToCaller = TRUE;
  632. break;
  633. case IOCTL_LMDR_GET_BROWSER_SERVER_LIST:
  634. Status = GetBrowserServerList(Irp, Wait, InFsd,
  635. InputBuffer, &InputBufferLength,
  636. OutputBuffer, OutputBufferLength,
  637. (PUCHAR)OutputBuffer - (PUCHAR)Irp->UserBuffer);
  638. CopyEnumResultsToCaller = TRUE;
  639. break;
  640. case IOCTL_LMDR_GET_MASTER_NAME:
  641. Status = GetMasterName(Irp, Wait, InFsd,
  642. InputBuffer, InputBufferLength );
  643. break;
  644. case IOCTL_LMDR_BECOME_BACKUP:
  645. Status = HandleBecomeBackup(Irp, InputBuffer, InputBufferLength);
  646. break;
  647. case IOCTL_LMDR_BECOME_MASTER:
  648. Status = BecomeMaster(Irp, InputBuffer, InputBufferLength);
  649. break;
  650. case IOCTL_LMDR_WAIT_FOR_MASTER_ANNOUNCE:
  651. Status = WaitForMasterAnnounce(Irp, InputBuffer, InputBufferLength);
  652. break;
  653. case IOCTL_LMDR_WRITE_MAILSLOT:
  654. Status = WriteMailslot(Irp, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength);
  655. break;
  656. case IOCTL_LMDR_UPDATE_STATUS:
  657. BOWSECURITYCHECK(Irp, IrpSp, Status);
  658. Status = UpdateStatus(Irp, InFsd, InputBuffer, InputBufferLength );
  659. break;
  660. case IOCTL_LMDR_CHANGE_ROLE:
  661. Status = WaitForBrowserRoleChange(Irp, InputBuffer, InputBufferLength );
  662. break;
  663. case IOCTL_LMDR_NEW_MASTER_NAME:
  664. Status = WaitForNewMaster(Irp, InputBuffer, InputBufferLength);
  665. break;
  666. case IOCTL_LMDR_QUERY_STATISTICS:
  667. Status = QueryStatistics(Irp, OutputBuffer, &OutputBufferLength);
  668. InputBufferLength = OutputBufferLength;
  669. break;
  670. case IOCTL_LMDR_RESET_STATISTICS:
  671. Status = ResetStatistics();
  672. break;
  673. case IOCTL_LMDR_NETLOGON_MAILSLOT_READ:
  674. Status = BowserReadPnp( Irp, OutputBufferLength, NETLOGON_PNP );
  675. break;
  676. case IOCTL_LMDR_NETLOGON_MAILSLOT_ENABLE:
  677. BOWSECURITYCHECK ( Irp, IrpSp, Status );
  678. if (InputBufferLength <
  679. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters)+sizeof(DWORD)) {
  680. Status = STATUS_INVALID_PARAMETER;
  681. } else {
  682. Status = BowserEnablePnp( InputBuffer, NETLOGON_PNP );
  683. }
  684. break;
  685. case IOCTL_LMDR_IP_ADDRESS_CHANGED:
  686. BOWSECURITYCHECK(Irp, IrpSp, Status);
  687. Status = BowserIpAddressChanged( InputBuffer );
  688. break;
  689. case IOCTL_LMDR_ENABLE_DISABLE_TRANSPORT:
  690. Status = EnableDisableTransport( InputBuffer, InputBufferLength );
  691. break;
  692. case IOCTL_LMDR_BROWSER_PNP_READ:
  693. Status = BowserReadPnp( Irp, OutputBufferLength, BROWSER_PNP );
  694. break;
  695. case IOCTL_LMDR_BROWSER_PNP_ENABLE:
  696. if (InputBufferLength <
  697. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters)+sizeof(DWORD)) {
  698. Status = STATUS_INVALID_PARAMETER;
  699. } else {
  700. Status = BowserEnablePnp( InputBuffer, BROWSER_PNP );
  701. }
  702. break;
  703. case IOCTL_LMDR_RENAME_DOMAIN:
  704. BOWSECURITYCHECK(Irp, IrpSp, Status);
  705. Status = BowserRenameDomain( InputBuffer, InputBufferLength );
  706. break;
  707. #if DBG
  708. case IOCTL_LMDR_DEBUG_CALL:
  709. Status = BowserDebugCall(InputBuffer, InputBufferLength);
  710. break;
  711. #endif
  712. default:
  713. dlog(DPRT_FSCTL, ("Unknown IoControlFile %d\n", MinorFunction));
  714. Status = STATUS_NOT_IMPLEMENTED;
  715. break;
  716. }
  717. //
  718. // Allow IOCTL_LMDR_STOP
  719. //
  720. InterlockedDecrement( &BowserOperationCount );
  721. break;
  722. //
  723. // All other IoControlFile API's
  724. //
  725. default:
  726. dlog(DPRT_FSCTL, ("Unknown IoControlFile %d\n", MinorFunction));
  727. Status = STATUS_NOT_IMPLEMENTED;
  728. break;
  729. }
  730. if (Status != STATUS_PENDING) {
  731. //
  732. // Return the size of the input buffer to the caller.
  733. // (But never more than the output buffer size).
  734. //
  735. Irp->IoStatus.Information = min(InputBufferLength, OutputBufferLength);
  736. //
  737. // If the input buffer needs to be copied back to the caller,
  738. // do so now.
  739. //
  740. if ( CopyEnumResultsToCaller && OriginalInputBuffer != NULL ) {
  741. try {
  742. if (Irp->RequestorMode != KernelMode) {
  743. ProbeForWrite( OriginalInputBuffer,
  744. InputBufferLength,
  745. sizeof(DWORD) );
  746. }
  747. //
  748. // Copy the enumeration results to the caller.
  749. //
  750. // Don't copy the entire request packet back to the caller.
  751. // It has other modified fields (e.g., relocated pointers)
  752. //
  753. if ( fThunk32bit ) {
  754. // typecast to 32bit buffer
  755. ((PLMDR_REQUEST_PACKET32)OriginalInputBuffer)->Parameters.EnumerateNames.EntriesRead =
  756. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.EntriesRead;
  757. ((PLMDR_REQUEST_PACKET32)OriginalInputBuffer)->Parameters.EnumerateNames.TotalEntries =
  758. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.TotalEntries;
  759. ((PLMDR_REQUEST_PACKET32)OriginalInputBuffer)->Parameters.EnumerateNames.TotalBytesNeeded =
  760. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.TotalBytesNeeded;
  761. ((PLMDR_REQUEST_PACKET32)OriginalInputBuffer)->Parameters.EnumerateNames.ResumeHandle =
  762. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.ResumeHandle;
  763. }
  764. else{
  765. // native mode
  766. ((PLMDR_REQUEST_PACKET)OriginalInputBuffer)->Parameters.EnumerateNames.EntriesRead =
  767. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.EntriesRead;
  768. ((PLMDR_REQUEST_PACKET)OriginalInputBuffer)->Parameters.EnumerateNames.TotalEntries =
  769. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.TotalEntries;
  770. ((PLMDR_REQUEST_PACKET)OriginalInputBuffer)->Parameters.EnumerateNames.TotalBytesNeeded =
  771. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.TotalBytesNeeded;
  772. ((PLMDR_REQUEST_PACKET)OriginalInputBuffer)->Parameters.EnumerateNames.ResumeHandle =
  773. ((PLMDR_REQUEST_PACKET)InputBuffer)->Parameters.EnumerateNames.ResumeHandle;
  774. }
  775. } except (BR_EXCEPTION) {
  776. try_return (Status = GetExceptionCode());
  777. }
  778. }
  779. }
  780. try_exit:NOTHING;
  781. } finally {
  782. if (Status == STATUS_PENDING) {
  783. //
  784. // If this is one of the longterm FsControl APIs, they are
  785. // not to be processed in the FSP, they should just be returned
  786. // to the caller with STATUS_PENDING.
  787. //
  788. if ((MinorFunction == IRP_MN_USER_FS_REQUEST) &&
  789. ((IoControlCode == IOCTL_LMDR_GET_MASTER_NAME) ||
  790. (IoControlCode == IOCTL_LMDR_BECOME_BACKUP) ||
  791. (IoControlCode == IOCTL_LMDR_BECOME_MASTER) ||
  792. (IoControlCode == IOCTL_LMDR_CHANGE_ROLE) ||
  793. (IoControlCode == IOCTL_LMDR_NEW_MASTER_NAME) ||
  794. (IoControlCode == IOCTL_LMDR_WAIT_FOR_MASTER_ANNOUNCE) ||
  795. (IoControlCode == IOCTL_LMDR_NETLOGON_MAILSLOT_READ) ||
  796. (IoControlCode == IOCTL_LMDR_BROWSER_PNP_READ))) {
  797. // return Status;
  798. //
  799. // If this call is to be processed in the FSP,
  800. // do it.
  801. //
  802. // The input buffer has already been captured and relocated.
  803. //
  804. } else {
  805. Status = BowserFsdPostToFsp(DeviceObject, Irp);
  806. if (Status != STATUS_PENDING) {
  807. BowserCompleteRequest(Irp, Status);
  808. }
  809. }
  810. } else {
  811. BowserCompleteRequest(Irp, Status);
  812. }
  813. }
  814. dlog(DPRT_FSCTL, ("Returning status: %X\n", Status));
  815. #undef BOWSECURITYCHECK
  816. return Status;
  817. }
  818. NTSTATUS
  819. StartBowser (
  820. IN BOOLEAN Wait,
  821. IN BOOLEAN InFsd,
  822. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  823. IN PLMDR_REQUEST_PACKET InputBuffer,
  824. IN ULONG InputBufferLength
  825. )
  826. /*++
  827. Routine Description:
  828. This routine adds a reference to a file object created with .
  829. Arguments:
  830. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  831. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  832. Return Value:
  833. NTSTATUS
  834. --*/
  835. {
  836. NTSTATUS Status;
  837. PAGED_CODE();
  838. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Initialize request\n"));
  839. if (!ExAcquireResourceExclusiveLite(&BowserDataResource, Wait)) {
  840. return STATUS_PENDING;
  841. }
  842. try {
  843. if (BowserData.Initialized == TRUE) {
  844. dlog(DPRT_FSCTL, ("Bowser already started\n"));
  845. try_return(Status = STATUS_REDIRECTOR_STARTED);
  846. }
  847. //
  848. // Load a pointer to the users input buffer into InputBuffer
  849. //
  850. if (InputBufferLength != sizeof(LMDR_REQUEST_PACKET)) {
  851. try_return(Status = STATUS_INVALID_PARAMETER);
  852. }
  853. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  854. try_return(Status = STATUS_INVALID_PARAMETER);
  855. }
  856. BowserFspProcess = RxGetRDBSSProcess();
  857. BowserData.IllegalDatagramThreshold = InputBuffer->Parameters.Start.IllegalDatagramThreshold;
  858. BowserData.EventLogResetFrequency = InputBuffer->Parameters.Start.EventLogResetFrequency;
  859. BowserData.NumberOfMailslotBuffers = InputBuffer->Parameters.Start.NumberOfMailslotBuffers;
  860. BowserData.NumberOfServerAnnounceBuffers = InputBuffer->Parameters.Start.NumberOfServerAnnounceBuffers;
  861. BowserLogElectionPackets = InputBuffer->Parameters.Start.LogElectionPackets;
  862. BowserData.IsLanmanNt = InputBuffer->Parameters.Start.IsLanManNt;
  863. #ifdef ENABLE_PSEUDO_BROWSER
  864. BowserData.PseudoServerLevel = BROWSER_NON_PSEUDO;
  865. #endif
  866. Status = BowserpInitializeAnnounceTable();
  867. if (!NT_SUCCESS(Status)) {
  868. try_return(Status);
  869. }
  870. BowserData.Initialized = TRUE;
  871. //
  872. // Now that we know the browser parameters, we can kick off the
  873. // browser timer...
  874. //
  875. IoStartTimer((PDEVICE_OBJECT )DeviceObject);
  876. KeQuerySystemTime(&BowserStartTime);
  877. RtlZeroMemory(&BowserStatistics, sizeof(BOWSER_STATISTICS));
  878. KeQuerySystemTime(&BowserStatistics.StartTime);
  879. KeInitializeSpinLock(&BowserStatisticsLock);
  880. try_return(Status = STATUS_SUCCESS);
  881. try_exit:NOTHING;
  882. } finally {
  883. ExReleaseResourceLite(&BowserDataResource);
  884. }
  885. return Status;
  886. UNREFERENCED_PARAMETER(Wait);
  887. UNREFERENCED_PARAMETER(InFsd);
  888. }
  889. NTSTATUS
  890. StopBowser (
  891. IN BOOLEAN Wait,
  892. IN BOOLEAN InFsd,
  893. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject,
  894. IN PLMDR_REQUEST_PACKET InputBuffer,
  895. IN ULONG InputBufferLength
  896. )
  897. /*++
  898. Routine Description:
  899. This routine sets the username for the NT redirector.
  900. Arguments:
  901. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  902. IN PBOWSER_FS_DEVICE_OBJECT DeviceObject, - Device object of destination of Irp
  903. IN PIRP Irp, - Io Request Packet for request
  904. IN PIO_STACK_LOCATION IrpSp - Current I/O Stack location for request
  905. Return Value:
  906. NTSTATUS
  907. --*/
  908. {
  909. NTSTATUS Status;
  910. PAGED_CODE();
  911. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Initialize request\n"));
  912. if (!ExAcquireResourceExclusiveLite(&BowserDataResource, Wait)) {
  913. return STATUS_PENDING;
  914. }
  915. try {
  916. if (BowserData.Initialized != TRUE) {
  917. try_return(Status = STATUS_REDIRECTOR_NOT_STARTED);
  918. }
  919. //
  920. // Load a pointer to the users input buffer into InputBuffer
  921. //
  922. if (InputBufferLength != sizeof(LMDR_REQUEST_PACKET)) {
  923. try_return(Status = STATUS_INVALID_PARAMETER);
  924. }
  925. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  926. try_return(Status = STATUS_INVALID_PARAMETER);
  927. }
  928. if (InFsd) {
  929. try_return(Status = STATUS_PENDING);
  930. }
  931. //
  932. // Prevent any new callers.
  933. //
  934. BowserData.Initialized = FALSE;
  935. //
  936. // Loop until our caller has the last outstanding reference.
  937. //
  938. while ( InterlockedDecrement( &BowserOperationCount ) != 0 ) {
  939. LARGE_INTEGER Interval;
  940. InterlockedIncrement( &BowserOperationCount );
  941. // Don't hold the resource while we're waiting.
  942. ExReleaseResourceLite(&BowserDataResource);
  943. // Sleep to relinquish the CPU
  944. Interval.QuadPart = -1000*10000; // .1 second
  945. KeDelayExecutionThread( KernelMode, FALSE, &Interval );
  946. ExAcquireResourceExclusiveLite(&BowserDataResource, TRUE);
  947. }
  948. InterlockedIncrement( &BowserOperationCount );
  949. //
  950. // Finally stop the bowser now that we know we have exclusive access
  951. //
  952. Status = BowserUnbindFromAllTransports();
  953. if (!NT_SUCCESS(Status)) {
  954. dlog(DPRT_FSCTL, ("StopBowser: Failed to Unbind transports <0x%x>\n", Status));
  955. // Fall through to continue cleanup regardless.
  956. }
  957. Status = BowserpUninitializeAnnounceTable();
  958. if (!NT_SUCCESS(Status)) {
  959. dlog(DPRT_FSCTL, ("StopBowser: Failed to Uninitialize AnnounceTable <0x%x>\n", Status));
  960. // Fall through to continue cleanup regardless.
  961. }
  962. //
  963. // Now that we know the browser parameters, we can kick off the
  964. // browser timer...
  965. //
  966. IoStopTimer((PDEVICE_OBJECT )DeviceObject);
  967. try_return(Status = STATUS_SUCCESS);
  968. try_exit:NOTHING;
  969. } finally {
  970. ExReleaseResourceLite(&BowserDataResource);
  971. }
  972. return Status;
  973. UNREFERENCED_PARAMETER(Wait);
  974. UNREFERENCED_PARAMETER(InFsd);
  975. }
  976. NTSTATUS
  977. BowserBindToTransport (
  978. IN BOOLEAN Wait,
  979. IN BOOLEAN InFsd,
  980. IN PLMDR_REQUEST_PACKET InputBuffer,
  981. IN ULONG InputBufferLength
  982. )
  983. /*++
  984. Routine Description:
  985. This routine adds a reference to a file object created with .
  986. Arguments:
  987. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  988. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  989. Return Value:
  990. NTSTATUS
  991. --*/
  992. {
  993. NTSTATUS Status;
  994. UNICODE_STRING TransportName;
  995. UNICODE_STRING EmulatedComputerName;
  996. UNICODE_STRING EmulatedDomainName;
  997. BOOLEAN ProcessAttached = FALSE;
  998. KAPC_STATE ApcState;
  999. PAGED_CODE();
  1000. if (IoGetCurrentProcess() != BowserFspProcess) {
  1001. KeStackAttachProcess(BowserFspProcess, &ApcState );
  1002. ProcessAttached = TRUE;
  1003. }
  1004. try {
  1005. //
  1006. // Check some fields in the input buffer.
  1007. //
  1008. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.Bind.TransportName)) {
  1009. try_return(Status = STATUS_INVALID_PARAMETER);
  1010. }
  1011. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1012. try_return(Status = STATUS_INVALID_PARAMETER);
  1013. }
  1014. //
  1015. // Get the transport name from the input buffer.
  1016. //
  1017. TransportName.MaximumLength = TransportName.Length = (USHORT )
  1018. InputBuffer->Parameters.Bind.TransportNameLength;
  1019. TransportName.Buffer = InputBuffer->Parameters.Bind.TransportName;
  1020. ENSURE_IN_INPUT_BUFFER( &TransportName, FALSE, FALSE );
  1021. //
  1022. // Ignore the new NetbiosSmb transport
  1023. //
  1024. {
  1025. UNICODE_STRING NetbiosSmb;
  1026. RtlInitUnicodeString( &NetbiosSmb, L"\\Device\\NetbiosSmb" );
  1027. if ( RtlEqualUnicodeString(&TransportName, &NetbiosSmb, TRUE )) {
  1028. try_return(Status = STATUS_SUCCESS);
  1029. }
  1030. }
  1031. //
  1032. // Get & verify emulated domain name
  1033. //
  1034. EmulatedDomainName = InputBuffer->EmulatedDomainName;
  1035. ENSURE_IN_INPUT_BUFFER( &EmulatedDomainName, FALSE, FALSE );
  1036. //
  1037. // Get the emulated computer name from the input buffer.
  1038. // (Callers that don't want us to do the add names don't pass the computername)
  1039. //
  1040. if ( InputBuffer->Level ) {
  1041. ENSURE_IN_INPUT_BUFFER_STR( (LPWSTR)((PCHAR)TransportName.Buffer+TransportName.Length) );
  1042. RtlInitUnicodeString( &EmulatedComputerName,
  1043. (LPWSTR)((PCHAR)TransportName.Buffer+TransportName.Length) );
  1044. } else {
  1045. RtlInitUnicodeString( &EmulatedComputerName, NULL );
  1046. }
  1047. //
  1048. // Fail if either EmulatedDomainName or EmulatedComputerName is missing.
  1049. //
  1050. if ( EmulatedDomainName.Length == 0 || EmulatedComputerName.Length == 0 ) {
  1051. try_return(Status = STATUS_INVALID_COMPUTER_NAME);
  1052. }
  1053. dlog(DPRT_FSCTL,
  1054. ("%wZ: %wZ: %wZ: NtDeviceIoControlFile: Bind to transport\n",
  1055. &EmulatedDomainName,
  1056. &EmulatedComputerName,
  1057. &TransportName ));
  1058. Status = BowserTdiAllocateTransport( &TransportName,
  1059. &EmulatedDomainName,
  1060. &EmulatedComputerName );
  1061. try_return(Status);
  1062. try_exit:NOTHING;
  1063. } finally {
  1064. if (ProcessAttached) {
  1065. KeUnstackDetachProcess( &ApcState );
  1066. }
  1067. }
  1068. return Status;
  1069. UNREFERENCED_PARAMETER(Wait);
  1070. UNREFERENCED_PARAMETER(InputBufferLength);
  1071. }
  1072. NTSTATUS
  1073. UnbindFromTransport (
  1074. IN BOOLEAN Wait,
  1075. IN BOOLEAN InFsd,
  1076. IN PLMDR_REQUEST_PACKET InputBuffer,
  1077. IN ULONG InputBufferLength
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. This routine adds a reference to a file object created with .
  1082. Arguments:
  1083. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1084. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1085. Return Value:
  1086. NTSTATUS
  1087. --*/
  1088. {
  1089. NTSTATUS Status;
  1090. UNICODE_STRING TransportName;
  1091. BOOLEAN ProcessAttached = FALSE;
  1092. KAPC_STATE ApcState;
  1093. PAGED_CODE();
  1094. if (IoGetCurrentProcess() != BowserFspProcess) {
  1095. KeStackAttachProcess(BowserFspProcess, &ApcState );
  1096. ProcessAttached = TRUE;
  1097. }
  1098. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Unbind from transport\n"));
  1099. try {
  1100. //
  1101. // Check some fields in the input buffer.
  1102. //
  1103. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.Unbind.TransportName)) {
  1104. try_return(Status = STATUS_INVALID_PARAMETER);
  1105. }
  1106. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1107. try_return(Status = STATUS_INVALID_PARAMETER);
  1108. }
  1109. //
  1110. // Capture transport name.
  1111. //
  1112. TransportName.MaximumLength = TransportName.Length = (USHORT )
  1113. InputBuffer->Parameters.Unbind.TransportNameLength;
  1114. TransportName.Buffer = InputBuffer->Parameters.Unbind.TransportName;
  1115. ENSURE_IN_INPUT_BUFFER( &TransportName, FALSE, FALSE );
  1116. dlog(DPRT_FSCTL, ("\"%wZ\"", &TransportName));
  1117. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  1118. Status = BowserFreeTransportByName(&TransportName, &InputBuffer->EmulatedDomainName );
  1119. try_return(Status);
  1120. try_exit:NOTHING;
  1121. } finally {
  1122. if (ProcessAttached) {
  1123. KeUnstackDetachProcess( &ApcState );
  1124. }
  1125. }
  1126. return Status;
  1127. UNREFERENCED_PARAMETER(Wait);
  1128. UNREFERENCED_PARAMETER(InputBufferLength);
  1129. }
  1130. NTSTATUS
  1131. BowserEnumTransports (
  1132. IN BOOLEAN Wait,
  1133. IN BOOLEAN InFsd,
  1134. IN PLMDR_REQUEST_PACKET InputBuffer,
  1135. IN PULONG InputBufferLength,
  1136. OUT PVOID OutputBuffer,
  1137. IN OUT ULONG OutputBufferLength,
  1138. IN ULONG_PTR OutputBufferDisplacement
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. This routine enumerates the transports bound into the bowser.
  1143. Arguments:
  1144. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1145. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1146. IN PLMDR_REQUEST_PACKET InputBuffer,
  1147. IN ULONG InputBufferLength,
  1148. OUT PVOID OutputBuffer,
  1149. IN OUT PULONG OutputBufferLength
  1150. Return Value:
  1151. NTSTATUS - Status of operation.
  1152. --*/
  1153. {
  1154. NTSTATUS Status;
  1155. PAGED_CODE();
  1156. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: EnumerateTransports\n"));
  1157. //
  1158. // Check some fields in the input buffer.
  1159. //
  1160. if (*InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1161. Status = STATUS_INVALID_PARAMETER;
  1162. goto ReturnStatus;
  1163. }
  1164. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1165. Status = STATUS_INVALID_PARAMETER;
  1166. goto ReturnStatus;
  1167. }
  1168. if (InputBuffer->Type != EnumerateXports) {
  1169. Status = STATUS_INVALID_PARAMETER;
  1170. goto ReturnStatus;
  1171. }
  1172. if (OutputBufferLength < sizeof(LMDR_TRANSPORT_LIST)) {
  1173. Status = STATUS_BUFFER_TOO_SMALL;
  1174. goto ReturnStatus;
  1175. }
  1176. Status = BowserEnumerateTransports(OutputBuffer,
  1177. OutputBufferLength,
  1178. &InputBuffer->Parameters.EnumerateTransports.EntriesRead,
  1179. &InputBuffer->Parameters.EnumerateTransports.TotalEntries,
  1180. &InputBuffer->Parameters.EnumerateTransports.TotalBytesNeeded,
  1181. OutputBufferDisplacement);
  1182. *InputBufferLength = sizeof(LMDR_REQUEST_PACKET);
  1183. ReturnStatus:
  1184. return Status;
  1185. UNREFERENCED_PARAMETER(Wait);
  1186. UNREFERENCED_PARAMETER(InFsd);
  1187. }
  1188. NTSTATUS
  1189. EnumNames (
  1190. IN BOOLEAN Wait,
  1191. IN BOOLEAN InFsd,
  1192. IN PLMDR_REQUEST_PACKET InputBuffer,
  1193. IN PULONG RetInputBufferLength,
  1194. OUT PVOID OutputBuffer,
  1195. IN OUT ULONG OutputBufferLength,
  1196. IN ULONG_PTR OutputBufferDisplacement
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. This routine enumerates the names bound into the bowser.
  1201. Arguments:
  1202. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1203. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1204. IN PLMDR_REQUEST_PACKET InputBuffer,
  1205. IN ULONG InputBufferLength,
  1206. OUT PVOID OutputBuffer,
  1207. IN OUT PULONG OutputBufferLength
  1208. Return Value:
  1209. NTSTATUS - Status of operation.
  1210. --*/
  1211. {
  1212. NTSTATUS Status;
  1213. PDOMAIN_INFO DomainInfo = NULL;
  1214. PTRANSPORT Transport = NULL;
  1215. ULONG InputBufferLength = *RetInputBufferLength;
  1216. PAGED_CODE();
  1217. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: EnumerateNames\n"));
  1218. try {
  1219. //
  1220. // Check some fields in the input buffer.
  1221. //
  1222. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1223. try_return (Status = STATUS_INVALID_PARAMETER);
  1224. }
  1225. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1226. try_return (Status = STATUS_INVALID_PARAMETER);
  1227. }
  1228. if (InputBuffer->Type != EnumerateNames) {
  1229. try_return (Status = STATUS_INVALID_PARAMETER);
  1230. }
  1231. if (OutputBufferLength < sizeof(DGRECEIVE_NAMES)) {
  1232. try_return (Status = STATUS_BUFFER_TOO_SMALL);
  1233. }
  1234. //
  1235. // Find the emulated domain the names are to be enumerated for
  1236. //
  1237. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  1238. DomainInfo = BowserFindDomain( &InputBuffer->EmulatedDomainName );
  1239. if ( DomainInfo == NULL ) {
  1240. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1241. }
  1242. //
  1243. // If we want to limit our search to a particular transport,
  1244. // lookup that transport.
  1245. //
  1246. if ( InputBuffer->TransportName.Length != 0 ) {
  1247. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, FALSE );
  1248. Transport = BowserFindTransport ( &InputBuffer->TransportName,
  1249. &InputBuffer->EmulatedDomainName );
  1250. dprintf(DPRT_REF, ("Called Find transport %lx from EnumNames.\n", Transport));
  1251. if ( Transport == NULL ) {
  1252. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1253. }
  1254. }
  1255. Status = BowserEnumerateNamesInDomain(
  1256. DomainInfo,
  1257. Transport,
  1258. OutputBuffer,
  1259. OutputBufferLength,
  1260. &InputBuffer->Parameters.EnumerateTransports.EntriesRead,
  1261. &InputBuffer->Parameters.EnumerateTransports.TotalEntries,
  1262. &InputBuffer->Parameters.EnumerateTransports.TotalBytesNeeded,
  1263. OutputBufferDisplacement);
  1264. *RetInputBufferLength = sizeof(LMDR_REQUEST_PACKET);
  1265. try_exit:NOTHING;
  1266. } finally {
  1267. if ( DomainInfo != NULL ) {
  1268. BowserDereferenceDomain( DomainInfo );
  1269. }
  1270. if ( Transport != NULL ) {
  1271. BowserDereferenceTransport( Transport );
  1272. }
  1273. }
  1274. return Status;
  1275. UNREFERENCED_PARAMETER(Wait);
  1276. UNREFERENCED_PARAMETER(InFsd);
  1277. }
  1278. NTSTATUS
  1279. DeleteName (
  1280. IN BOOLEAN Wait,
  1281. IN BOOLEAN InFsd,
  1282. IN PLMDR_REQUEST_PACKET InputBuffer,
  1283. IN ULONG InputBufferLength
  1284. )
  1285. /*++
  1286. Routine Description:
  1287. This routine adds a reference to a file object created with .
  1288. Arguments:
  1289. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1290. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1291. Return Value:
  1292. NTSTATUS
  1293. --*/
  1294. {
  1295. NTSTATUS Status;
  1296. UNICODE_STRING Name;
  1297. PDOMAIN_INFO DomainInfo = NULL;
  1298. BOOLEAN ProcessAttached = FALSE;
  1299. KAPC_STATE ApcState;
  1300. PAGED_CODE();
  1301. if (IoGetCurrentProcess() != BowserFspProcess) {
  1302. KeStackAttachProcess(BowserFspProcess, &ApcState );
  1303. ProcessAttached = TRUE;
  1304. }
  1305. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Delete Name\n"));
  1306. try {
  1307. //
  1308. // Check some fields in the input buffer.
  1309. //
  1310. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.AddDelName.Name)) {
  1311. try_return(Status = STATUS_INVALID_PARAMETER);
  1312. }
  1313. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1314. try_return(Status = STATUS_INVALID_PARAMETER);
  1315. }
  1316. // NULL name means to delete all names of that name type.
  1317. Name.MaximumLength = Name.Length = (USHORT )
  1318. InputBuffer->Parameters.AddDelName.DgReceiverNameLength;
  1319. Name.Buffer = InputBuffer->Parameters.AddDelName.Name;
  1320. ENSURE_IN_INPUT_BUFFER( &Name, TRUE, FALSE );
  1321. //
  1322. // Find the emulated domain the name is to be deleted for
  1323. //
  1324. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  1325. DomainInfo = BowserFindDomain( &InputBuffer->EmulatedDomainName );
  1326. if ( DomainInfo == NULL ) {
  1327. try_return(Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1328. }
  1329. dlog(DPRT_FSCTL, ("Deleting \"%wZ\"", &Name));
  1330. Status = BowserDeleteNameByName(DomainInfo, &Name, InputBuffer->Parameters.AddDelName.Type);
  1331. try_return(Status);
  1332. try_exit:NOTHING;
  1333. } finally {
  1334. if ( DomainInfo != NULL ) {
  1335. BowserDereferenceDomain( DomainInfo );
  1336. }
  1337. if (ProcessAttached) {
  1338. KeUnstackDetachProcess( &ApcState );
  1339. }
  1340. }
  1341. return Status;
  1342. UNREFERENCED_PARAMETER(Wait);
  1343. UNREFERENCED_PARAMETER(InputBufferLength);
  1344. }
  1345. NTSTATUS
  1346. EnumServers (
  1347. IN BOOLEAN Wait,
  1348. IN BOOLEAN InFsd,
  1349. IN PLMDR_REQUEST_PACKET InputBuffer,
  1350. IN PULONG RetInputBufferLength,
  1351. OUT PVOID OutputBuffer,
  1352. IN OUT ULONG OutputBufferLength,
  1353. IN ULONG_PTR OutputBufferDisplacement
  1354. )
  1355. /*++
  1356. Routine Description:
  1357. This routine adds a reference to a file object created with .
  1358. Arguments:
  1359. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1360. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1361. IN PLMDR_REQUEST_PACKET InputBuffer,
  1362. IN ULONG InputBufferLength,
  1363. OUT PVOID OutputBuffer,
  1364. IN OUT PULONG OutputBufferLength
  1365. Return Value:
  1366. NTSTATUS - Status of operation.
  1367. --*/
  1368. {
  1369. NTSTATUS Status;
  1370. UNICODE_STRING DomainName;
  1371. ULONG InputBufferLength = *RetInputBufferLength;
  1372. PAGED_CODE();
  1373. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: EnumerateServers\n"));
  1374. //
  1375. // Check some fields in the input buffer.
  1376. //
  1377. try {
  1378. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1379. try_return (Status = STATUS_INVALID_PARAMETER);
  1380. }
  1381. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1382. try_return (Status = STATUS_INVALID_PARAMETER);
  1383. }
  1384. if (InputBuffer->Type != EnumerateServers) {
  1385. try_return (Status = STATUS_INVALID_PARAMETER);
  1386. }
  1387. if (InputBuffer->Level != 100 && InputBuffer->Level != 101) {
  1388. try_return (Status = STATUS_INVALID_LEVEL);
  1389. }
  1390. if (OutputBufferLength < sizeof(SERVER_INFO_100)) {
  1391. try_return (Status = STATUS_BUFFER_TOO_SMALL);
  1392. }
  1393. if (InputBuffer->Level == 101 && OutputBufferLength < sizeof(SERVER_INFO_101)) {
  1394. try_return (Status = STATUS_BUFFER_TOO_SMALL);
  1395. }
  1396. if (InputBuffer->Parameters.EnumerateServers.DomainNameLength != 0) {
  1397. DomainName.Buffer = InputBuffer->Parameters.EnumerateServers.DomainName;
  1398. DomainName.Length = DomainName.MaximumLength =
  1399. (USHORT )InputBuffer->Parameters.EnumerateServers.DomainNameLength;
  1400. ENSURE_IN_INPUT_BUFFER( &DomainName, FALSE, FALSE );
  1401. }
  1402. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, FALSE, FALSE );
  1403. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, TRUE, FALSE );
  1404. Status = BowserEnumerateServers( InputBuffer->Level, &InputBuffer->LogonId,
  1405. &InputBuffer->Parameters.EnumerateServers.ResumeHandle,
  1406. InputBuffer->Parameters.EnumerateServers.ServerType,
  1407. (InputBuffer->TransportName.Length != 0 ? &InputBuffer->TransportName : NULL),
  1408. &InputBuffer->EmulatedDomainName,
  1409. (InputBuffer->Parameters.EnumerateServers.DomainNameLength != 0 ? &DomainName : NULL),
  1410. OutputBuffer,
  1411. OutputBufferLength,
  1412. &InputBuffer->Parameters.EnumerateServers.EntriesRead,
  1413. &InputBuffer->Parameters.EnumerateServers.TotalEntries,
  1414. &InputBuffer->Parameters.EnumerateServers.TotalBytesNeeded,
  1415. OutputBufferDisplacement);
  1416. *RetInputBufferLength = sizeof(LMDR_REQUEST_PACKET);
  1417. try_exit:NOTHING;
  1418. } finally {
  1419. }
  1420. return Status;
  1421. UNREFERENCED_PARAMETER(Wait);
  1422. UNREFERENCED_PARAMETER(InFsd);
  1423. }
  1424. NTSTATUS
  1425. AddBowserName (
  1426. IN BOOLEAN Wait,
  1427. IN BOOLEAN InFsd,
  1428. IN PLMDR_REQUEST_PACKET InputBuffer,
  1429. IN ULONG InputBufferLength
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. This routine adds a reference to a file object created with .
  1434. Arguments:
  1435. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1436. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1437. Return Value:
  1438. NTSTATUS
  1439. --*/
  1440. {
  1441. NTSTATUS Status;
  1442. UNICODE_STRING Name;
  1443. PTRANSPORT Transport = NULL;
  1444. PDOMAIN_INFO DomainInfo = NULL;
  1445. BOOLEAN ProcessAttached = FALSE;
  1446. KAPC_STATE ApcState;
  1447. PAGED_CODE();
  1448. if (IoGetCurrentProcess() != BowserFspProcess) {
  1449. KeStackAttachProcess(BowserFspProcess, &ApcState );
  1450. ProcessAttached = TRUE;
  1451. }
  1452. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Bind to transport\n"));
  1453. try {
  1454. //
  1455. // Check some fields in the input buffer.
  1456. //
  1457. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.AddDelName.Name)) {
  1458. try_return(Status = STATUS_INVALID_PARAMETER);
  1459. }
  1460. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1461. try_return(Status = STATUS_INVALID_PARAMETER);
  1462. }
  1463. Name.MaximumLength = Name.Length = (USHORT )
  1464. InputBuffer->Parameters.AddDelName.DgReceiverNameLength;
  1465. Name.Buffer = InputBuffer->Parameters.AddDelName.Name;
  1466. ENSURE_IN_INPUT_BUFFER( &Name, FALSE, FALSE );
  1467. dlog(DPRT_FSCTL, ("\"%wZ\"", &Name));
  1468. //
  1469. // If the transport was specified,
  1470. // just add the name on that transport.
  1471. //
  1472. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  1473. if (InputBuffer->TransportName.Length != 0) {
  1474. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, FALSE );
  1475. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  1476. dprintf(DPRT_REF, ("Called Find transport %lx from AddBowserName.\n", Transport));
  1477. if (Transport == NULL) {
  1478. try_return(Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1479. }
  1480. //
  1481. // If the transport wasn't specified,
  1482. // just add the name on the specified domain.
  1483. //
  1484. // It doesn't make sense to add the name on ALL transports. Either the domain name
  1485. // or the transport name must be specified.
  1486. //
  1487. } else {
  1488. DomainInfo = BowserFindDomain( &InputBuffer->EmulatedDomainName );
  1489. if ( DomainInfo == NULL ) {
  1490. try_return(Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1491. }
  1492. }
  1493. Status = BowserAllocateName(&Name,
  1494. InputBuffer->Parameters.AddDelName.Type,
  1495. Transport,
  1496. DomainInfo );
  1497. try_return(Status);
  1498. try_exit:NOTHING;
  1499. } finally {
  1500. if (Transport != NULL) {
  1501. BowserDereferenceTransport(Transport);
  1502. }
  1503. if ( DomainInfo != NULL ) {
  1504. BowserDereferenceDomain( DomainInfo );
  1505. }
  1506. if (ProcessAttached) {
  1507. KeUnstackDetachProcess( &ApcState );
  1508. }
  1509. }
  1510. return Status;
  1511. UNREFERENCED_PARAMETER(Wait);
  1512. UNREFERENCED_PARAMETER(InputBufferLength);
  1513. }
  1514. NTSTATUS
  1515. GetBrowserServerList(
  1516. IN PIRP Irp,
  1517. IN BOOLEAN Wait,
  1518. IN BOOLEAN InFsd,
  1519. IN PLMDR_REQUEST_PACKET InputBuffer,
  1520. IN OUT PULONG RetInputBufferLength,
  1521. IN PVOID OutputBuffer,
  1522. IN ULONG OutputBufferLength,
  1523. IN ULONG_PTR OutputBufferDisplacement
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. This routine will return the list of browser servers for the specified
  1528. net on the specified domain.
  1529. Arguments:
  1530. IN BOOLEAN Wait, - True IFF redirector can block callers thread on request
  1531. IN BOOLEAN InFsd, - True IFF this request is initiated from the FSD.
  1532. IN PLMDR_REQUEST_PACKET InputBuffer,
  1533. IN ULONG InputBufferLength,
  1534. OUT PVOID OutputBuffer,
  1535. IN OUT PULONG OutputBufferLength
  1536. Return Value:
  1537. NTSTATUS - Status of operation.
  1538. --*/
  1539. {
  1540. NTSTATUS Status;
  1541. UNICODE_STRING DomainName;
  1542. PTRANSPORT Transport = NULL;
  1543. ULONG BrowserServerListLength;
  1544. PWSTR *BrowserServerList;
  1545. BOOLEAN IsPrimaryDomain = FALSE;
  1546. BOOLEAN TransportBrowserListAcquired = FALSE;
  1547. PVOID OutputBufferEnd = (PCHAR)OutputBuffer + OutputBufferLength;
  1548. PPAGED_TRANSPORT PagedTransport;
  1549. ULONG InputBufferLength = *RetInputBufferLength;
  1550. BOOLEAN fThunk32bit;
  1551. PAGED_CODE();
  1552. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: GetBrowserServerList\n"));
  1553. try {
  1554. //
  1555. // Check some fields in the input buffer.
  1556. //
  1557. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1558. try_return(Status = STATUS_INVALID_PARAMETER);
  1559. }
  1560. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1561. try_return(Status = STATUS_INVALID_PARAMETER);
  1562. }
  1563. if (InputBuffer->TransportName.Length == 0 ||
  1564. InputBuffer->TransportName.Buffer == NULL) {
  1565. try_return(Status = STATUS_INVALID_PARAMETER);
  1566. }
  1567. #ifdef _WIN64
  1568. fThunk32bit = IoIs32bitProcess(Irp);
  1569. #else
  1570. // If we're in 32 bit (e.g. call above isn't available), use unchanged functionality
  1571. // i.e. pure new-64-bit == pure old-32-bit == homogeneous environment. Thus, set to FALSE.
  1572. fThunk32bit = FALSE;
  1573. #endif
  1574. if (InputBuffer->Parameters.GetBrowserServerList.DomainNameLength != 0) {
  1575. DomainName.Buffer = InputBuffer->Parameters.GetBrowserServerList.DomainName;
  1576. DomainName.Length = DomainName.MaximumLength =
  1577. (USHORT)InputBuffer->Parameters.GetBrowserServerList.DomainNameLength;
  1578. ENSURE_IN_INPUT_BUFFER( &DomainName, FALSE, fThunk32bit );
  1579. } else {
  1580. DomainName.Length = 0;
  1581. DomainName.Buffer = NULL;
  1582. }
  1583. //
  1584. // See if the specified domain is an emulated domain.
  1585. //
  1586. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, fThunk32bit );
  1587. Transport = BowserFindTransport(&InputBuffer->TransportName, &DomainName );
  1588. dprintf(DPRT_REF, ("Called Find transport %lx from GetBrowserServerList.\n", Transport));
  1589. if (Transport == NULL) {
  1590. //
  1591. // Otherwise simply use the primary domain transport
  1592. //
  1593. Transport = BowserFindTransport(&InputBuffer->TransportName, NULL );
  1594. dprintf(DPRT_REF, ("Called Find transport %lx from GetBrowserServerList (2).\n", Transport));
  1595. if ( Transport == NULL ) {
  1596. try_return(Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1597. }
  1598. }
  1599. PagedTransport = Transport->PagedTransport;
  1600. if (!ExAcquireResourceSharedLite(&Transport->BrowserServerListResource, Wait)) {
  1601. try_return(Status = STATUS_PENDING);
  1602. }
  1603. TransportBrowserListAcquired = TRUE;
  1604. //
  1605. // If this request is for the primary domain and there are no entries
  1606. // in the cached list, or if it is not for the primary domain, or
  1607. // if we are supposed to force a rescan of the list, get the list
  1608. // from the master for that domain..
  1609. //
  1610. if ((DomainName.Length == 0) ||
  1611. RtlEqualUnicodeString(&DomainName, &Transport->DomainInfo->DomUnicodeDomainName, TRUE)) {
  1612. IsPrimaryDomain = TRUE;
  1613. BrowserServerList = PagedTransport->BrowserServerListBuffer;
  1614. BrowserServerListLength = PagedTransport->BrowserServerListLength;
  1615. }
  1616. if ((IsPrimaryDomain &&
  1617. (BrowserServerListLength == 0))
  1618. ||
  1619. !IsPrimaryDomain
  1620. ||
  1621. (InputBuffer->Parameters.GetBrowserServerList.ForceRescan)) {
  1622. //
  1623. // We need to re-gather the transport list.
  1624. // Re-acquire the BrowserServerList resource for exclusive access.
  1625. //
  1626. ExReleaseResourceLite(&Transport->BrowserServerListResource);
  1627. TransportBrowserListAcquired = FALSE;
  1628. if (!ExAcquireResourceExclusiveLite(&Transport->BrowserServerListResource, Wait)) {
  1629. try_return(Status = STATUS_PENDING);
  1630. }
  1631. TransportBrowserListAcquired = TRUE;
  1632. //
  1633. // If we are being asked to rescan the list, free it up.
  1634. //
  1635. if (InputBuffer->Parameters.GetBrowserServerList.ForceRescan &&
  1636. PagedTransport->BrowserServerListBuffer != NULL) {
  1637. BowserFreeBrowserServerList(PagedTransport->BrowserServerListBuffer,
  1638. PagedTransport->BrowserServerListLength);
  1639. PagedTransport->BrowserServerListLength = 0;
  1640. PagedTransport->BrowserServerListBuffer = NULL;
  1641. }
  1642. //
  1643. // If there are still no servers in the list, get the list.
  1644. //
  1645. Status = BowserGetBrowserServerList(Irp,
  1646. Transport,
  1647. (DomainName.Length == 0 ?
  1648. NULL :
  1649. &DomainName),
  1650. &BrowserServerList,
  1651. &BrowserServerListLength);
  1652. if (!NT_SUCCESS(Status)) {
  1653. try_return(Status);
  1654. }
  1655. if (IsPrimaryDomain) {
  1656. //
  1657. // Save away the list of servers retreived in the transport.
  1658. //
  1659. if (PagedTransport->BrowserServerListBuffer != NULL) {
  1660. BowserFreeBrowserServerList(
  1661. PagedTransport->BrowserServerListBuffer,
  1662. PagedTransport->BrowserServerListLength);
  1663. }
  1664. PagedTransport->BrowserServerListBuffer = BrowserServerList;
  1665. PagedTransport->BrowserServerListLength = BrowserServerListLength;
  1666. }
  1667. }
  1668. //
  1669. // If there any servers in the browser server list, we want to
  1670. // pick the first 3 of them and return them to the caller.
  1671. //
  1672. if (BrowserServerListLength != 0) {
  1673. ULONG i;
  1674. PWSTR *ServerList = OutputBuffer;
  1675. BOOLEAN BufferRemaining = TRUE;
  1676. InputBuffer->Parameters.GetBrowserServerList.TotalEntries = 0;
  1677. InputBuffer->Parameters.GetBrowserServerList.EntriesRead = 0;
  1678. InputBuffer->Parameters.GetBrowserServerList.TotalBytesNeeded = 0;
  1679. //
  1680. // Now pick the first 3 entries from the list to return.
  1681. //
  1682. for ( i = 0 ; i < min(3, BrowserServerListLength) ; i ++ ) {
  1683. PWSTR Temp;
  1684. InputBuffer->Parameters.GetBrowserServerList.TotalEntries += 1;
  1685. InputBuffer->Parameters.GetBrowserServerList.TotalBytesNeeded += wcslen(BrowserServerList[i])*sizeof(WCHAR);
  1686. Temp = BrowserServerList[i];
  1687. dlog(DPRT_CLIENT, ("Packing server name %ws into buffer...", Temp));
  1688. //
  1689. // Pack the entry into the users buffer.
  1690. //
  1691. if (BufferRemaining &&
  1692. BowserPackUnicodeString(&Temp,
  1693. wcslen(Temp)*sizeof(WCHAR),
  1694. OutputBufferDisplacement,
  1695. &ServerList[i+1],
  1696. &OutputBufferEnd) != 0) {
  1697. ServerList[i] = Temp;
  1698. InputBuffer->Parameters.GetBrowserServerList.EntriesRead += 1;
  1699. } else {
  1700. BufferRemaining = FALSE;
  1701. }
  1702. }
  1703. }
  1704. //
  1705. // Set the number of bytes to copy on return.
  1706. //
  1707. *RetInputBufferLength = sizeof(LMDR_REQUEST_PACKET);
  1708. try_return(Status = STATUS_SUCCESS);
  1709. try_exit:NOTHING;
  1710. } finally {
  1711. if (Transport != NULL) {
  1712. if (TransportBrowserListAcquired) {
  1713. ExReleaseResourceLite(&Transport->BrowserServerListResource);
  1714. }
  1715. BowserDereferenceTransport(Transport);
  1716. }
  1717. if (NT_SUCCESS(Status) && !IsPrimaryDomain) {
  1718. BowserFreeBrowserServerList(BrowserServerList,
  1719. BrowserServerListLength);
  1720. }
  1721. }
  1722. return(Status);
  1723. UNREFERENCED_PARAMETER(Irp);
  1724. UNREFERENCED_PARAMETER(InFsd);
  1725. }
  1726. NTSTATUS
  1727. HandleBecomeBackup (
  1728. IN PIRP Irp,
  1729. IN PLMDR_REQUEST_PACKET InputBuffer,
  1730. IN ULONG InputBufferLength
  1731. )
  1732. /*++
  1733. Routine Description:
  1734. This routine will queue a request that will complete when a request
  1735. to make the workstation become a backup browser is received.
  1736. Arguments:
  1737. IN PIRP Irp - I/O request packet describing request.
  1738. Return Value:
  1739. Status of operation.
  1740. Please note that this IRP is cancelable.
  1741. --*/
  1742. {
  1743. NTSTATUS Status;
  1744. PTRANSPORT Transport = NULL;
  1745. PAGED_CODE();
  1746. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: %wZ: Get Announce Request\n", &InputBuffer->TransportName ));
  1747. try {
  1748. WCHAR TransportNameBuffer[MAX_PATH+1];
  1749. WCHAR DomainNameBuffer[DNLEN+1];
  1750. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1751. try_return(Status = STATUS_INVALID_PARAMETER);
  1752. }
  1753. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  1754. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  1755. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  1756. dprintf(DPRT_REF, ("Called Find transport %lx from HandleBecomeBackup.\n", Transport));
  1757. if (Transport == NULL) {
  1758. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1759. }
  1760. Status = BowserQueueNonBufferRequest(Irp,
  1761. &Transport->BecomeBackupQueue,
  1762. BowserCancelQueuedRequest
  1763. );
  1764. try_exit:NOTHING;
  1765. } finally {
  1766. if ( Transport != NULL ) {
  1767. BowserDereferenceTransport(Transport);
  1768. }
  1769. }
  1770. return Status;
  1771. }
  1772. NTSTATUS
  1773. BecomeMaster (
  1774. IN PIRP Irp,
  1775. IN PLMDR_REQUEST_PACKET InputBuffer,
  1776. IN ULONG InputBufferLength
  1777. )
  1778. /*++
  1779. Routine Description:
  1780. This routine will queue a request that will complete when the workstation
  1781. becomes a master browser server.
  1782. Arguments:
  1783. IN PIRP Irp - I/O request packet describing request.
  1784. Return Value:
  1785. Status of operation.
  1786. Please note that this IRP is cancelable.
  1787. --*/
  1788. {
  1789. NTSTATUS Status;
  1790. PTRANSPORT Transport = NULL;
  1791. PAGED_CODE();
  1792. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: BecomeMaster\n"));
  1793. try {
  1794. WCHAR TransportNameBuffer[MAX_PATH+1];
  1795. WCHAR DomainNameBuffer[DNLEN+1];
  1796. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1797. try_return(Status = STATUS_INVALID_PARAMETER);
  1798. }
  1799. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  1800. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  1801. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  1802. dprintf(DPRT_REF, ("Called Find transport %lx from BecomeMaster.\n", Transport));
  1803. if (Transport == NULL) {
  1804. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1805. }
  1806. LOCK_TRANSPORT (Transport);
  1807. if (Transport->ElectionState == DeafToElections) {
  1808. Transport->ElectionState = Idle;
  1809. }
  1810. UNLOCK_TRANSPORT (Transport);
  1811. Status = BowserQueueNonBufferRequest(Irp,
  1812. &Transport->BecomeMasterQueue,
  1813. BowserCancelQueuedRequest
  1814. );
  1815. try_exit:NOTHING;
  1816. } finally {
  1817. if ( Transport != NULL ) {
  1818. BowserDereferenceTransport(Transport);
  1819. }
  1820. }
  1821. return Status;
  1822. }
  1823. NTSTATUS
  1824. WaitForMasterAnnounce (
  1825. IN PIRP Irp,
  1826. IN PLMDR_REQUEST_PACKET InputBuffer,
  1827. IN ULONG InputBufferLength
  1828. )
  1829. /*++
  1830. Routine Description:
  1831. This routine will queue a request that will complete when the workstation
  1832. becomes a master browser server.
  1833. Arguments:
  1834. IN PIRP Irp - I/O request packet describing request.
  1835. Return Value:
  1836. Status of operation.
  1837. Please note that this IRP is cancelable.
  1838. --*/
  1839. {
  1840. NTSTATUS Status;
  1841. PTRANSPORT Transport = NULL;
  1842. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  1843. PAGED_CODE();
  1844. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: WaitForMasterAnnounce\n"));
  1845. try {
  1846. WCHAR TransportNameBuffer[MAX_PATH+1];
  1847. WCHAR DomainNameBuffer[DNLEN+1];
  1848. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1849. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.WaitForMasterAnnouncement.Name)) {
  1850. try_return(Status = STATUS_INVALID_PARAMETER);
  1851. }
  1852. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  1853. try_return(Status = STATUS_INVALID_PARAMETER);
  1854. }
  1855. if ( (InputBuffer->TransportName.Length & 1) != 0 ) {
  1856. // invalid unicode string. bug 55448.
  1857. try_return(Status = STATUS_INVALID_PARAMETER);
  1858. }
  1859. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  1860. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  1861. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  1862. dprintf(DPRT_REF, ("Called Find transport %lx from WaitForMasterAnnounce.\n", Transport));
  1863. if (Transport == NULL) {
  1864. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1865. }
  1866. Status = BowserQueueNonBufferRequest(Irp,
  1867. &Transport->WaitForMasterAnnounceQueue,
  1868. BowserCancelQueuedRequest
  1869. );
  1870. try_exit:NOTHING;
  1871. } finally {
  1872. if ( Transport != NULL ) {
  1873. BowserDereferenceTransport(Transport);
  1874. }
  1875. }
  1876. return Status;
  1877. }
  1878. NTSTATUS
  1879. UpdateStatus(
  1880. IN PIRP Irp,
  1881. IN BOOLEAN InFsd,
  1882. IN PLMDR_REQUEST_PACKET InputBuffer,
  1883. IN ULONG InputBufferLength
  1884. )
  1885. {
  1886. NTSTATUS Status = STATUS_SUCCESS;
  1887. PTRANSPORT Transport = NULL;
  1888. ULONG NewStatus;
  1889. BOOLEAN TransportLocked = FALSE;
  1890. PPAGED_TRANSPORT PagedTransport;
  1891. BOOLEAN ProcessAttached = FALSE;
  1892. KAPC_STATE ApcState;
  1893. PAGED_CODE();
  1894. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: Update status\n"));
  1895. if (IoGetCurrentProcess() != BowserFspProcess) {
  1896. KeStackAttachProcess(BowserFspProcess, &ApcState );
  1897. ProcessAttached = TRUE;
  1898. }
  1899. try {
  1900. if (InputBufferLength <
  1901. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters)+sizeof(InputBuffer->Parameters.UpdateStatus)) {
  1902. try_return(Status = STATUS_INVALID_PARAMETER);
  1903. }
  1904. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  1905. try_return (Status = STATUS_INVALID_PARAMETER);
  1906. }
  1907. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, FALSE );
  1908. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  1909. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  1910. dprintf(DPRT_REF, ("Called Find transport %lx from UpdateStatus.\n", Transport));
  1911. if (Transport == NULL) {
  1912. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  1913. }
  1914. PagedTransport = Transport->PagedTransport;
  1915. NewStatus = InputBuffer->Parameters.UpdateStatus.NewStatus;
  1916. BowserData.MaintainServerList = InputBuffer->Parameters.UpdateStatus.MaintainServerList;
  1917. BowserData.IsLanmanNt = InputBuffer->Parameters.UpdateStatus.IsLanmanNt;
  1918. #ifdef ENABLE_PSEUDO_BROWSER
  1919. BowserData.PseudoServerLevel = (DWORD)InputBuffer->Parameters.UpdateStatus.PseudoServerLevel;
  1920. #endif
  1921. LOCK_TRANSPORT(Transport);
  1922. TransportLocked = TRUE;
  1923. //
  1924. // We are being called to update our state. There are several
  1925. // actions that should be performed on the state change:
  1926. //
  1927. // New Role | Previous Role
  1928. // | Potential Browser | Backup Browser | Master Browser
  1929. // ----------+--------------------+----------------+----------------
  1930. // | | |
  1931. // Potential | N/A | N/A | N/A
  1932. // | | |
  1933. // ----------+--------------------+----------------+----------------
  1934. // | | |
  1935. // Backup | Update role | N/A | N/A
  1936. // | | |
  1937. // ----------+--------------------+----------------+----------------
  1938. // | | |
  1939. // Master | Update role | Update role | N/A
  1940. // | | |
  1941. // ----------+--------------------+----------------+----------------
  1942. // | | |
  1943. // None | Remove elect | Remove elect | Remove all names
  1944. // | | |
  1945. // ----------+--------------------+----------------+----------------
  1946. //
  1947. dlog(DPRT_BROWSER,
  1948. ("%s: %ws: Update status to %lx\n",
  1949. Transport->DomainInfo->DomOemDomainName,
  1950. PagedTransport->TransportName.Buffer,
  1951. NewStatus));
  1952. PagedTransport->ServiceStatus = NewStatus;
  1953. //
  1954. // If the caller says we should have the 1E name registered,
  1955. // and we don't.
  1956. // Do so now.
  1957. //
  1958. if ( PagedTransport->Role == None &&
  1959. (NewStatus & SV_TYPE_POTENTIAL_BROWSER) != 0 ) {
  1960. dlog(DPRT_BROWSER,
  1961. ("%s: %ws: New status indicates we are a potential browser, but we're not\n",
  1962. Transport->DomainInfo->DomOemDomainName,
  1963. PagedTransport->TransportName.Buffer ));
  1964. PagedTransport->Role = PotentialBackup;
  1965. UNLOCK_TRANSPORT(Transport);
  1966. TransportLocked = FALSE;
  1967. Status = BowserAllocateName(
  1968. &Transport->DomainInfo->DomUnicodeDomainName,
  1969. BrowserElection,
  1970. Transport,
  1971. Transport->DomainInfo );
  1972. if (!NT_SUCCESS(Status)) {
  1973. try_return(Status);
  1974. }
  1975. LOCK_TRANSPORT(Transport);
  1976. TransportLocked = TRUE;
  1977. }
  1978. //
  1979. // If we are a master, then update appropriately.
  1980. //
  1981. if (PagedTransport->Role == Master) {
  1982. PagedTransport->NumberOfServersInTable = InputBuffer->Parameters.UpdateStatus.NumberOfServersInTable;
  1983. //
  1984. // If the new status doesn't indicate that we should be a master
  1985. // browser, flag it as such.
  1986. //
  1987. if (!(NewStatus & SV_TYPE_MASTER_BROWSER)) {
  1988. dlog(DPRT_BROWSER,
  1989. ("%s: %ws: New status indicates we are not a master browser\n",
  1990. Transport->DomainInfo->DomOemDomainName,
  1991. PagedTransport->TransportName.Buffer ));
  1992. //
  1993. // We must be a backup now, if we're not a master.
  1994. //
  1995. PagedTransport->Role = Backup;
  1996. //
  1997. // Stop processing announcements on this transport.
  1998. //
  1999. Status = BowserForEachTransportName(Transport, BowserStopProcessingAnnouncements, NULL);
  2000. UNLOCK_TRANSPORT(Transport);
  2001. TransportLocked = FALSE;
  2002. Status = BowserDeleteTransportNameByName(Transport, NULL, MasterBrowser);
  2003. if (!NT_SUCCESS(Status)) {
  2004. dlog(DPRT_BROWSER,
  2005. ("%s: %ws: Unable to remove master name: %X\n",
  2006. Transport->DomainInfo->DomOemDomainName,
  2007. PagedTransport->TransportName.Buffer,
  2008. Status));
  2009. }
  2010. Status = BowserDeleteTransportNameByName(Transport, NULL,
  2011. DomainAnnouncement);
  2012. if (!NT_SUCCESS(Status)) {
  2013. dlog(DPRT_BROWSER,
  2014. ("%s: %ws: Unable to delete domain announcement name: %X\n",
  2015. Transport->DomainInfo->DomOemDomainName,
  2016. PagedTransport->TransportName.Buffer,
  2017. Status));
  2018. }
  2019. if (!(NewStatus & SV_TYPE_BACKUP_BROWSER)) {
  2020. //
  2021. // We've stopped being a master browser, and we're not
  2022. // going to be a backup browser. We want to toss our
  2023. // cached browser server list just in case we're on the
  2024. // list.
  2025. //
  2026. ExAcquireResourceExclusiveLite(&Transport->BrowserServerListResource, TRUE);
  2027. if (PagedTransport->BrowserServerListBuffer != NULL) {
  2028. BowserFreeBrowserServerList(PagedTransport->BrowserServerListBuffer,
  2029. PagedTransport->BrowserServerListLength);
  2030. PagedTransport->BrowserServerListLength = 0;
  2031. PagedTransport->BrowserServerListBuffer = NULL;
  2032. }
  2033. ExReleaseResourceLite(&Transport->BrowserServerListResource);
  2034. }
  2035. LOCK_TRANSPORT(Transport);
  2036. TransportLocked = TRUE;
  2037. }
  2038. } else if (NewStatus & SV_TYPE_MASTER_BROWSER) {
  2039. dlog(DPRT_BROWSER | DPRT_MASTER,
  2040. ("%s: %ws: New status indicates we should be master, but we're not.\n",
  2041. Transport->DomainInfo->DomOemDomainName,
  2042. PagedTransport->TransportName.Buffer ));
  2043. UNLOCK_TRANSPORT(Transport);
  2044. TransportLocked = FALSE;
  2045. Status = BowserBecomeMaster (Transport);
  2046. LOCK_TRANSPORT(Transport);
  2047. dlog(DPRT_BROWSER | DPRT_MASTER,
  2048. ("%s: %ws: Master promotion status: %lX.\n",
  2049. Transport->DomainInfo->DomOemDomainName,
  2050. PagedTransport->TransportName.Buffer,
  2051. Status));
  2052. TransportLocked = TRUE;
  2053. ASSERT ((PagedTransport->Role == Master) || !NT_SUCCESS(Status));
  2054. }
  2055. if (!NT_SUCCESS(Status) || PagedTransport->Role == Master) {
  2056. try_return(Status);
  2057. }
  2058. //
  2059. // If we are a backup, then update appropriately.
  2060. //
  2061. if (PagedTransport->Role == Backup) {
  2062. if (!(NewStatus & SV_TYPE_BACKUP_BROWSER)) {
  2063. dlog(DPRT_BROWSER,
  2064. ("%s: %ws: New status indicates we are not a backup browser\n",
  2065. Transport->DomainInfo->DomOemDomainName,
  2066. PagedTransport->TransportName.Buffer ));
  2067. PagedTransport->Role = PotentialBackup;
  2068. //
  2069. // We've stopped being a browser. We want to toss our cached
  2070. // browser list in case we're on the list.
  2071. //
  2072. ExAcquireResourceExclusiveLite(&Transport->BrowserServerListResource, TRUE);
  2073. if (PagedTransport->BrowserServerListBuffer != NULL) {
  2074. BowserFreeBrowserServerList(PagedTransport->BrowserServerListBuffer,
  2075. PagedTransport->BrowserServerListLength);
  2076. PagedTransport->BrowserServerListLength = 0;
  2077. PagedTransport->BrowserServerListBuffer = NULL;
  2078. }
  2079. ExReleaseResourceLite(&Transport->BrowserServerListResource);
  2080. }
  2081. } else if (NewStatus & SV_TYPE_BACKUP_BROWSER) {
  2082. dlog(DPRT_BROWSER,
  2083. ("%s: %ws: New status indicates we are a backup, but we think we are not\n",
  2084. Transport->DomainInfo->DomOemDomainName,
  2085. PagedTransport->TransportName.Buffer ));
  2086. PagedTransport->Role = Backup;
  2087. Status = STATUS_SUCCESS;
  2088. }
  2089. if (!NT_SUCCESS(Status) || PagedTransport->Role == Backup) {
  2090. try_return(Status);
  2091. }
  2092. //
  2093. // If we are a potential backup, then update appropriately.
  2094. //
  2095. if (PagedTransport->Role == PotentialBackup) {
  2096. if (!(NewStatus & SV_TYPE_POTENTIAL_BROWSER)) {
  2097. dlog(DPRT_BROWSER,
  2098. ("%s: %ws: New status indicates we are not a potential browser\n",
  2099. Transport->DomainInfo->DomOemDomainName,
  2100. PagedTransport->TransportName.Buffer ));
  2101. UNLOCK_TRANSPORT(Transport);
  2102. TransportLocked = FALSE;
  2103. Status = BowserDeleteTransportNameByName(Transport, NULL,
  2104. BrowserElection);
  2105. if (!NT_SUCCESS(Status)) {
  2106. dlog(DPRT_BROWSER,
  2107. ("%s: %ws: Unable to remove election name: %X\n",
  2108. Transport->DomainInfo->DomOemDomainName,
  2109. PagedTransport->TransportName.Buffer,
  2110. Status));
  2111. try_return(Status);
  2112. }
  2113. LOCK_TRANSPORT(Transport);
  2114. TransportLocked = TRUE;
  2115. PagedTransport->Role = None;
  2116. }
  2117. }
  2118. try_return(Status);
  2119. try_exit:NOTHING;
  2120. } finally {
  2121. if (TransportLocked) {
  2122. UNLOCK_TRANSPORT(Transport);
  2123. }
  2124. if (Transport != NULL) {
  2125. BowserDereferenceTransport(Transport);
  2126. }
  2127. if (ProcessAttached) {
  2128. KeUnstackDetachProcess( &ApcState );
  2129. }
  2130. }
  2131. return Status;
  2132. }
  2133. NTSTATUS
  2134. BowserStopProcessingAnnouncements(
  2135. IN PTRANSPORT_NAME TransportName,
  2136. IN PVOID Context
  2137. )
  2138. {
  2139. PAGED_CODE();
  2140. ASSERT (TransportName->Signature == STRUCTURE_SIGNATURE_TRANSPORTNAME);
  2141. ASSERT (TransportName->NameType == TransportName->PagedTransportName->Name->NameType);
  2142. if ((TransportName->NameType == OtherDomain) ||
  2143. (TransportName->NameType == MasterBrowser) ||
  2144. (TransportName->NameType == PrimaryDomain) ||
  2145. (TransportName->NameType == BrowserElection) ||
  2146. (TransportName->NameType == DomainAnnouncement)) {
  2147. if (TransportName->ProcessHostAnnouncements) {
  2148. BowserDereferenceDiscardableCode( BowserDiscardableCodeSection );
  2149. TransportName->ProcessHostAnnouncements = FALSE;
  2150. }
  2151. }
  2152. return(STATUS_SUCCESS);
  2153. UNREFERENCED_PARAMETER(Context);
  2154. }
  2155. NTSTATUS
  2156. WaitForBrowserRoleChange (
  2157. IN PIRP Irp,
  2158. IN PLMDR_REQUEST_PACKET InputBuffer,
  2159. IN ULONG InputBufferLength
  2160. )
  2161. /*++
  2162. Routine Description:
  2163. This routine will queue a request that will complete when a request
  2164. to make the workstation become a backup browser is received.
  2165. Arguments:
  2166. IN PIRP Irp - I/O request packet describing request.
  2167. Return Value:
  2168. Status of operation.
  2169. Please note that this IRP is cancelable.
  2170. --*/
  2171. {
  2172. NTSTATUS Status;
  2173. PTRANSPORT Transport = NULL;
  2174. PAGED_CODE();
  2175. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: WaitForMasterRoleChange\n"));
  2176. try {
  2177. WCHAR TransportNameBuffer[MAX_PATH+1];
  2178. WCHAR DomainNameBuffer[DNLEN+1];
  2179. if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) {
  2180. try_return(Status = STATUS_INVALID_PARAMETER);
  2181. }
  2182. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  2183. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  2184. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  2185. dprintf(DPRT_REF, ("Called Find transport %lx from WaitForBrowserRoleChange.\n", Transport));
  2186. if (Transport == NULL) {
  2187. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  2188. }
  2189. Status = BowserQueueNonBufferRequest(Irp,
  2190. &Transport->ChangeRoleQueue,
  2191. BowserCancelQueuedRequest
  2192. );
  2193. try_exit:NOTHING;
  2194. } finally {
  2195. if (Transport != NULL) {
  2196. BowserDereferenceTransport(Transport);
  2197. }
  2198. }
  2199. return Status;
  2200. }
  2201. NTSTATUS
  2202. WriteMailslot (
  2203. IN PIRP Irp,
  2204. IN PLMDR_REQUEST_PACKET InputBuffer,
  2205. IN ULONG InputBufferLength,
  2206. IN PVOID OutputBuffer,
  2207. IN ULONG OutputBufferLength
  2208. )
  2209. /*++
  2210. Routine Description:
  2211. This routine will announce the primary domain to the world
  2212. Arguments:
  2213. IN PIRP Irp - I/O request packet describing request.
  2214. Return Value:
  2215. Status of operation.
  2216. Please note that this IRP is cancelable.
  2217. --*/
  2218. {
  2219. NTSTATUS Status;
  2220. PTRANSPORT Transport = NULL;
  2221. UNICODE_STRING DestinationName;
  2222. PAGED_CODE();
  2223. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: %wZ: Write Mailslot\n", &InputBuffer->TransportName ));
  2224. try {
  2225. ANSI_STRING MailslotName;
  2226. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.SendDatagram.Name) ||
  2227. OutputBufferLength < 1) {
  2228. try_return(Status = STATUS_INVALID_PARAMETER);
  2229. }
  2230. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  2231. try_return(Status = STATUS_INVALID_PARAMETER);
  2232. }
  2233. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, FALSE );
  2234. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  2235. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  2236. dprintf(DPRT_REF, ("Called Find transport %lx from WriteMailslot.\n", Transport));
  2237. if (Transport == NULL) {
  2238. try_return(Status = STATUS_OBJECT_NAME_NOT_FOUND);
  2239. }
  2240. DestinationName.Length = DestinationName.MaximumLength =
  2241. (USHORT)InputBuffer->Parameters.SendDatagram.NameLength;
  2242. DestinationName.Buffer = InputBuffer->Parameters.SendDatagram.Name;
  2243. if ( DestinationName.Length == 0 ) {
  2244. try_return(Status = STATUS_INVALID_PARAMETER);
  2245. }
  2246. ENSURE_IN_INPUT_BUFFER( &DestinationName, TRUE, FALSE );
  2247. if (InputBuffer->Parameters.SendDatagram.MailslotNameLength != 0) {
  2248. MailslotName.Buffer = ((PCHAR)InputBuffer->Parameters.SendDatagram.Name)+
  2249. InputBuffer->Parameters.SendDatagram.NameLength;
  2250. MailslotName.MaximumLength = (USHORT)
  2251. InputBuffer->Parameters.SendDatagram.MailslotNameLength;
  2252. MailslotName.Length = MailslotName.MaximumLength - 1;
  2253. ENSURE_IN_INPUT_BUFFER( &MailslotName, FALSE, FALSE );
  2254. if ( MailslotName.Buffer[MailslotName.Length] != '\0' ) {
  2255. try_return(Status = STATUS_INVALID_PARAMETER);
  2256. }
  2257. } else {
  2258. MailslotName.Buffer = MAILSLOT_BROWSER_NAME;
  2259. }
  2260. Status = BowserSendSecondClassMailslot(Transport,
  2261. &DestinationName,
  2262. InputBuffer->Parameters.SendDatagram.DestinationNameType,
  2263. OutputBuffer,
  2264. OutputBufferLength,
  2265. TRUE,
  2266. MailslotName.Buffer,
  2267. NULL);
  2268. try_exit:NOTHING;
  2269. } finally {
  2270. if (Transport != NULL) {
  2271. BowserDereferenceTransport(Transport);
  2272. }
  2273. }
  2274. return Status;
  2275. }
  2276. NTSTATUS
  2277. WaitForNewMaster (
  2278. IN PIRP Irp,
  2279. IN PLMDR_REQUEST_PACKET InputBuffer,
  2280. IN ULONG InputBufferLength
  2281. )
  2282. /*++
  2283. Routine Description:
  2284. This routine will queue a request that will complete when a new workstation
  2285. becomes the master browser server.
  2286. Arguments:
  2287. IN PIRP Irp - I/O request packet describing request.
  2288. Return Value:
  2289. Status of operation.
  2290. Please note that this IRP is cancelable.
  2291. --*/
  2292. {
  2293. NTSTATUS Status;
  2294. PTRANSPORT Transport = NULL;
  2295. UNICODE_STRING ExistingMasterName;
  2296. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2297. PAGED_CODE();
  2298. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: WaitForNewMaster\n"));
  2299. try {
  2300. WCHAR TransportNameBuffer[MAX_PATH+1];
  2301. WCHAR DomainNameBuffer[DNLEN+1];
  2302. WCHAR ExistingMasterNameBuffer[CNLEN+1];
  2303. if (InputBufferLength < (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.GetMasterName.Name)) {
  2304. try_return(Status = STATUS_INVALID_PARAMETER);
  2305. }
  2306. ExistingMasterName.Buffer = InputBuffer->Parameters.GetMasterName.Name;
  2307. ExistingMasterName.Length = ExistingMasterName.MaximumLength = (USHORT)InputBuffer->Parameters.GetMasterName.MasterNameLength;
  2308. ENSURE_IN_INPUT_BUFFER(&ExistingMasterName, FALSE, FALSE);
  2309. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  2310. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  2311. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  2312. dprintf(DPRT_REF, ("Called Find transport %lx from WaitForNewMaster.\n", Transport));
  2313. if (Transport == NULL) {
  2314. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  2315. }
  2316. if (Transport->PagedTransport->Flags & DIRECT_HOST_IPX) {
  2317. try_return (Status = STATUS_NOT_SUPPORTED);
  2318. }
  2319. if (Transport->PagedTransport->MasterName.Length != 0) {
  2320. UNICODE_STRING ExistingMasterNameCopy;
  2321. WCHAR MasterNameBuffer[CNLEN+1];
  2322. ExistingMasterNameCopy.Buffer = MasterNameBuffer;
  2323. ExistingMasterNameCopy.MaximumLength = sizeof(MasterNameBuffer);
  2324. Status = RtlUpcaseUnicodeString(&ExistingMasterNameCopy, &ExistingMasterName, FALSE);
  2325. if (!NT_SUCCESS(Status)) {
  2326. try_return (Status);
  2327. }
  2328. //
  2329. // If the name the application passed in was not the same as the
  2330. // name we have stored locally, we complete the request immediately,
  2331. // since the name changed between when we last determined the name
  2332. // and now.
  2333. //
  2334. LOCK_TRANSPORT(Transport);
  2335. if (!RtlEqualUnicodeString(&ExistingMasterNameCopy, &Transport->PagedTransport->MasterName, FALSE)) {
  2336. RtlCopyUnicodeString(&ExistingMasterNameCopy, &Transport->PagedTransport->MasterName);
  2337. UNLOCK_TRANSPORT(Transport);
  2338. if (InputBufferLength <
  2339. ((ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.GetMasterName.Name)+
  2340. ExistingMasterNameCopy.Length+3*sizeof(WCHAR))) {
  2341. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  2342. }
  2343. InputBuffer->Parameters.GetMasterName.Name[0] = L'\\';
  2344. InputBuffer->Parameters.GetMasterName.Name[1] = L'\\';
  2345. RtlCopyMemory(&InputBuffer->Parameters.GetMasterName.Name[2], ExistingMasterNameCopy.Buffer,
  2346. ExistingMasterNameCopy.Length);
  2347. InputBuffer->Parameters.GetMasterName.MasterNameLength = ExistingMasterNameCopy.Length+2*sizeof(WCHAR);
  2348. InputBuffer->Parameters.GetMasterName.Name[2+(ExistingMasterNameCopy.Length/sizeof(WCHAR))] = UNICODE_NULL;
  2349. Irp->IoStatus.Information = FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.GetMasterName.Name) +
  2350. ExistingMasterNameCopy.Length+3*sizeof(WCHAR);;
  2351. try_return (Status = STATUS_SUCCESS);
  2352. }
  2353. UNLOCK_TRANSPORT(Transport);
  2354. }
  2355. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  2356. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters.GetMasterName.Name)+3*sizeof(WCHAR)) {
  2357. try_return(Status = STATUS_INVALID_PARAMETER);
  2358. }
  2359. Status = BowserQueueNonBufferRequest(Irp,
  2360. &Transport->WaitForNewMasterNameQueue,
  2361. BowserCancelQueuedRequest
  2362. );
  2363. try_exit:NOTHING;
  2364. } finally {
  2365. if ( Transport != NULL ) {
  2366. BowserDereferenceTransport(Transport);
  2367. }
  2368. }
  2369. return Status;
  2370. }
  2371. NTSTATUS
  2372. QueryStatistics(
  2373. IN PIRP Irp,
  2374. OUT PBOWSER_STATISTICS OutputBuffer,
  2375. IN OUT PULONG OutputBufferLength
  2376. )
  2377. {
  2378. KIRQL OldIrql;
  2379. if (*OutputBufferLength != sizeof(BOWSER_STATISTICS)) {
  2380. *OutputBufferLength = 0;
  2381. return STATUS_BUFFER_TOO_SMALL;
  2382. }
  2383. BowserReferenceDiscardableCode( BowserDiscardableCodeSection );
  2384. DISCARDABLE_CODE( BowserDiscardableCodeSection );
  2385. ACQUIRE_SPIN_LOCK(&BowserStatisticsLock, &OldIrql);
  2386. RtlCopyMemory(OutputBuffer, &BowserStatistics, sizeof(BOWSER_STATISTICS));
  2387. RELEASE_SPIN_LOCK(&BowserStatisticsLock, OldIrql);
  2388. BowserDereferenceDiscardableCode( BowserDiscardableCodeSection );
  2389. return STATUS_SUCCESS;
  2390. }
  2391. NTSTATUS
  2392. ResetStatistics(
  2393. VOID
  2394. )
  2395. {
  2396. KIRQL OldIrql;
  2397. BowserReferenceDiscardableCode( BowserDiscardableCodeSection );
  2398. DISCARDABLE_CODE( BowserDiscardableCodeSection );
  2399. ACQUIRE_SPIN_LOCK(&BowserStatisticsLock, &OldIrql);
  2400. RtlZeroMemory(&BowserStatistics, sizeof(BOWSER_STATISTICS));
  2401. KeQuerySystemTime(&BowserStatistics.StartTime);
  2402. RELEASE_SPIN_LOCK(&BowserStatisticsLock, OldIrql);
  2403. BowserDereferenceDiscardableCode( BowserDiscardableCodeSection );
  2404. return STATUS_SUCCESS;
  2405. }
  2406. NTSTATUS
  2407. BowserIpAddressChanged(
  2408. IN PLMDR_REQUEST_PACKET InputBuffer
  2409. )
  2410. /*++
  2411. Routine Description:
  2412. This routine is called whenever the IP address of a transport changes.
  2413. NetBt uses the IP address to associate it's transport endpoint with the
  2414. appropriate NDIS driver. As such, it can't return NDIS specific information,
  2415. until the IP address is defined.
  2416. Arguments:
  2417. InputBuffer - Buffer specifying the name of the transport whose address
  2418. has changed.
  2419. Return Value:
  2420. NTSTATUS
  2421. --*/
  2422. {
  2423. NTSTATUS Status;
  2424. PAGED_CODE();
  2425. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: BowserIpAddressChanged: Calling dead code!!\n"));
  2426. //
  2427. // Nobody should call into us here. This is dead code.
  2428. //
  2429. ASSERT(FALSE);
  2430. //
  2431. // The no longer need notification of address changes.
  2432. // The redir gets PNP bind and unbind notifications when the IP address
  2433. // changes. The redir passes those along to us.
  2434. //
  2435. return STATUS_SUCCESS;
  2436. #ifdef notdef
  2437. //
  2438. // Check some fields in the input buffer.
  2439. //
  2440. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  2441. Status = STATUS_INVALID_PARAMETER;
  2442. goto ReturnStatus;
  2443. }
  2444. if (InputBuffer->TransportName.Length == 0) {
  2445. Status = STATUS_INVALID_PARAMETER;
  2446. goto ReturnStatus;
  2447. }
  2448. //
  2449. // Handle each transport (in each emulated domain) that has this transport name.
  2450. //
  2451. ENSURE_IN_INPUT_BUFFER( &InputBuffer->TransportName, FALSE, FALSE );
  2452. Status = BowserForEachTransport( BowserIpAddressChangedWorker,
  2453. &InputBuffer->TransportName );
  2454. ReturnStatus:
  2455. return Status;
  2456. #endif // notdef
  2457. }
  2458. #ifdef notdef
  2459. NTSTATUS
  2460. BowserIpAddressChangedWorker(
  2461. PTRANSPORT Transport,
  2462. PVOID Context
  2463. )
  2464. /*++
  2465. Routine Description:
  2466. This routine is the worker routine for BowserIpAddressChanged.
  2467. This routine is called whenever the IP address of a transport changes.
  2468. Arguments:
  2469. Transport - Current transport being handled.
  2470. Context - Name of transport to search for
  2471. Return Value:
  2472. Status of the operation.
  2473. --*/
  2474. {
  2475. PUNICODE_STRING TransportName = (PUNICODE_STRING) Context;
  2476. PAGED_CODE();
  2477. try {
  2478. //
  2479. // If the TransportName of the transport matches the one passed in,
  2480. // update the information from the NDIS driver.
  2481. //
  2482. if (RtlEqualUnicodeString(TransportName,
  2483. &Transport->PagedTransport->TransportName, TRUE)) {
  2484. //
  2485. // Notify services that the IP address changed for this transport.
  2486. //
  2487. BowserSendPnp(
  2488. NlPnpNewIpAddress,
  2489. NULL, // All hosted domains
  2490. &Transport->PagedTransport->TransportName,
  2491. BowserTransportFlags(Transport->PagedTransport) );
  2492. //
  2493. // Update bowser information about the provider.
  2494. (VOID) BowserUpdateProviderInformation( Transport->PagedTransport );
  2495. }
  2496. } finally {
  2497. }
  2498. return STATUS_SUCCESS;
  2499. }
  2500. #endif // notdef
  2501. NTSTATUS
  2502. EnableDisableTransport (
  2503. IN PLMDR_REQUEST_PACKET InputBuffer,
  2504. IN ULONG InputBufferLength
  2505. )
  2506. /*++
  2507. Routine Description:
  2508. This routine Implements the IOCTL to enable or disable a transport.
  2509. Arguments:
  2510. InputBuffer - Buffer indicating whether we should enable or disable the
  2511. transport.
  2512. Return Value:
  2513. Status of operation.
  2514. --*/
  2515. {
  2516. NTSTATUS Status;
  2517. PTRANSPORT Transport = NULL;
  2518. PPAGED_TRANSPORT PagedTransport;
  2519. PAGED_CODE();
  2520. try {
  2521. WCHAR TransportNameBuffer[MAX_PATH+1];
  2522. WCHAR DomainNameBuffer[DNLEN+1];
  2523. if (InputBufferLength <
  2524. (ULONG)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters) +
  2525. sizeof(InputBuffer->Parameters.EnableDisableTransport)) {
  2526. try_return(Status = STATUS_INVALID_PARAMETER);
  2527. }
  2528. CAPTURE_UNICODE_STRING( &InputBuffer->TransportName, TransportNameBuffer );
  2529. CAPTURE_UNICODE_STRING( &InputBuffer->EmulatedDomainName, DomainNameBuffer );
  2530. //
  2531. // Check some fields in the input buffer.
  2532. //
  2533. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  2534. try_return (Status = STATUS_INVALID_PARAMETER);
  2535. }
  2536. if (InputBuffer->TransportName.Length == 0) {
  2537. try_return (Status = STATUS_INVALID_PARAMETER);
  2538. }
  2539. //
  2540. // Find the transport whose address has changed.
  2541. //
  2542. dlog( DPRT_FSCTL,
  2543. ("NtDeviceIoControlFile: %wZ: Enable/Disable transport &ld\n",
  2544. &InputBuffer->TransportName,
  2545. InputBuffer->Parameters.EnableDisableTransport.EnableTransport ));
  2546. Transport = BowserFindTransport(&InputBuffer->TransportName, &InputBuffer->EmulatedDomainName );
  2547. dprintf(DPRT_REF, ("Called Find transport %lx from EnableDisableTransport.\n", Transport));
  2548. if (Transport == NULL) {
  2549. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  2550. }
  2551. PagedTransport = Transport->PagedTransport;
  2552. //
  2553. // Set the disabled bit correctly.
  2554. //
  2555. InputBuffer->Parameters.EnableDisableTransport.PreviouslyEnabled =
  2556. !PagedTransport->DisabledTransport;
  2557. if ( InputBuffer->Parameters.EnableDisableTransport.EnableTransport ) {
  2558. PagedTransport->DisabledTransport = FALSE;
  2559. //
  2560. // If the transport was previously disabled and this is an NTAS server,
  2561. // force an election.
  2562. //
  2563. if ( (!InputBuffer->Parameters.EnableDisableTransport.PreviouslyEnabled) &&
  2564. BowserData.IsLanmanNt ) {
  2565. BowserStartElection( Transport );
  2566. }
  2567. } else {
  2568. PagedTransport->DisabledTransport = TRUE;
  2569. //
  2570. // If we're disabling a previously enabled transport,
  2571. // ensure we're not the master browser.
  2572. //
  2573. BowserLoseElection( Transport );
  2574. }
  2575. Status = STATUS_SUCCESS;
  2576. try_exit:NOTHING;
  2577. } finally {
  2578. if (Transport != NULL) {
  2579. BowserDereferenceTransport(Transport);
  2580. }
  2581. }
  2582. return Status;
  2583. }
  2584. NTSTATUS
  2585. BowserRenameDomain (
  2586. IN PLMDR_REQUEST_PACKET InputBuffer,
  2587. IN ULONG InputBufferLength
  2588. )
  2589. /*++
  2590. Routine Description:
  2591. This routine renames an emulated domain.
  2592. Arguments:
  2593. IN PLMDR_REQUEST_PACKET InputBuffer,
  2594. IN ULONG InputBufferLength,
  2595. Return Value:
  2596. NTSTATUS - Status of operation.
  2597. --*/
  2598. {
  2599. NTSTATUS Status;
  2600. PDOMAIN_INFO DomainInfo = NULL;
  2601. WCHAR OldDomainNameBuffer[DNLEN+1];
  2602. UNICODE_STRING OldDomainName;
  2603. CHAR OemDomainName[DNLEN+1];
  2604. DWORD OemDomainNameLength;
  2605. UNICODE_STRING NewDomainName;
  2606. PAGED_CODE();
  2607. dlog(DPRT_FSCTL, ("NtDeviceIoControlFile: RenameDomain\n"));
  2608. try {
  2609. //
  2610. // Check some fields in the input buffer.
  2611. //
  2612. if (InputBufferLength < offsetof(LMDR_REQUEST_PACKET, Parameters.DomainRename.DomainName)) {
  2613. try_return (Status = STATUS_INVALID_PARAMETER);
  2614. }
  2615. if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION_DOM) {
  2616. try_return (Status = STATUS_INVALID_PARAMETER);
  2617. }
  2618. ENSURE_IN_INPUT_BUFFER( &InputBuffer->EmulatedDomainName, TRUE, FALSE );
  2619. //
  2620. // Find the emulated domain to rename
  2621. //
  2622. DomainInfo = BowserFindDomain( &InputBuffer->EmulatedDomainName );
  2623. if ( DomainInfo == NULL ) {
  2624. try_return (Status = STATUS_OBJECT_NAME_NOT_FOUND);
  2625. }
  2626. //
  2627. // Make a copy of the old domain name for use throughout the routine.
  2628. //
  2629. wcscpy( OldDomainNameBuffer, DomainInfo->DomUnicodeDomainNameBuffer );
  2630. RtlInitUnicodeString( &OldDomainName, OldDomainNameBuffer );
  2631. //
  2632. // If the old and new names are the same,
  2633. // we're done.
  2634. //
  2635. NewDomainName.MaximumLength = NewDomainName.Length = (USHORT )
  2636. InputBuffer->Parameters.DomainRename.DomainNameLength;
  2637. NewDomainName.Buffer = InputBuffer->Parameters.DomainRename.DomainName;
  2638. ENSURE_IN_INPUT_BUFFER( &NewDomainName, FALSE, FALSE );
  2639. if ( RtlEqualUnicodeString( &OldDomainName, &NewDomainName, TRUE) ) {
  2640. try_return (Status = STATUS_SUCCESS);
  2641. }
  2642. //
  2643. // Register the new default names with the new domain name.
  2644. //
  2645. Status = BowserForEachTransportInDomain(DomainInfo, BowserAddDefaultNames, &NewDomainName );
  2646. if ( !NT_SUCCESS(Status) || InputBuffer->Parameters.DomainRename.ValidateOnly ) {
  2647. NTSTATUS TempStatus;
  2648. //
  2649. // Delete any names that did get registered.
  2650. //
  2651. (VOID) BowserForEachTransportInDomain(DomainInfo, BowserDeleteDefaultDomainNames, &NewDomainName );
  2652. } else {
  2653. //
  2654. // Store the new domain name into the domain structure
  2655. //
  2656. Status = BowserSetDomainName( DomainInfo, &NewDomainName );
  2657. if ( !NT_SUCCESS(Status)) {
  2658. //
  2659. // Delete any names that did get registered.
  2660. //
  2661. (VOID) BowserForEachTransportInDomain(DomainInfo, BowserDeleteDefaultDomainNames, &NewDomainName );
  2662. } else {
  2663. //
  2664. // Delete the old names.
  2665. //
  2666. (VOID) BowserForEachTransportInDomain(DomainInfo, BowserDeleteDefaultDomainNames, &OldDomainName );
  2667. //
  2668. // Tell Netlogon and the Browser service about this domain rename.
  2669. //
  2670. BowserSendPnp( NlPnpDomainRename,
  2671. &OldDomainName,
  2672. NULL, // Affects all transports
  2673. 0 );
  2674. }
  2675. }
  2676. try_exit:NOTHING;
  2677. } finally {
  2678. if ( DomainInfo != NULL ) {
  2679. BowserDereferenceDomain( DomainInfo );
  2680. }
  2681. }
  2682. return Status;
  2683. }
  2684. PLMDR_REQUEST_PACKET
  2685. RequestPacket32to64 (
  2686. IN PLMDR_REQUEST_PACKET32 RequestPacket32,
  2687. IN OUT PLMDR_REQUEST_PACKET RequestPacket)
  2688. /*++
  2689. Routine Description:
  2690. Converts a 32 bit request packet into supplied native (64 bit)
  2691. packet format. (see bug 454130)
  2692. Arguments:
  2693. RequestPacket32 -- Buffer containing request packet packet by a 32 bit client
  2694. ReqestPacket -- Native (64 bit) request packet buffer
  2695. Return Value:
  2696. a pointer to converted buffer (ReqestPacket arg)
  2697. Remarks:
  2698. No checks assumed at this point (this is a convinience function). It is assumed
  2699. that the conversion is needed at this point
  2700. --*/
  2701. {
  2702. PAGED_CODE();
  2703. ASSERT(RequestPacket32);
  2704. //
  2705. // The following code depends on the request packet structure contents.
  2706. // 1. copy everything before the 2 unicode strings TransportName & EmulatedDomainName.
  2707. // 2. convert the string structs.
  2708. // 3. copy the rest.
  2709. //
  2710. RequestPacket->Type = RequestPacket32->Type;
  2711. RequestPacket->Version = RequestPacket32->Version;
  2712. RequestPacket->Level = RequestPacket32->Level;
  2713. RequestPacket->LogonId = RequestPacket32->LogonId;
  2714. // convert strings.
  2715. RequestPacket->TransportName.Length = RequestPacket32->TransportName.Length;
  2716. RequestPacket->TransportName.MaximumLength = RequestPacket32->TransportName.MaximumLength;
  2717. // note: this line is the reason for all of this
  2718. RequestPacket->TransportName.Buffer = (WCHAR * POINTER_32) RequestPacket32->TransportName.Buffer;
  2719. RequestPacket->EmulatedDomainName.Length = RequestPacket32->EmulatedDomainName.Length;
  2720. RequestPacket->EmulatedDomainName.MaximumLength = RequestPacket32->EmulatedDomainName.MaximumLength;
  2721. // note: this line is the reason for all of this
  2722. RequestPacket->EmulatedDomainName.Buffer = (WCHAR * POINTER_32) RequestPacket32->EmulatedDomainName.Buffer;
  2723. RtlCopyMemory((PBYTE)RequestPacket + (SIZE_T)FIELD_OFFSET(LMDR_REQUEST_PACKET,Parameters),
  2724. (PBYTE)RequestPacket32 + (SIZE_T)FIELD_OFFSET(LMDR_REQUEST_PACKET32,Parameters),
  2725. sizeof(LMDR_REQUEST_PACKET32) - (SIZE_T)FIELD_OFFSET(LMDR_REQUEST_PACKET32,Parameters));
  2726. return RequestPacket;
  2727. }