Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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