Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234 lines
30 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. rxdevice.c
  5. Abstract:
  6. This module contains the support routines for the APIs that call
  7. into the redirector or the datagram receiver.
  8. Author:
  9. Balan Sethu Raman -- Created from the workstation service code
  10. Revision History:
  11. --*/
  12. #include "align.h"
  13. #include "rxdrt.h"
  14. #include "rxdevice.h"
  15. #include "rxconfig.h"
  16. #include "malloc.h"
  17. #define SERVICE_REGISTRY_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
  18. //
  19. // Buffer allocation size for enumeration output buffer.
  20. //
  21. #define INITIAL_ALLOCATION_SIZE 4096 // First attempt size
  22. #define FUDGE_FACTOR_SIZE 1024 // Second try TotalBytesNeeded
  23. // plus this amount
  24. //
  25. // Handle to the Redirector FSD
  26. //
  27. HANDLE RxRedirDeviceHandle = NULL;
  28. HANDLE RxRedirAsyncDeviceHandle = NULL;
  29. BOOLEAN LoadedRdbssInsteadOfRdr = FALSE;
  30. //
  31. // Handle to the Datagram Receiver DD
  32. //
  33. HANDLE RxDgReceiverDeviceHandle = NULL;
  34. HANDLE RxDgrecAsyncDeviceHandle = NULL;
  35. NTSTATUS
  36. RxDeviceControlGetInfo(
  37. IN DDTYPE DeviceDriverType,
  38. IN HANDLE FileHandle,
  39. IN ULONG DeviceControlCode,
  40. IN PVOID RequestPacket,
  41. IN ULONG RequestPacketLength,
  42. OUT PVOID *OutputBuffer,
  43. IN ULONG PreferedMaximumLength,
  44. IN ULONG BufferHintSize,
  45. OUT PULONG Information
  46. )
  47. /*++
  48. Routine Description:
  49. This function allocates the buffer and fill it with the information
  50. that is retrieved from the redirector or datagram receiver.
  51. Arguments:
  52. DeviceDriverType - Supplies the value which indicates whether to call
  53. the redirector or the datagram receiver.
  54. FileHandle - Supplies a handle to the file or device of which to get
  55. information about.
  56. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  57. function control code.
  58. RequestPacket - Supplies a pointer to the device request packet.
  59. RrequestPacketLength - Supplies the length of the device request packet.
  60. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  61. which contains the use information requested. This pointer is set to
  62. NULL if return code is not Success.
  63. PreferedMaximumLength - Supplies the number of bytes of information to
  64. return in the buffer. If this value is MAXULONG, we will try to
  65. return all available information if there is enough memory resource.
  66. BufferHintSize - Supplies the hint size of the output buffer so that the
  67. memory allocated for the initial buffer will most likely be large
  68. enough to hold all requested data.
  69. Information - Returns the information code from the NtFsControlFile or
  70. NtIoDeviceControlFile call.
  71. Return Value:
  72. NET_API_STATUS - NERR_Success or reason for failure.
  73. --*/
  74. {
  75. NTSTATUS status;
  76. DWORD OutputBufferLength;
  77. DWORD TotalBytesNeeded = 1;
  78. ULONG OriginalResumeKey;
  79. //
  80. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  81. // the information, regardless of size. Allocate the output buffer of a
  82. // reasonable size and try to use it. If this fails, the Redirector FSD
  83. // will say how much we need to allocate.
  84. //
  85. if (PreferedMaximumLength == MAXULONG) {
  86. OutputBufferLength = (BufferHintSize) ?
  87. BufferHintSize :
  88. INITIAL_ALLOCATION_SIZE;
  89. }
  90. else {
  91. OutputBufferLength = PreferedMaximumLength;
  92. }
  93. OutputBufferLength = ROUND_UP_COUNT(OutputBufferLength, ALIGN_WCHAR);
  94. if ((*OutputBuffer = malloc(OutputBufferLength)) == NULL) {
  95. return ERROR_NOT_ENOUGH_MEMORY;
  96. }
  97. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  98. if (DeviceDriverType == Redirector) {
  99. PLMR_REQUEST_PACKET Rrp = (PLMR_REQUEST_PACKET) RequestPacket;
  100. OriginalResumeKey = Rrp->Parameters.Get.ResumeHandle;
  101. //
  102. // Make the request of the Redirector
  103. //
  104. status = RxRedirFsControl(
  105. FileHandle,
  106. DeviceControlCode,
  107. Rrp,
  108. RequestPacketLength,
  109. *OutputBuffer,
  110. OutputBufferLength,
  111. Information
  112. );
  113. if (status == ERROR_MORE_DATA) {
  114. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  115. }
  116. }
  117. else {
  118. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  119. OriginalResumeKey = Drrp->Parameters.EnumerateNames.ResumeHandle;
  120. //
  121. // Make the request of the Datagram Receiver
  122. //
  123. status = RxDgReceiverIoControl(
  124. FileHandle,
  125. DeviceControlCode,
  126. Drrp,
  127. RequestPacketLength,
  128. *OutputBuffer,
  129. OutputBufferLength,
  130. NULL
  131. );
  132. if (status == ERROR_MORE_DATA) {
  133. TotalBytesNeeded = Drrp->Parameters.EnumerateNames.TotalBytesNeeded;
  134. }
  135. }
  136. if ((TotalBytesNeeded > OutputBufferLength) &&
  137. (PreferedMaximumLength == MAXULONG)) {
  138. //
  139. // Initial output buffer allocated was too small and we need to return
  140. // all data. First free the output buffer before allocating the
  141. // required size plus a fudge factor just in case the amount of data
  142. // grew.
  143. //
  144. free(*OutputBuffer);
  145. OutputBufferLength =
  146. ROUND_UP_COUNT((TotalBytesNeeded + FUDGE_FACTOR_SIZE),
  147. ALIGN_WCHAR);
  148. if ((*OutputBuffer = malloc(OutputBufferLength)) == NULL) {
  149. return ERROR_NOT_ENOUGH_MEMORY;
  150. }
  151. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  152. //
  153. // Try again to get the information from the redirector or datagram
  154. // receiver
  155. //
  156. if (DeviceDriverType == Redirector) {
  157. PLMR_REQUEST_PACKET Rrp = (PLMR_REQUEST_PACKET) RequestPacket;
  158. Rrp->Parameters.Get.ResumeHandle = OriginalResumeKey;
  159. //
  160. // Make the request of the Redirector
  161. //
  162. status = RxRedirFsControl(
  163. FileHandle,
  164. DeviceControlCode,
  165. Rrp,
  166. RequestPacketLength,
  167. *OutputBuffer,
  168. OutputBufferLength,
  169. Information
  170. );
  171. }
  172. else {
  173. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  174. Drrp->Parameters.EnumerateNames.ResumeHandle = OriginalResumeKey;
  175. //
  176. // Make the request of the Datagram Receiver
  177. //
  178. status = RxDgReceiverIoControl(
  179. FileHandle,
  180. DeviceControlCode,
  181. Drrp,
  182. RequestPacketLength,
  183. *OutputBuffer,
  184. OutputBufferLength,
  185. NULL
  186. );
  187. }
  188. }
  189. //
  190. // If not successful in getting any data, or if the caller asked for
  191. // all available data with PreferedMaximumLength == MAXULONG and
  192. // our buffer overflowed, free the output buffer and set its pointer
  193. // to NULL.
  194. //
  195. if ((status != STATUS_SUCCESS && status != ERROR_MORE_DATA) ||
  196. (TotalBytesNeeded == 0) ||
  197. (PreferedMaximumLength == MAXULONG && status == ERROR_MORE_DATA)) {
  198. free(*OutputBuffer);
  199. *OutputBuffer = NULL;
  200. //
  201. // PreferedMaximumLength == MAXULONG and buffer overflowed means
  202. // we do not have enough memory to satisfy the request.
  203. //
  204. if (status == ERROR_MORE_DATA) {
  205. status = ERROR_NOT_ENOUGH_MEMORY;
  206. }
  207. }
  208. return status;
  209. }
  210. NTSTATUS
  211. RxOpenRedirector(
  212. VOID
  213. )
  214. /*++
  215. Routine Description:
  216. This routine opens the NT LAN Man redirector FSD.
  217. Arguments:
  218. None.
  219. Return Value:
  220. NTSTATUS - NERR_Success or reason for failure.
  221. --*/
  222. {
  223. NTSTATUS ntstatus;
  224. UNICODE_STRING DeviceName;
  225. IO_STATUS_BLOCK IoStatusBlock;
  226. OBJECT_ATTRIBUTES ObjectAttributes;
  227. //
  228. // Open the redirector device.
  229. //
  230. RtlInitUnicodeString(&DeviceName,
  231. DD_NFS2_DEVICE_NAME_U);
  232. InitializeObjectAttributes(
  233. &ObjectAttributes,
  234. &DeviceName,
  235. OBJ_CASE_INSENSITIVE,
  236. NULL,
  237. NULL
  238. );
  239. ntstatus = NtOpenFile(
  240. &RxRedirDeviceHandle,
  241. SYNCHRONIZE,
  242. &ObjectAttributes,
  243. &IoStatusBlock,
  244. FILE_SHARE_VALID_FLAGS,
  245. FILE_SYNCHRONOUS_IO_NONALERT
  246. );
  247. if (NT_SUCCESS(ntstatus)) {
  248. ntstatus = IoStatusBlock.Status;
  249. }
  250. if (! NT_SUCCESS(ntstatus)) {
  251. RxRedirDeviceHandle = NULL;
  252. return ntstatus;
  253. }
  254. ntstatus = NtOpenFile(
  255. &RxRedirAsyncDeviceHandle,
  256. FILE_READ_DATA | FILE_WRITE_DATA,
  257. &ObjectAttributes,
  258. &IoStatusBlock,
  259. FILE_SHARE_VALID_FLAGS,
  260. 0L
  261. );
  262. if (NT_SUCCESS(ntstatus)) {
  263. ntstatus = IoStatusBlock.Status;
  264. }
  265. if (! NT_SUCCESS(ntstatus)) {
  266. RxRedirAsyncDeviceHandle = NULL;
  267. }
  268. return ntstatus;
  269. }
  270. NTSTATUS
  271. RxOpenDgReceiver(
  272. VOID
  273. )
  274. /*++
  275. Routine Description:
  276. This routine opens the NT LAN Man Datagram Receiver driver.
  277. Arguments:
  278. None.
  279. Return Value:
  280. NTSTATUS - NERR_Success or reason for failure.
  281. --*/
  282. {
  283. NTSTATUS ntstatus;
  284. UNICODE_STRING DeviceName;
  285. IO_STATUS_BLOCK IoStatusBlock;
  286. OBJECT_ATTRIBUTES ObjectAttributes;
  287. //
  288. // Open the redirector device.
  289. //
  290. RtlInitUnicodeString( &DeviceName, DD_BROWSER_DEVICE_NAME_U);
  291. InitializeObjectAttributes(
  292. &ObjectAttributes,
  293. &DeviceName,
  294. OBJ_CASE_INSENSITIVE,
  295. NULL,
  296. NULL
  297. );
  298. ntstatus = NtOpenFile(
  299. &RxDgReceiverDeviceHandle,
  300. SYNCHRONIZE,
  301. &ObjectAttributes,
  302. &IoStatusBlock,
  303. FILE_SHARE_VALID_FLAGS,
  304. FILE_SYNCHRONOUS_IO_NONALERT
  305. );
  306. if (NT_SUCCESS(ntstatus)) {
  307. ntstatus = IoStatusBlock.Status;
  308. }
  309. if (! NT_SUCCESS(ntstatus)) {
  310. RxDgReceiverDeviceHandle = NULL;
  311. return ntstatus;
  312. }
  313. ntstatus = NtOpenFile(
  314. &RxDgrecAsyncDeviceHandle,
  315. FILE_READ_DATA | FILE_WRITE_DATA,
  316. &ObjectAttributes,
  317. &IoStatusBlock,
  318. FILE_SHARE_VALID_FLAGS,
  319. 0L
  320. );
  321. if (NT_SUCCESS(ntstatus)) {
  322. ntstatus = IoStatusBlock.Status;
  323. }
  324. if (! NT_SUCCESS(ntstatus)) {
  325. RxDgrecAsyncDeviceHandle = NULL;
  326. }
  327. return ntstatus;
  328. }
  329. NTSTATUS
  330. RxUnloadDriver(
  331. IN LPWSTR DriverNameString
  332. )
  333. {
  334. ULONG Privileges[1];
  335. LPWSTR DriverRegistryName;
  336. UNICODE_STRING DriverRegistryString;
  337. NTSTATUS Status;
  338. NTSTATUS ntstatus;
  339. DriverRegistryName = (LPWSTR) malloc(
  340. (UINT) (sizeof(SERVICE_REGISTRY_KEY) +
  341. (wcslen(DriverNameString) *
  342. sizeof(WCHAR)))
  343. );
  344. if (DriverRegistryName == NULL) {
  345. return ERROR_NOT_ENOUGH_MEMORY;
  346. }
  347. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  348. Status = RxGetPrivilege(1, Privileges);
  349. if (Status != STATUS_SUCCESS) {
  350. free(DriverRegistryName);
  351. return Status;
  352. }
  353. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  354. wcscat(DriverRegistryName, DriverNameString);
  355. RtlInitUnicodeString(&DriverRegistryString, DriverRegistryName);
  356. ntstatus = NtUnloadDriver(&DriverRegistryString);
  357. free(DriverRegistryName);
  358. RxReleasePrivilege();
  359. return ntstatus;
  360. }
  361. NTSTATUS
  362. RxLoadDriver(
  363. IN LPWSTR DriverNameString
  364. )
  365. {
  366. ULONG Privileges[1];
  367. LPWSTR DriverRegistryName;
  368. UNICODE_STRING DriverRegistryString;
  369. NTSTATUS Status;
  370. NTSTATUS ntstatus;
  371. DriverRegistryName = (LPWSTR) malloc(
  372. (UINT) (sizeof(SERVICE_REGISTRY_KEY) +
  373. (wcslen(DriverNameString) *
  374. sizeof(WCHAR)))
  375. );
  376. if (DriverRegistryName == NULL) {
  377. return ERROR_NOT_ENOUGH_MEMORY;
  378. }
  379. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  380. Status = RxGetPrivilege(1, Privileges);
  381. if (Status != STATUS_SUCCESS) {
  382. free(DriverRegistryName);
  383. return Status;
  384. }
  385. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  386. wcscat(DriverRegistryName, DriverNameString);
  387. RtlInitUnicodeString(&DriverRegistryString, DriverRegistryName);
  388. ntstatus = NtLoadDriver(&DriverRegistryString);
  389. RxReleasePrivilege();
  390. free(DriverRegistryName);
  391. if (ntstatus != STATUS_SUCCESS && ntstatus != STATUS_IMAGE_ALREADY_LOADED) {
  392. LPWSTR subString[1];
  393. subString[0] = DriverNameString;
  394. }
  395. return ntstatus;
  396. }
  397. NTSTATUS
  398. RxStopRedirector(
  399. VOID
  400. )
  401. /*++
  402. Routine Description:
  403. This routine close the LAN Man Redirector device.
  404. Arguments:
  405. None.
  406. Return Value:
  407. --*/
  408. {
  409. LMR_REQUEST_PACKET Rrp;
  410. LMDR_REQUEST_PACKET Drp;
  411. NTSTATUS Status;
  412. Rrp.Version = REQUEST_PACKET_VERSION;
  413. Status = RxRedirFsControl(
  414. RxRedirDeviceHandle,
  415. FSCTL_LMR_STOP,
  416. &Rrp,
  417. sizeof(LMR_REQUEST_PACKET),
  418. NULL,
  419. 0,
  420. NULL);
  421. return Status;
  422. }
  423. NTSTATUS
  424. RxStopDgReceiver(
  425. VOID
  426. )
  427. /*++
  428. Routine Description:
  429. This routine stops the datagram receiver.
  430. Arguments:
  431. None.
  432. Return Value:
  433. --*/
  434. {
  435. NTSTATUS Status;
  436. if (RxDgReceiverDeviceHandle != NULL) {
  437. LMDR_REQUEST_PACKET Drp;
  438. Drp.Version = LMDR_REQUEST_PACKET_VERSION;
  439. (void) RxDgReceiverIoControl(
  440. RxDgReceiverDeviceHandle,
  441. IOCTL_LMDR_STOP,
  442. &Drp,
  443. sizeof(LMDR_REQUEST_PACKET),
  444. NULL,
  445. 0,
  446. NULL
  447. );
  448. } else {
  449. DbgPrint("[RxDevice] Invalid datagram receiver handle\n");
  450. Status = STATUS_INVALID_HANDLE;
  451. }
  452. return Status;
  453. }
  454. NTSTATUS
  455. RxRedirFsControl(
  456. IN HANDLE FileHandle,
  457. IN ULONG RedirControlCode,
  458. IN PLMR_REQUEST_PACKET Rrp,
  459. IN ULONG RrpLength,
  460. IN PVOID SecondBuffer OPTIONAL,
  461. IN ULONG SecondBufferLength,
  462. OUT PULONG Information OPTIONAL
  463. )
  464. /*++
  465. Routine Description:
  466. Arguments:
  467. FileHandle - Supplies a handle to the file or device on which the service
  468. is being performed.
  469. RedirControlCode - Supplies the NtFsControlFile function code given to
  470. the redirector.
  471. Rrp - Supplies the redirector request packet.
  472. RrpLength - Supplies the length of the redirector request packet.
  473. SecondBuffer - Supplies the second buffer in call to NtFsControlFile.
  474. SecondBufferLength - Supplies the length of the second buffer.
  475. Information - Returns the information field of the I/O status block.
  476. Return Value:
  477. NTSTATUS - NERR_Success or reason for failure.
  478. --*/
  479. {
  480. NTSTATUS ntstatus;
  481. IO_STATUS_BLOCK IoStatusBlock;
  482. //
  483. // Send the request to the Redirector FSD.
  484. //
  485. ntstatus = NtFsControlFile(
  486. FileHandle,
  487. NULL,
  488. NULL,
  489. NULL,
  490. &IoStatusBlock,
  491. RedirControlCode,
  492. Rrp,
  493. RrpLength,
  494. SecondBuffer,
  495. SecondBufferLength
  496. );
  497. if (NT_SUCCESS(ntstatus)) {
  498. ntstatus = IoStatusBlock.Status;
  499. }
  500. if (ARGUMENT_PRESENT(Information)) {
  501. *Information = IoStatusBlock.Information;
  502. }
  503. return ntstatus;
  504. }
  505. NTSTATUS
  506. RxDgReceiverIoControl(
  507. IN HANDLE FileHandle,
  508. IN ULONG DgReceiverControlCode,
  509. IN PLMDR_REQUEST_PACKET Drp,
  510. IN ULONG DrpSize,
  511. IN PVOID SecondBuffer OPTIONAL,
  512. IN ULONG SecondBufferLength,
  513. OUT PULONG Information OPTIONAL
  514. )
  515. /*++
  516. Routine Description:
  517. Arguments:
  518. FileHandle - Supplies a handle to the file or device on which the service
  519. is being performed.
  520. DgReceiverControlCode - Supplies the NtDeviceIoControlFile function code
  521. given to the datagram receiver.
  522. Drp - Supplies the datagram receiver request packet.
  523. DrpSize - Supplies the length of the datagram receiver request packet.
  524. SecondBuffer - Supplies the second buffer in call to NtDeviceIoControlFile.
  525. SecondBufferLength - Supplies the length of the second buffer.
  526. Information - Returns the information field of the I/O status block.
  527. Return Value:
  528. NTSTATUS - NERR_Success or reason for failure.
  529. --*/
  530. {
  531. NTSTATUS ntstatus;
  532. IO_STATUS_BLOCK IoStatusBlock;
  533. if (FileHandle == NULL) {
  534. return STATUS_INVALID_HANDLE;
  535. }
  536. Drp->TransportName.Length = 0;
  537. //
  538. // Send the request to the Datagram Receiver DD.
  539. //
  540. ntstatus = NtDeviceIoControlFile(
  541. FileHandle,
  542. NULL,
  543. NULL,
  544. NULL,
  545. &IoStatusBlock,
  546. DgReceiverControlCode,
  547. Drp,
  548. DrpSize,
  549. SecondBuffer,
  550. SecondBufferLength
  551. );
  552. if (NT_SUCCESS(ntstatus)) {
  553. ntstatus = IoStatusBlock.Status;
  554. }
  555. if (ARGUMENT_PRESENT(Information)) {
  556. *Information = IoStatusBlock.Information;
  557. }
  558. return ntstatus;
  559. }
  560. NTSTATUS
  561. RxAsyncBindTransport(
  562. IN LPWSTR transportName,
  563. IN DWORD qualityOfService,
  564. IN PLIST_ENTRY pHeader
  565. )
  566. /*++
  567. Routine Description:
  568. This function async binds the specified transport to the redirector
  569. and the datagram receiver.
  570. NOTE: The transport name length pass to the redirector and
  571. datagram receiver is the number of bytes.
  572. Arguments:
  573. transportName - Supplies the name of the transport to bind to.
  574. qualityOfService - Supplies a value which specifies the search
  575. order of the transport with respect to other transports. The
  576. highest value is searched first.
  577. Return Value:
  578. NO_ERROR
  579. --*/
  580. {
  581. NTSTATUS ntstatus;
  582. NTSTATUS status;
  583. DWORD size;
  584. DWORD redirSize;
  585. DWORD dgrecSize;
  586. DWORD nameLength;
  587. PRX_BIND pBind;
  588. PRX_BIND_REDIR pBindRedir;
  589. PRX_BIND_DGREC pBindDgrec;
  590. nameLength = wcslen( transportName);
  591. //
  592. // Make sure *Size-s are DWORD aligned.
  593. //
  594. dgrecSize = redirSize = size = (nameLength & 1) ? sizeof( WCHAR) : 0;
  595. //
  596. // Then add the fixed part to *Size-s.
  597. //
  598. size += sizeof( RX_BIND) + nameLength * sizeof( WCHAR);
  599. redirSize += sizeof( RX_BIND_REDIR) + nameLength * sizeof( WCHAR);
  600. dgrecSize += sizeof( RX_BIND_DGREC) +
  601. nameLength * sizeof( WCHAR)
  602. ;
  603. pBind = (PVOID) malloc(
  604. (UINT) (size + redirSize + dgrecSize)
  605. );
  606. if ( pBind == NULL) {
  607. return GetLastError();
  608. }
  609. pBind->TransportNameLength = nameLength * sizeof( WCHAR);
  610. wcscpy( pBind->TransportName, transportName);
  611. pBind->Redir = pBindRedir = (PRX_BIND_REDIR)( (PCHAR)pBind + size);
  612. pBind->Dgrec = pBindDgrec = (PRX_BIND_DGREC)( (PCHAR)pBindRedir + redirSize);
  613. pBindRedir->EventHandle = INVALID_HANDLE_VALUE;
  614. pBindRedir->Bound = FALSE;
  615. pBindRedir->Packet.Version = REQUEST_PACKET_VERSION;
  616. pBindRedir->Packet.Parameters.Bind.QualityOfService = qualityOfService;
  617. pBindRedir->Packet.Parameters.Bind.TransportNameLength =
  618. nameLength * sizeof( WCHAR);
  619. wcscpy( pBindRedir->Packet.Parameters.Bind.TransportName, transportName);
  620. pBindDgrec->EventHandle = INVALID_HANDLE_VALUE;
  621. pBindDgrec->Bound = FALSE;
  622. pBindDgrec->Packet.Version = LMDR_REQUEST_PACKET_VERSION;
  623. pBindDgrec->Packet.Level = 0; // Indicate computername doesn't follow transport name
  624. pBindDgrec->Packet.Parameters.Bind.TransportNameLength =
  625. nameLength * sizeof( WCHAR);
  626. wcscpy( pBindDgrec->Packet.Parameters.Bind.TransportName, transportName);
  627. pBindRedir->EventHandle = CreateEvent(
  628. NULL,
  629. TRUE,
  630. FALSE,
  631. NULL
  632. );
  633. if ( pBindRedir->EventHandle == INVALID_HANDLE_VALUE) {
  634. status = GetLastError();
  635. goto tail_exit;
  636. }
  637. ntstatus = NtFsControlFile(
  638. RxRedirAsyncDeviceHandle,
  639. pBindRedir->EventHandle,
  640. NULL, // apc routine
  641. NULL, // apc context
  642. &pBindRedir->IoStatusBlock,
  643. FSCTL_LMR_BIND_TO_TRANSPORT, // control code
  644. &pBindRedir->Packet,
  645. sizeof( LMR_REQUEST_PACKET) +
  646. pBindRedir->Packet.Parameters.Bind.TransportNameLength,
  647. NULL,
  648. 0
  649. );
  650. if ( ntstatus != STATUS_PENDING) {
  651. CloseHandle( pBindRedir->EventHandle);
  652. pBindRedir->EventHandle = INVALID_HANDLE_VALUE;
  653. }
  654. pBindDgrec->EventHandle = CreateEvent(
  655. NULL,
  656. TRUE,
  657. FALSE,
  658. NULL
  659. );
  660. if ( pBindDgrec->EventHandle == INVALID_HANDLE_VALUE) {
  661. status = GetLastError();
  662. goto tail_exit;
  663. }
  664. ntstatus = NtDeviceIoControlFile(
  665. RxDgrecAsyncDeviceHandle,
  666. pBindDgrec->EventHandle,
  667. NULL,
  668. NULL,
  669. &pBindDgrec->IoStatusBlock,
  670. IOCTL_LMDR_BIND_TO_TRANSPORT,
  671. &pBindDgrec->Packet,
  672. dgrecSize,
  673. NULL,
  674. 0
  675. );
  676. if ( ntstatus != STATUS_PENDING) {
  677. CloseHandle( pBindDgrec->EventHandle);
  678. pBindDgrec->EventHandle = INVALID_HANDLE_VALUE;
  679. }
  680. tail_exit:
  681. InsertTailList( pHeader, &pBind->ListEntry);
  682. return NO_ERROR;
  683. }
  684. NTSTATUS
  685. RxBindTransport(
  686. IN LPTSTR TransportName,
  687. IN DWORD QualityOfService,
  688. OUT LPDWORD ErrorParameter OPTIONAL
  689. )
  690. /*++
  691. Routine Description:
  692. This function binds the specified transport to the redirector
  693. and the datagram receiver.
  694. NOTE: The transport name length pass to the redirector and
  695. datagram receiver is the number of bytes.
  696. Arguments:
  697. TransportName - Supplies the name of the transport to bind to.
  698. QualityOfService - Supplies a value which specifies the search
  699. order of the transport with respect to other transports. The
  700. highest value is searched first.
  701. ErrorParameter - Returns the identifier to the invalid parameter if
  702. this function returns ERROR_INVALID_PARAMETER.
  703. Return Value:
  704. NTSTATUS - NERR_Success or reason for failure.
  705. --*/
  706. {
  707. NTSTATUS status;
  708. DWORD RequestPacketSize;
  709. DWORD TransportNameSize = wcslen(TransportName) * sizeof(TCHAR);
  710. PLMR_REQUEST_PACKET Rrp;
  711. PLMDR_REQUEST_PACKET Drrp;
  712. //
  713. // Size of request packet buffer
  714. //
  715. RequestPacketSize = wcslen(TransportName) * sizeof(WCHAR) +
  716. max(sizeof(LMR_REQUEST_PACKET),
  717. sizeof(LMDR_REQUEST_PACKET));
  718. //
  719. // Allocate memory for redirector/datagram receiver request packet
  720. //
  721. if ((Rrp = (PVOID) malloc((UINT) RequestPacketSize)) == NULL) {
  722. return GetLastError();
  723. }
  724. //
  725. // Get redirector to bind to transport
  726. //
  727. Rrp->Version = REQUEST_PACKET_VERSION;
  728. Rrp->Parameters.Bind.QualityOfService = QualityOfService;
  729. Rrp->Parameters.Bind.TransportNameLength = TransportNameSize;
  730. wcscpy(Rrp->Parameters.Bind.TransportName, TransportName);
  731. if ((status = RxRedirFsControl(
  732. RxRedirDeviceHandle,
  733. FSCTL_LMR_BIND_TO_TRANSPORT,
  734. Rrp,
  735. sizeof(LMR_REQUEST_PACKET) +
  736. Rrp->Parameters.Bind.TransportNameLength,
  737. //Rrp, BUGBUG: rdr bugchecks!
  738. //RequestPacketSize, specify NULL for now
  739. NULL,
  740. 0,
  741. NULL
  742. )) != STATUS_SUCCESS) {
  743. if (status == ERROR_INVALID_PARAMETER &&
  744. ARGUMENT_PRESENT(ErrorParameter)) {
  745. *ErrorParameter = Rrp->Parameters.Bind.WkstaParameter;
  746. }
  747. (void) free(Rrp);
  748. return status;
  749. }
  750. //
  751. // Get dgrec to bind to transport
  752. //
  753. //
  754. // Make use of the same request packet buffer as FSCtl to
  755. // redirector.
  756. //
  757. Drrp = (PLMDR_REQUEST_PACKET) Rrp;
  758. Drrp->Version = LMDR_REQUEST_PACKET_VERSION;
  759. Drrp->Parameters.Bind.TransportNameLength = TransportNameSize;
  760. wcscpy(Drrp->Parameters.Bind.TransportName, TransportName);
  761. status = RxDgReceiverIoControl(
  762. RxDgReceiverDeviceHandle,
  763. IOCTL_LMDR_BIND_TO_TRANSPORT,
  764. Drrp,
  765. RequestPacketSize,
  766. NULL,
  767. 0,
  768. NULL
  769. );
  770. (void) free(Rrp);
  771. return status;
  772. }
  773. VOID
  774. RxUnbindTransport2(
  775. IN PRX_BIND pBind
  776. )
  777. /*++
  778. Routine Description:
  779. This function unbinds the specified transport from the redirector
  780. and the datagram receiver.
  781. Arguments:
  782. pBind - structure constructed via RxAsyncBindTransport()
  783. Return Value:
  784. None.
  785. --*/
  786. {
  787. // NTSTATUS status;
  788. PRX_BIND_REDIR pBindRedir = pBind->Redir;
  789. PRX_BIND_DGREC pBindDgrec = pBind->Dgrec;
  790. //
  791. // Get redirector to unbind from transport
  792. //
  793. if ( pBindRedir->Bound == TRUE) {
  794. pBindRedir->Packet.Parameters.Unbind.TransportNameLength
  795. = pBind->TransportNameLength;
  796. memcpy(
  797. pBindRedir->Packet.Parameters.Unbind.TransportName,
  798. pBind->TransportName,
  799. pBind->TransportNameLength
  800. );
  801. (VOID)NtFsControlFile(
  802. RxRedirDeviceHandle,
  803. NULL,
  804. NULL, // apc routine
  805. NULL, // apc context
  806. &pBindRedir->IoStatusBlock,
  807. FSCTL_LMR_UNBIND_FROM_TRANSPORT, // control code
  808. &pBindRedir->Packet,
  809. sizeof( LMR_REQUEST_PACKET) +
  810. pBindRedir->Packet.Parameters.Unbind.TransportNameLength,
  811. NULL,
  812. 0
  813. );
  814. pBindRedir->Bound = FALSE;
  815. }
  816. //
  817. // Get datagram receiver to unbind from transport
  818. //
  819. if ( pBindDgrec->Bound == TRUE) {
  820. pBindDgrec->Packet.Parameters.Unbind.TransportNameLength
  821. = pBind->TransportNameLength;
  822. memcpy(
  823. pBindDgrec->Packet.Parameters.Unbind.TransportName,
  824. pBind->TransportName,
  825. pBind->TransportNameLength
  826. );
  827. (VOID)NtDeviceIoControlFile(
  828. RxDgReceiverDeviceHandle,
  829. NULL,
  830. NULL, // apc routine
  831. NULL, // apc context
  832. &pBindDgrec->IoStatusBlock,
  833. FSCTL_LMR_UNBIND_FROM_TRANSPORT, // control code
  834. &pBindDgrec->Packet,
  835. sizeof( LMR_REQUEST_PACKET) +
  836. pBindDgrec->Packet.Parameters.Unbind.TransportNameLength,
  837. NULL,
  838. 0
  839. );
  840. pBindDgrec->Bound = FALSE;
  841. }
  842. }
  843. NTSTATUS
  844. RxUnbindTransport(
  845. IN LPTSTR TransportName,
  846. IN DWORD ForceLevel
  847. )
  848. /*++
  849. Routine Description:
  850. This function unbinds the specified transport from the redirector
  851. and the datagram receiver.
  852. NOTE: The transport name length pass to the redirector and
  853. datagram receiver is the number of bytes.
  854. Arguments:
  855. TransportName - Supplies the name of the transport to bind to.
  856. ForceLevel - Supplies the force level to delete active connections
  857. on the specified transport.
  858. Return Value:
  859. NTSTATUS - NERR_Success or reason for failure.
  860. --*/
  861. {
  862. NTSTATUS status;
  863. DWORD RequestPacketSize;
  864. DWORD TransportNameSize = wcslen(TransportName) * sizeof(TCHAR);
  865. PLMR_REQUEST_PACKET Rrp;
  866. PLMDR_REQUEST_PACKET Drrp;
  867. //
  868. // Size of request packet buffer
  869. //
  870. RequestPacketSize = wcslen(TransportName) * sizeof(WCHAR) +
  871. max(sizeof(LMR_REQUEST_PACKET),
  872. sizeof(LMDR_REQUEST_PACKET));
  873. //
  874. // Allocate memory for redirector/datagram receiver request packet
  875. //
  876. if ((Rrp = (PVOID) malloc((UINT) RequestPacketSize)) == NULL) {
  877. return GetLastError();
  878. }
  879. //
  880. // Get redirector to unbind from transport
  881. //
  882. Rrp->Version = REQUEST_PACKET_VERSION;
  883. Rrp->Level = ForceLevel;
  884. Rrp->Parameters.Unbind.TransportNameLength = TransportNameSize;
  885. wcscpy(Rrp->Parameters.Unbind.TransportName, TransportName);
  886. if ((status = RxRedirFsControl(
  887. RxRedirDeviceHandle,
  888. FSCTL_LMR_UNBIND_FROM_TRANSPORT,
  889. Rrp,
  890. sizeof(LMR_REQUEST_PACKET) +
  891. Rrp->Parameters.Unbind.TransportNameLength,
  892. NULL,
  893. 0,
  894. NULL
  895. )) != STATUS_SUCCESS) {
  896. (void) free(Rrp);
  897. return status;
  898. }
  899. //
  900. // Get datagram receiver to unbind from transport
  901. //
  902. //
  903. // Make use of the same request packet buffer as FSCtl to
  904. // redirector.
  905. //
  906. Drrp = (PLMDR_REQUEST_PACKET) Rrp;
  907. Drrp->Version = LMDR_REQUEST_PACKET_VERSION;
  908. Drrp->Level = ForceLevel;
  909. Drrp->Parameters.Unbind.TransportNameLength = TransportNameSize;
  910. wcscpy(Drrp->Parameters.Unbind.TransportName, TransportName);
  911. if ((status = RxDgReceiverIoControl(
  912. RxDgReceiverDeviceHandle,
  913. IOCTL_LMDR_UNBIND_FROM_TRANSPORT,
  914. Drrp,
  915. RequestPacketSize,
  916. NULL,
  917. 0,
  918. NULL
  919. )) != STATUS_SUCCESS) {
  920. // BUGBUG: This is a hack until the bowser supports XNS and LOOP.
  921. if (status == STATUS_NOT_FOUND) {
  922. status = STATUS_SUCCESS;
  923. }
  924. }
  925. (void) free(Rrp);
  926. return status;
  927. }
  928.