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.

2077 lines
52 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. wsdevice.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. Rita Wong (ritaw) 20-Feb-1991
  10. Revision History:
  11. --*/
  12. #include "wsutil.h"
  13. #include "wsconfig.h"
  14. #include "wsdevice.h"
  15. #include "wsbind.h"
  16. #include <lmerrlog.h> // Eventlog message IDs
  17. #include "winreg.h" // registry API's
  18. #include <prefix.h> // PREFIX_ equates.
  19. //
  20. // Buffer allocation size for enumeration output buffer.
  21. //
  22. #define INITIAL_ALLOCATION_SIZE 4096 // First attempt size
  23. #define FUDGE_FACTOR_SIZE 1024 // Second try TotalBytesNeeded
  24. // plus this amount
  25. #define CSC_WAIT_TIME 15 * 1000 // give agent 15 seconds to stop CSC
  26. //-------------------------------------------------------------------//
  27. // //
  28. // Local Function Prototypes //
  29. // //
  30. //-------------------------------------------------------------------//
  31. STATIC
  32. NET_API_STATUS
  33. WsOpenRedirector(
  34. VOID
  35. );
  36. STATIC
  37. NET_API_STATUS
  38. WsOpenDgReceiver (
  39. VOID
  40. );
  41. HANDLE
  42. CreateNamedEvent(
  43. LPWSTR lpwEventName
  44. );
  45. BOOL
  46. AgentIsAlive(
  47. VOID
  48. );
  49. //-------------------------------------------------------------------//
  50. // //
  51. // Global variables //
  52. // //
  53. //-------------------------------------------------------------------//
  54. //
  55. // Handle to the Redirector FSD
  56. //
  57. HANDLE WsRedirDeviceHandle = NULL;
  58. HANDLE WsRedirAsyncDeviceHandle = NULL;
  59. BOOLEAN LoadedMRxSmbInsteadOfRdr = FALSE;
  60. //
  61. // Handle to the Datagram Receiver DD
  62. //
  63. HANDLE WsDgReceiverDeviceHandle = NULL;
  64. HANDLE WsDgrecAsyncDeviceHandle = NULL;
  65. HANDLE heventWkssvcToAgentStart = NULL;
  66. HANDLE heventWkssvcToAgentStop = NULL;
  67. HANDLE heventAgentToWkssvc = NULL;
  68. BOOL vfRedirStarted = FALSE;
  69. static WCHAR wszWkssvcToAgentStartEvent[] = L"WkssvcToAgentStartEvent";
  70. static WCHAR wszWkssvcToAgentStopEvent[] = L"WkssvcToAgentStopEvent";
  71. static WCHAR wszAgentToWkssvcEvent[] = L"AgentToWkssvcEvent";
  72. static WCHAR wzAgentExistsEvent[] = L"AgentExistsEvent"; // used to detect if agent exists
  73. NET_API_STATUS
  74. WsDeviceControlGetInfo(
  75. IN DDTYPE DeviceDriverType,
  76. IN HANDLE FileHandle,
  77. IN ULONG DeviceControlCode,
  78. IN PVOID RequestPacket,
  79. IN ULONG RequestPacketLength,
  80. OUT LPBYTE *OutputBuffer,
  81. IN ULONG PreferedMaximumLength,
  82. IN ULONG BufferHintSize,
  83. OUT PULONG_PTR Information OPTIONAL
  84. )
  85. /*++
  86. Routine Description:
  87. This function allocates the buffer and fill it with the information
  88. that is retrieved from the redirector or datagram receiver.
  89. Arguments:
  90. DeviceDriverType - Supplies the value which indicates whether to call
  91. the redirector or the datagram receiver.
  92. FileHandle - Supplies a handle to the file or device of which to get
  93. information about.
  94. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  95. function control code.
  96. RequestPacket - Supplies a pointer to the device request packet.
  97. RrequestPacketLength - Supplies the length of the device request packet.
  98. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  99. which contains the use information requested. This pointer is set to
  100. NULL if return code is not NERR_Success.
  101. PreferedMaximumLength - Supplies the number of bytes of information to
  102. return in the buffer. If this value is MAXULONG, we will try to
  103. return all available information if there is enough memory resource.
  104. BufferHintSize - Supplies the hint size of the output buffer so that the
  105. memory allocated for the initial buffer will most likely be large
  106. enough to hold all requested data.
  107. Information - Returns the information code from the NtFsControlFile or
  108. NtIoDeviceControlFile call.
  109. Return Value:
  110. NET_API_STATUS - NERR_Success or reason for failure.
  111. --*/
  112. {
  113. NET_API_STATUS status;
  114. DWORD OutputBufferLength;
  115. DWORD TotalBytesNeeded = 1;
  116. ULONG OriginalResumeKey;
  117. //
  118. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  119. // the information, regardless of size. Allocate the output buffer of a
  120. // reasonable size and try to use it. If this fails, the Redirector FSD
  121. // will say how much we need to allocate.
  122. //
  123. if (PreferedMaximumLength == MAXULONG) {
  124. OutputBufferLength = (BufferHintSize) ?
  125. BufferHintSize :
  126. INITIAL_ALLOCATION_SIZE;
  127. }
  128. else {
  129. OutputBufferLength = PreferedMaximumLength;
  130. }
  131. OutputBufferLength = ROUND_UP_COUNT(OutputBufferLength, ALIGN_WCHAR);
  132. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  133. return ERROR_NOT_ENOUGH_MEMORY;
  134. }
  135. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  136. if (DeviceDriverType == Redirector) {
  137. PLMR_REQUEST_PACKET Rrp = (PLMR_REQUEST_PACKET) RequestPacket;
  138. OriginalResumeKey = Rrp->Parameters.Get.ResumeHandle;
  139. //
  140. // Make the request of the Redirector
  141. //
  142. status = WsRedirFsControl(
  143. FileHandle,
  144. DeviceControlCode,
  145. Rrp,
  146. RequestPacketLength,
  147. *OutputBuffer,
  148. OutputBufferLength,
  149. Information
  150. );
  151. if (status == ERROR_MORE_DATA) {
  152. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  153. }
  154. }
  155. else {
  156. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  157. OriginalResumeKey = Drrp->Parameters.EnumerateNames.ResumeHandle;
  158. //
  159. // Make the request of the Datagram Receiver
  160. //
  161. status = WsDgReceiverIoControl(
  162. FileHandle,
  163. DeviceControlCode,
  164. Drrp,
  165. RequestPacketLength,
  166. *OutputBuffer,
  167. OutputBufferLength,
  168. NULL
  169. );
  170. if (status == ERROR_MORE_DATA) {
  171. NetpAssert(
  172. FIELD_OFFSET(
  173. LMDR_REQUEST_PACKET,
  174. Parameters.EnumerateNames.TotalBytesNeeded
  175. ) ==
  176. FIELD_OFFSET(
  177. LMDR_REQUEST_PACKET,
  178. Parameters.EnumerateServers.TotalBytesNeeded
  179. )
  180. );
  181. TotalBytesNeeded = Drrp->Parameters.EnumerateNames.TotalBytesNeeded;
  182. }
  183. }
  184. if ((TotalBytesNeeded > OutputBufferLength) &&
  185. (PreferedMaximumLength == MAXULONG)) {
  186. //
  187. // Initial output buffer allocated was too small and we need to return
  188. // all data. First free the output buffer before allocating the
  189. // required size plus a fudge factor just in case the amount of data
  190. // grew.
  191. //
  192. MIDL_user_free(*OutputBuffer);
  193. OutputBufferLength =
  194. ROUND_UP_COUNT((TotalBytesNeeded + FUDGE_FACTOR_SIZE),
  195. ALIGN_WCHAR);
  196. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  197. return ERROR_NOT_ENOUGH_MEMORY;
  198. }
  199. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  200. //
  201. // Try again to get the information from the redirector or datagram
  202. // receiver
  203. //
  204. if (DeviceDriverType == Redirector) {
  205. PLMR_REQUEST_PACKET Rrp = (PLMR_REQUEST_PACKET) RequestPacket;
  206. Rrp->Parameters.Get.ResumeHandle = OriginalResumeKey;
  207. //
  208. // Make the request of the Redirector
  209. //
  210. status = WsRedirFsControl(
  211. FileHandle,
  212. DeviceControlCode,
  213. Rrp,
  214. RequestPacketLength,
  215. *OutputBuffer,
  216. OutputBufferLength,
  217. Information
  218. );
  219. }
  220. else {
  221. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  222. NetpAssert(
  223. FIELD_OFFSET(
  224. LMDR_REQUEST_PACKET,
  225. Parameters.EnumerateNames.ResumeHandle
  226. ) ==
  227. FIELD_OFFSET(
  228. LMDR_REQUEST_PACKET,
  229. Parameters.EnumerateServers.ResumeHandle
  230. )
  231. );
  232. Drrp->Parameters.EnumerateNames.ResumeHandle = OriginalResumeKey;
  233. //
  234. // Make the request of the Datagram Receiver
  235. //
  236. status = WsDgReceiverIoControl(
  237. FileHandle,
  238. DeviceControlCode,
  239. Drrp,
  240. RequestPacketLength,
  241. *OutputBuffer,
  242. OutputBufferLength,
  243. NULL
  244. );
  245. }
  246. }
  247. //
  248. // If not successful in getting any data, or if the caller asked for
  249. // all available data with PreferedMaximumLength == MAXULONG and
  250. // our buffer overflowed, free the output buffer and set its pointer
  251. // to NULL.
  252. //
  253. if ((status != NERR_Success && status != ERROR_MORE_DATA) ||
  254. (TotalBytesNeeded == 0) ||
  255. (PreferedMaximumLength == MAXULONG && status == ERROR_MORE_DATA)) {
  256. MIDL_user_free(*OutputBuffer);
  257. *OutputBuffer = NULL;
  258. //
  259. // PreferedMaximumLength == MAXULONG and buffer overflowed means
  260. // we do not have enough memory to satisfy the request.
  261. //
  262. if (status == ERROR_MORE_DATA) {
  263. status = ERROR_NOT_ENOUGH_MEMORY;
  264. }
  265. }
  266. return status;
  267. }
  268. NET_API_STATUS
  269. WsInitializeRedirector(
  270. VOID
  271. )
  272. /*++
  273. Routine Description:
  274. This routine opens the NT LAN Man redirector. It then reads in
  275. the configuration information and initializes to redirector.
  276. Arguments:
  277. None.
  278. Return Value:
  279. NET_API_STATUS - NERR_Success or reason for failure.
  280. --*/
  281. {
  282. NET_API_STATUS status;
  283. status = WsLoadRedirector();
  284. if (status != NERR_Success && status != ERROR_SERVICE_ALREADY_RUNNING) {
  285. DbgPrint("WKSSVC Load redirector returned %lx\n", status);
  286. return status;
  287. }
  288. //
  289. // Open redirector FSD to get handle to it
  290. //
  291. if ((status = WsOpenRedirector()) != NERR_Success) {
  292. DbgPrint("WKSSVC Open redirector returned %lx\n", status);
  293. return status;
  294. }
  295. // if ((status = WsLoadDriver(L"DGRcvr")) != NERR_Success) {
  296. // return status;
  297. // }
  298. //
  299. // Open datagram receiver FSD to get handle to it.
  300. //
  301. if ((status = WsOpenDgReceiver()) != NERR_Success) {
  302. DbgPrint("WKSSVC Open datagram receiver returned %lx\n", status);
  303. return status;
  304. }
  305. //
  306. // Load redirector and datagram receiver configuration
  307. //
  308. if ((status = WsGetWorkstationConfiguration()) != NERR_Success) {
  309. DbgPrint("WKSSVC Get workstation configuration returned %lx\n", status);
  310. DbgPrint("WKSSVC Shut down the redirector\n");
  311. (void) WsShutdownRedirector();
  312. return status;
  313. }
  314. IF_DEBUG(START) {
  315. DbgPrint("WKSSVC Get workstation configuration returned %lx\n", status);
  316. }
  317. return NERR_Success;
  318. }
  319. STATIC
  320. NET_API_STATUS
  321. WsOpenRedirector(
  322. VOID
  323. )
  324. /*++
  325. Routine Description:
  326. This routine opens the NT LAN Man redirector FSD.
  327. Arguments:
  328. None.
  329. Return Value:
  330. NET_API_STATUS - NERR_Success or reason for failure.
  331. --*/
  332. {
  333. NTSTATUS ntstatus;
  334. UNICODE_STRING DeviceName;
  335. IO_STATUS_BLOCK IoStatusBlock;
  336. OBJECT_ATTRIBUTES ObjectAttributes;
  337. //
  338. // Open the redirector device.
  339. //
  340. RtlInitUnicodeString(&DeviceName,DD_NFS_DEVICE_NAME_U);
  341. InitializeObjectAttributes(
  342. &ObjectAttributes,
  343. &DeviceName,
  344. OBJ_CASE_INSENSITIVE,
  345. NULL,
  346. NULL
  347. );
  348. ntstatus = NtOpenFile(
  349. &WsRedirDeviceHandle,
  350. SYNCHRONIZE,
  351. &ObjectAttributes,
  352. &IoStatusBlock,
  353. FILE_SHARE_VALID_FLAGS,
  354. FILE_SYNCHRONOUS_IO_NONALERT
  355. );
  356. if (NT_SUCCESS(ntstatus)) {
  357. ntstatus = IoStatusBlock.Status;
  358. }
  359. if (! NT_SUCCESS(ntstatus)) {
  360. NetpKdPrint(("[Wksta] NtOpenFile redirector failed: 0x%08lx\n",
  361. ntstatus));
  362. WsRedirDeviceHandle = NULL;
  363. return NetpNtStatusToApiStatus( ntstatus);
  364. }
  365. ntstatus = NtOpenFile(
  366. &WsRedirAsyncDeviceHandle,
  367. FILE_READ_DATA | FILE_WRITE_DATA,
  368. &ObjectAttributes,
  369. &IoStatusBlock,
  370. FILE_SHARE_VALID_FLAGS,
  371. 0L
  372. );
  373. if (NT_SUCCESS(ntstatus)) {
  374. ntstatus = IoStatusBlock.Status;
  375. }
  376. if (! NT_SUCCESS(ntstatus)) {
  377. NetpKdPrint(("[Wksta] NtOpenFile redirector ASYNC failed: 0x%08lx\n",
  378. ntstatus));
  379. WsRedirAsyncDeviceHandle = NULL;
  380. }
  381. return NetpNtStatusToApiStatus(ntstatus);
  382. }
  383. STATIC
  384. NET_API_STATUS
  385. WsOpenDgReceiver(
  386. VOID
  387. )
  388. /*++
  389. Routine Description:
  390. This routine opens the NT LAN Man Datagram Receiver driver.
  391. Arguments:
  392. None.
  393. Return Value:
  394. NET_API_STATUS - NERR_Success or reason for failure.
  395. --*/
  396. {
  397. NTSTATUS ntstatus;
  398. UNICODE_STRING DeviceName;
  399. IO_STATUS_BLOCK IoStatusBlock;
  400. OBJECT_ATTRIBUTES ObjectAttributes;
  401. RtlInitUnicodeString( &DeviceName, DD_BROWSER_DEVICE_NAME_U);
  402. InitializeObjectAttributes(
  403. &ObjectAttributes,
  404. &DeviceName,
  405. OBJ_CASE_INSENSITIVE,
  406. NULL,
  407. NULL
  408. );
  409. if (WsDgReceiverDeviceHandle == NULL) {
  410. //
  411. // Open the BOSWER device. The check is based on the fact that Services process
  412. // does not actually unload the driver when the service is stopped.
  413. //
  414. ntstatus = NtOpenFile(
  415. &WsDgReceiverDeviceHandle,
  416. SYNCHRONIZE,
  417. &ObjectAttributes,
  418. &IoStatusBlock,
  419. FILE_SHARE_VALID_FLAGS,
  420. FILE_SYNCHRONOUS_IO_NONALERT
  421. );
  422. if (NT_SUCCESS(ntstatus)) {
  423. ntstatus = IoStatusBlock.Status;
  424. }
  425. if (! NT_SUCCESS(ntstatus)) {
  426. NetpKdPrint(("[Wksta] NtOpenFile datagram receiver failed: 0x%08lx\n",
  427. ntstatus));
  428. WsDgReceiverDeviceHandle = NULL;
  429. return NetpNtStatusToApiStatus(ntstatus);
  430. }
  431. }
  432. ntstatus = NtOpenFile(
  433. &WsDgrecAsyncDeviceHandle,
  434. FILE_READ_DATA | FILE_WRITE_DATA,
  435. &ObjectAttributes,
  436. &IoStatusBlock,
  437. FILE_SHARE_VALID_FLAGS,
  438. 0L
  439. );
  440. if (NT_SUCCESS(ntstatus)) {
  441. ntstatus = IoStatusBlock.Status;
  442. }
  443. if (! NT_SUCCESS(ntstatus)) {
  444. NetpKdPrint(("[Wksta] NtOpenFile datagram receiver ASYNC failed: 0x%08lx\n",
  445. ntstatus));
  446. WsDgrecAsyncDeviceHandle = NULL;
  447. }
  448. return NetpNtStatusToApiStatus(ntstatus);
  449. }
  450. NET_API_STATUS
  451. WsUnloadDriver(
  452. IN LPWSTR DriverNameString
  453. )
  454. {
  455. ULONG Privileges[1];
  456. LPWSTR DriverRegistryName;
  457. UNICODE_STRING DriverRegistryString;
  458. NET_API_STATUS Status;
  459. NTSTATUS ntstatus;
  460. DriverRegistryName = (LPWSTR) LocalAlloc(
  461. LMEM_FIXED,
  462. (UINT) (sizeof(SERVICE_REGISTRY_KEY) +
  463. (wcslen(DriverNameString) *
  464. sizeof(WCHAR)))
  465. );
  466. if (DriverRegistryName == NULL) {
  467. return ERROR_NOT_ENOUGH_MEMORY;
  468. }
  469. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  470. Status = NetpGetPrivilege(1, Privileges);
  471. if (Status != NERR_Success) {
  472. LocalFree(DriverRegistryName);
  473. return Status;
  474. }
  475. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  476. wcscat(DriverRegistryName, DriverNameString);
  477. RtlInitUnicodeString(&DriverRegistryString, DriverRegistryName);
  478. ntstatus = NtUnloadDriver(&DriverRegistryString);
  479. LocalFree(DriverRegistryName);
  480. NetpReleasePrivilege();
  481. return(WsMapStatus(ntstatus));
  482. }
  483. NET_API_STATUS
  484. WsLoadDriver(
  485. IN LPWSTR DriverNameString
  486. )
  487. {
  488. ULONG Privileges[1];
  489. LPWSTR DriverRegistryName;
  490. UNICODE_STRING DriverRegistryString;
  491. NET_API_STATUS Status;
  492. NTSTATUS ntstatus;
  493. DriverRegistryName = (LPWSTR) LocalAlloc(
  494. LMEM_FIXED,
  495. (UINT) (sizeof(SERVICE_REGISTRY_KEY) +
  496. (wcslen(DriverNameString) *
  497. sizeof(WCHAR)))
  498. );
  499. if (DriverRegistryName == NULL) {
  500. return ERROR_NOT_ENOUGH_MEMORY;
  501. }
  502. Privileges[0] = SE_LOAD_DRIVER_PRIVILEGE;
  503. Status = NetpGetPrivilege(1, Privileges);
  504. if (Status != NERR_Success) {
  505. LocalFree(DriverRegistryName);
  506. return Status;
  507. }
  508. wcscpy(DriverRegistryName, SERVICE_REGISTRY_KEY);
  509. wcscat(DriverRegistryName, DriverNameString);
  510. RtlInitUnicodeString(&DriverRegistryString, DriverRegistryName);
  511. ntstatus = NtLoadDriver(&DriverRegistryString);
  512. NetpReleasePrivilege();
  513. LocalFree(DriverRegistryName);
  514. if (ntstatus != STATUS_SUCCESS && ntstatus != STATUS_IMAGE_ALREADY_LOADED) {
  515. LPWSTR subString[1];
  516. subString[0] = DriverNameString;
  517. WsLogEvent(
  518. NELOG_DriverNotLoaded,
  519. EVENTLOG_ERROR_TYPE,
  520. 1,
  521. subString,
  522. ntstatus
  523. );
  524. }
  525. return(WsMapStatus(ntstatus));
  526. }
  527. NET_API_STATUS
  528. WsShutdownRedirector(
  529. VOID
  530. )
  531. /*++
  532. Routine Description:
  533. This routine close the LAN Man Redirector device.
  534. Arguments:
  535. None.
  536. Return Value:
  537. --*/
  538. {
  539. LMR_REQUEST_PACKET Rrp;
  540. LMDR_REQUEST_PACKET Drp;
  541. NET_API_STATUS Status;
  542. // tell csc to stop doing stuff
  543. if ((Status = WsCSCWantToStopRedir()) != ERROR_SUCCESS)
  544. {
  545. return Status;
  546. }
  547. Rrp.Version = REQUEST_PACKET_VERSION;
  548. Status = WsRedirFsControl(
  549. WsRedirDeviceHandle,
  550. FSCTL_LMR_STOP,
  551. &Rrp,
  552. sizeof(LMR_REQUEST_PACKET),
  553. NULL,
  554. 0,
  555. NULL
  556. );
  557. (void) NtClose(WsRedirDeviceHandle);
  558. WsRedirDeviceHandle = NULL;
  559. if (Status != ERROR_REDIRECTOR_HAS_OPEN_HANDLES) {
  560. //
  561. // After the workstation has been stopped, we want to unload our
  562. // dependant drivers (the RDR and BOWSER).
  563. //
  564. if (WsDgReceiverDeviceHandle != NULL) {
  565. Drp.Version = LMDR_REQUEST_PACKET_VERSION;
  566. (void) WsDgReceiverIoControl(
  567. WsDgReceiverDeviceHandle,
  568. IOCTL_LMDR_STOP,
  569. &Drp,
  570. sizeof(LMDR_REQUEST_PACKET),
  571. NULL,
  572. 0,
  573. NULL
  574. );
  575. (void) NtClose(WsDgReceiverDeviceHandle);
  576. WsDgReceiverDeviceHandle = NULL;
  577. //
  578. // WsUnloadDriver(L"DGRcvr");
  579. //
  580. }
  581. WsUnloadRedirector();
  582. } else {
  583. NET_API_STATUS TempStatus;
  584. HKEY hRedirectorKey;
  585. DWORD FinalStatus;
  586. TempStatus = RegOpenKeyEx(
  587. HKEY_LOCAL_MACHINE,
  588. MRXSMB_REGISTRY_KEY,
  589. 0,
  590. KEY_ALL_ACCESS,
  591. &hRedirectorKey);
  592. if (TempStatus == ERROR_SUCCESS) {
  593. // if this is a controlled shutdown and the driver could not be
  594. // unloaded mark the status in the registry for resumption
  595. FinalStatus = ERROR_SUCCESS;
  596. TempStatus = RegSetValueEx(
  597. hRedirectorKey,
  598. LAST_LOAD_STATUS,
  599. 0,
  600. REG_DWORD,
  601. (PCHAR)&FinalStatus,
  602. sizeof(DWORD));
  603. if (TempStatus == ERROR_SUCCESS) {
  604. NetpKdPrint((PREFIX_WKSTA "New RDR will be loaded on restart\n"));
  605. }
  606. RegCloseKey(hRedirectorKey);
  607. }
  608. }
  609. if (Status != NERR_Success)
  610. {
  611. // NetpAssert(vfRedirStarted == 0);
  612. WsCSCReportStartRedir();
  613. }
  614. return Status;
  615. }
  616. NET_API_STATUS
  617. WsRedirFsControl(
  618. IN HANDLE FileHandle,
  619. IN ULONG RedirControlCode,
  620. IN PLMR_REQUEST_PACKET Rrp,
  621. IN ULONG RrpLength,
  622. IN PVOID SecondBuffer OPTIONAL,
  623. IN ULONG SecondBufferLength,
  624. OUT PULONG_PTR Information OPTIONAL
  625. )
  626. /*++
  627. Routine Description:
  628. Arguments:
  629. FileHandle - Supplies a handle to the file or device on which the service
  630. is being performed.
  631. RedirControlCode - Supplies the NtFsControlFile function code given to
  632. the redirector.
  633. Rrp - Supplies the redirector request packet.
  634. RrpLength - Supplies the length of the redirector request packet.
  635. SecondBuffer - Supplies the second buffer in call to NtFsControlFile.
  636. SecondBufferLength - Supplies the length of the second buffer.
  637. Information - Returns the information field of the I/O status block.
  638. Return Value:
  639. NET_API_STATUS - NERR_Success or reason for failure.
  640. --*/
  641. {
  642. NTSTATUS ntstatus;
  643. IO_STATUS_BLOCK IoStatusBlock;
  644. //
  645. // Send the request to the Redirector FSD.
  646. //
  647. ntstatus = NtFsControlFile(
  648. FileHandle,
  649. NULL,
  650. NULL,
  651. NULL,
  652. &IoStatusBlock,
  653. RedirControlCode,
  654. Rrp,
  655. RrpLength,
  656. SecondBuffer,
  657. SecondBufferLength
  658. );
  659. if (NT_SUCCESS(ntstatus)) {
  660. ntstatus = IoStatusBlock.Status;
  661. }
  662. if (ARGUMENT_PRESENT(Information)) {
  663. *Information = IoStatusBlock.Information;
  664. }
  665. IF_DEBUG(UTIL) {
  666. if (! NT_SUCCESS(ntstatus)) {
  667. NetpKdPrint(("[Wksta] fsctl to redir returns %08lx\n", ntstatus));
  668. }
  669. }
  670. return WsMapStatus(ntstatus);
  671. }
  672. NET_API_STATUS
  673. WsDgReceiverIoControl(
  674. IN HANDLE FileHandle,
  675. IN ULONG DgReceiverControlCode,
  676. IN PLMDR_REQUEST_PACKET Drp,
  677. IN ULONG DrpSize,
  678. IN PVOID SecondBuffer OPTIONAL,
  679. IN ULONG SecondBufferLength,
  680. OUT PULONG_PTR Information OPTIONAL
  681. )
  682. /*++
  683. Routine Description:
  684. Arguments:
  685. FileHandle - Supplies a handle to the file or device on which the service
  686. is being performed.
  687. DgReceiverControlCode - Supplies the NtDeviceIoControlFile function code
  688. given to the datagram receiver.
  689. Drp - Supplies the datagram receiver request packet.
  690. DrpSize - Supplies the length of the datagram receiver request packet.
  691. SecondBuffer - Supplies the second buffer in call to NtDeviceIoControlFile.
  692. SecondBufferLength - Supplies the length of the second buffer.
  693. Information - Returns the information field of the I/O status block.
  694. Return Value:
  695. NET_API_STATUS - NERR_Success or reason for failure.
  696. --*/
  697. {
  698. NTSTATUS ntstatus;
  699. IO_STATUS_BLOCK IoStatusBlock;
  700. if (FileHandle == NULL) {
  701. IF_DEBUG(UTIL) {
  702. NetpKdPrint(("[Wksta] Datagram receiver not implemented\n"));
  703. }
  704. return ERROR_NOT_SUPPORTED;
  705. }
  706. Drp->TransportName.Length = 0;
  707. #ifdef _CAIRO_
  708. RtlInitUnicodeString( &Drp->EmulatedDomainName, NULL );
  709. #endif // _CAIRO_
  710. //
  711. // Send the request to the Datagram Receiver DD.
  712. //
  713. ntstatus = NtDeviceIoControlFile(
  714. FileHandle,
  715. NULL,
  716. NULL,
  717. NULL,
  718. &IoStatusBlock,
  719. DgReceiverControlCode,
  720. Drp,
  721. DrpSize,
  722. SecondBuffer,
  723. SecondBufferLength
  724. );
  725. // as our handles are always async, only if the driver returned pending
  726. // do we copy the status from the iostatusblock
  727. if (ntstatus==STATUS_PENDING) {
  728. ntstatus = IoStatusBlock.Status;
  729. }
  730. if (ARGUMENT_PRESENT(Information)) {
  731. if (NT_SUCCESS(ntstatus))
  732. {
  733. *Information = IoStatusBlock.Information;
  734. }
  735. }
  736. IF_DEBUG(UTIL) {
  737. if (! NT_SUCCESS(ntstatus)) {
  738. NetpKdPrint(("[Wksta] fsctl to dgreceiver returns %08lx\n", ntstatus));
  739. }
  740. }
  741. if (ntstatus == STATUS_TIMEOUT) {
  742. return ERROR_TIMEOUT;
  743. } else {
  744. return WsMapStatus(ntstatus);
  745. }
  746. }
  747. NET_API_STATUS
  748. WsAsyncBindTransport(
  749. IN LPWSTR transportName,
  750. IN DWORD qualityOfService,
  751. IN PLIST_ENTRY pHeader
  752. )
  753. /*++
  754. Routine Description:
  755. This function async binds the specified transport to the redirector
  756. and the datagram receiver.
  757. NOTE: The transport name length pass to the redirector and
  758. datagram receiver is the number of bytes.
  759. Arguments:
  760. transportName - Supplies the name of the transport to bind to.
  761. qualityOfService - Supplies a value which specifies the search
  762. order of the transport with respect to other transports. The
  763. highest value is searched first.
  764. Return Value:
  765. NO_ERROR
  766. --*/
  767. {
  768. NTSTATUS ntStatus;
  769. NET_API_STATUS status;
  770. DWORD size;
  771. DWORD redirSize;
  772. DWORD dgrecSize;
  773. DWORD nameLength;
  774. PWS_BIND pBind;
  775. PWS_BIND_REDIR pBindRedir;
  776. PWS_BIND_DGREC pBindDgrec;
  777. DWORD variablePart;
  778. #ifdef _CAIRO_
  779. LPBYTE Where;
  780. #endif // _CAIRO_
  781. nameLength = STRLEN( transportName);
  782. //
  783. // Make sure *Size-s are PVOID aligned.
  784. //
  785. variablePart = nameLength * sizeof( WCHAR );
  786. variablePart = (variablePart + sizeof(PVOID) - 1) & ~(sizeof(PVOID) - 1);
  787. //
  788. // Then add the fixed part to *Size-s.
  789. //
  790. size = sizeof( WS_BIND) + variablePart;
  791. redirSize = sizeof( WS_BIND_REDIR) + variablePart;
  792. dgrecSize = sizeof( WS_BIND_DGREC) + variablePart
  793. #ifdef _CAIRO_
  794. + WsInfo.WsPrimaryDomainNameLength * sizeof(WCHAR) + sizeof(WCHAR)
  795. #endif // _CAIRO_
  796. ;
  797. pBind = (PVOID) LocalAlloc(
  798. LMEM_ZEROINIT,
  799. (UINT) (size + redirSize + dgrecSize)
  800. );
  801. if ( pBind == NULL) {
  802. NetpKdPrint(( "[Wksta] Failed to allocate pBind memory\n"));
  803. return GetLastError();
  804. }
  805. pBind->TransportNameLength = nameLength * sizeof( WCHAR);
  806. STRCPY( pBind->TransportName, transportName);
  807. pBind->Redir = pBindRedir = (PWS_BIND_REDIR)( (PCHAR)pBind + size);
  808. pBind->Dgrec = pBindDgrec = (PWS_BIND_DGREC)( (PCHAR)pBindRedir + redirSize);
  809. pBindRedir->EventHandle = INVALID_HANDLE_VALUE;
  810. pBindRedir->Bound = FALSE;
  811. pBindRedir->Packet.Version = REQUEST_PACKET_VERSION;
  812. pBindRedir->Packet.Parameters.Bind.QualityOfService = qualityOfService;
  813. pBindRedir->Packet.Parameters.Bind.TransportNameLength =
  814. nameLength * sizeof( WCHAR);
  815. STRCPY( pBindRedir->Packet.Parameters.Bind.TransportName, transportName);
  816. pBindDgrec->EventHandle = INVALID_HANDLE_VALUE;
  817. pBindDgrec->Bound = FALSE;
  818. pBindDgrec->Packet.Version = LMDR_REQUEST_PACKET_VERSION;
  819. pBindDgrec->Packet.Level = 0; // Indicate computername doesn't follow transport name
  820. pBindDgrec->Packet.Parameters.Bind.TransportNameLength =
  821. nameLength * sizeof( WCHAR);
  822. STRCPY( pBindDgrec->Packet.Parameters.Bind.TransportName, transportName);
  823. #ifdef _CAIRO_
  824. Where = ((LPBYTE)&pBindDgrec->Packet.Parameters.Bind.TransportName) +
  825. pBindDgrec->Packet.Parameters.Bind.TransportNameLength;
  826. wcscpy( (LPWSTR) Where, WsInfo.WsPrimaryDomainName);
  827. RtlInitUnicodeString( &pBindDgrec->Packet.EmulatedDomainName, (LPWSTR) Where );
  828. #endif // _CAIRO_
  829. pBindRedir->EventHandle = CreateEvent(
  830. NULL,
  831. TRUE,
  832. FALSE,
  833. NULL
  834. );
  835. if ( pBindRedir->EventHandle == NULL) {
  836. NetpKdPrint(( "[Wksta] Failed to allocate event handle\n"));
  837. status = GetLastError();
  838. goto tail_exit;
  839. }
  840. ntStatus = NtFsControlFile(
  841. WsRedirAsyncDeviceHandle,
  842. pBindRedir->EventHandle,
  843. NULL, // apc routine
  844. NULL, // apc context
  845. &pBindRedir->IoStatusBlock,
  846. FSCTL_LMR_BIND_TO_TRANSPORT, // control code
  847. &pBindRedir->Packet,
  848. sizeof( LMR_REQUEST_PACKET) +
  849. pBindRedir->Packet.Parameters.Bind.TransportNameLength,
  850. NULL,
  851. 0
  852. );
  853. if ( ntStatus != STATUS_PENDING) {
  854. CloseHandle( pBindRedir->EventHandle);
  855. pBindRedir->EventHandle = INVALID_HANDLE_VALUE;
  856. pBindRedir->Bound = NT_SUCCESS( ntStatus );
  857. }
  858. pBindDgrec->EventHandle = CreateEvent(
  859. NULL,
  860. TRUE,
  861. FALSE,
  862. NULL
  863. );
  864. if ( pBindDgrec->EventHandle == NULL) {
  865. status = GetLastError();
  866. goto tail_exit;
  867. }
  868. #ifdef RDR_PNP_POWER
  869. ntStatus = STATUS_SUCCESS;
  870. #else
  871. ntStatus = NtDeviceIoControlFile(
  872. WsDgrecAsyncDeviceHandle,
  873. pBindDgrec->EventHandle,
  874. NULL,
  875. NULL,
  876. &pBindDgrec->IoStatusBlock,
  877. IOCTL_LMDR_BIND_TO_TRANSPORT,
  878. &pBindDgrec->Packet,
  879. dgrecSize - FIELD_OFFSET( WS_BIND_DGREC, Packet ),
  880. NULL,
  881. 0
  882. );
  883. #endif
  884. if ( ntStatus != STATUS_PENDING) {
  885. CloseHandle( pBindDgrec->EventHandle);
  886. pBindDgrec->EventHandle = INVALID_HANDLE_VALUE;
  887. pBindDgrec->Bound = NT_SUCCESS( ntStatus );
  888. }
  889. tail_exit:
  890. InsertTailList( pHeader, &pBind->ListEntry);
  891. return NO_ERROR;
  892. }
  893. NET_API_STATUS
  894. WsBindTransport(
  895. IN LPTSTR TransportName,
  896. IN DWORD QualityOfService,
  897. OUT LPDWORD ErrorParameter OPTIONAL
  898. )
  899. /*++
  900. Routine Description:
  901. This function binds the specified transport to the redirector
  902. and the datagram receiver.
  903. NOTE: The transport name length pass to the redirector and
  904. datagram receiver is the number of bytes.
  905. Arguments:
  906. TransportName - Supplies the name of the transport to bind to.
  907. QualityOfService - Supplies a value which specifies the search
  908. order of the transport with respect to other transports. The
  909. highest value is searched first.
  910. ErrorParameter - Returns the identifier to the invalid parameter if
  911. this function returns ERROR_INVALID_PARAMETER.
  912. Return Value:
  913. NET_API_STATUS - NERR_Success or reason for failure.
  914. --*/
  915. {
  916. NET_API_STATUS status;
  917. DWORD RequestPacketSize;
  918. DWORD TransportNameSize = STRLEN(TransportName) * sizeof(TCHAR);
  919. PLMR_REQUEST_PACKET Rrp;
  920. PLMDR_REQUEST_PACKET Drrp;
  921. #ifdef _CAIRO_
  922. LPBYTE Where;
  923. #endif // _CAIRO_
  924. //
  925. // Size of request packet buffer
  926. //
  927. RequestPacketSize = STRLEN(TransportName) * sizeof(WCHAR) +
  928. #ifdef _CAIRO_
  929. WsInfo.WsPrimaryDomainNameLength*sizeof(WCHAR)+sizeof(WCHAR)+
  930. #endif // _CAIRO_
  931. max(sizeof(LMR_REQUEST_PACKET),
  932. sizeof(LMDR_REQUEST_PACKET));
  933. //
  934. // Allocate memory for redirector/datagram receiver request packet
  935. //
  936. if ((Rrp = (PVOID) LocalAlloc(LMEM_ZEROINIT, (UINT) RequestPacketSize)) == NULL) {
  937. return GetLastError();
  938. }
  939. //
  940. // Get redirector to bind to transport
  941. //
  942. Rrp->Version = REQUEST_PACKET_VERSION;
  943. Rrp->Parameters.Bind.QualityOfService = QualityOfService;
  944. Rrp->Parameters.Bind.TransportNameLength = TransportNameSize;
  945. STRCPY(Rrp->Parameters.Bind.TransportName, TransportName);
  946. if ((status = WsRedirFsControl(
  947. WsRedirDeviceHandle,
  948. FSCTL_LMR_BIND_TO_TRANSPORT,
  949. Rrp,
  950. sizeof(LMR_REQUEST_PACKET) +
  951. Rrp->Parameters.Bind.TransportNameLength,
  952. NULL,
  953. 0,
  954. NULL
  955. )) != NERR_Success) {
  956. if (status == ERROR_INVALID_PARAMETER &&
  957. ARGUMENT_PRESENT(ErrorParameter)) {
  958. IF_DEBUG(INFO) {
  959. NetpKdPrint((
  960. "[Wksta] NetrWkstaTransportAdd: invalid parameter is %lu\n",
  961. Rrp->Parameters.Bind.WkstaParameter));
  962. }
  963. *ErrorParameter = Rrp->Parameters.Bind.WkstaParameter;
  964. }
  965. (void) LocalFree(Rrp);
  966. return status;
  967. }
  968. //
  969. // Get dgrec to bind to transport
  970. //
  971. //
  972. // Make use of the same request packet buffer as FSCtl to
  973. // redirector.
  974. //
  975. Drrp = (PLMDR_REQUEST_PACKET) Rrp;
  976. Drrp->Version = LMDR_REQUEST_PACKET_VERSION;
  977. Drrp->Parameters.Bind.TransportNameLength = TransportNameSize;
  978. STRCPY(Drrp->Parameters.Bind.TransportName, TransportName);
  979. #ifdef _CAIRO_
  980. Where = ((LPBYTE)&Drrp->Parameters.Bind.TransportName) +
  981. Drrp->Parameters.Bind.TransportNameLength;
  982. wcscpy( (LPWSTR) Where, WsInfo.WsPrimaryDomainName);
  983. RtlInitUnicodeString( &Drrp->EmulatedDomainName, (LPWSTR) Where );
  984. #endif // _CAIRO_
  985. status = WsDgReceiverIoControl(
  986. WsDgReceiverDeviceHandle,
  987. IOCTL_LMDR_BIND_TO_TRANSPORT,
  988. Drrp,
  989. RequestPacketSize,
  990. NULL,
  991. 0,
  992. NULL
  993. );
  994. (void) LocalFree(Rrp);
  995. return status;
  996. }
  997. VOID
  998. WsUnbindTransport2(
  999. IN PWS_BIND pBind
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This function unbinds the specified transport from the redirector
  1004. and the datagram receiver.
  1005. Arguments:
  1006. pBind - structure constructed via WsAsyncBindTransport()
  1007. Return Value:
  1008. None.
  1009. --*/
  1010. {
  1011. // NET_API_STATUS status;
  1012. PWS_BIND_REDIR pBindRedir = pBind->Redir;
  1013. PWS_BIND_DGREC pBindDgrec = pBind->Dgrec;
  1014. //
  1015. // Get redirector to unbind from transport
  1016. //
  1017. if ( pBindRedir->Bound == TRUE) {
  1018. pBindRedir->Packet.Parameters.Unbind.TransportNameLength
  1019. = pBind->TransportNameLength;
  1020. memcpy(
  1021. pBindRedir->Packet.Parameters.Unbind.TransportName,
  1022. pBind->TransportName,
  1023. pBind->TransportNameLength
  1024. );
  1025. (VOID)NtFsControlFile(
  1026. WsRedirDeviceHandle,
  1027. NULL,
  1028. NULL, // apc routine
  1029. NULL, // apc context
  1030. &pBindRedir->IoStatusBlock,
  1031. FSCTL_LMR_UNBIND_FROM_TRANSPORT, // control code
  1032. &pBindRedir->Packet,
  1033. sizeof( LMR_REQUEST_PACKET) +
  1034. pBindRedir->Packet.Parameters.Unbind.TransportNameLength,
  1035. NULL,
  1036. 0
  1037. );
  1038. pBindRedir->Bound = FALSE;
  1039. }
  1040. //
  1041. // Get datagram receiver to unbind from transport
  1042. //
  1043. if ( pBindDgrec->Bound == TRUE) {
  1044. pBindDgrec->Packet.Parameters.Unbind.TransportNameLength
  1045. = pBind->TransportNameLength;
  1046. memcpy(
  1047. pBindDgrec->Packet.Parameters.Unbind.TransportName,
  1048. pBind->TransportName,
  1049. pBind->TransportNameLength
  1050. );
  1051. (VOID)NtDeviceIoControlFile(
  1052. WsDgReceiverDeviceHandle,
  1053. NULL,
  1054. NULL, // apc routine
  1055. NULL, // apc context
  1056. &pBindDgrec->IoStatusBlock,
  1057. FSCTL_LMR_UNBIND_FROM_TRANSPORT, // control code
  1058. &pBindDgrec->Packet,
  1059. sizeof( LMR_REQUEST_PACKET) +
  1060. pBindDgrec->Packet.Parameters.Unbind.TransportNameLength,
  1061. NULL,
  1062. 0
  1063. );
  1064. pBindDgrec->Bound = FALSE;
  1065. }
  1066. }
  1067. NET_API_STATUS
  1068. WsUnbindTransport(
  1069. IN LPTSTR TransportName,
  1070. IN DWORD ForceLevel
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. This function unbinds the specified transport from the redirector
  1075. and the datagram receiver.
  1076. NOTE: The transport name length pass to the redirector and
  1077. datagram receiver is the number of bytes.
  1078. Arguments:
  1079. TransportName - Supplies the name of the transport to bind to.
  1080. ForceLevel - Supplies the force level to delete active connections
  1081. on the specified transport.
  1082. Return Value:
  1083. NET_API_STATUS - NERR_Success or reason for failure.
  1084. --*/
  1085. {
  1086. NET_API_STATUS status;
  1087. DWORD RequestPacketSize;
  1088. DWORD TransportNameSize = STRLEN(TransportName) * sizeof(TCHAR);
  1089. PLMR_REQUEST_PACKET Rrp;
  1090. PLMDR_REQUEST_PACKET Drrp;
  1091. #ifdef _CAIRO_
  1092. LPBYTE Where;
  1093. #endif // _CAIRO_
  1094. //
  1095. // Size of request packet buffer
  1096. //
  1097. RequestPacketSize = STRLEN(TransportName) * sizeof(WCHAR) +
  1098. #ifdef _CAIRO_
  1099. WsInfo.WsPrimaryDomainNameLength*sizeof(WCHAR)+sizeof(WCHAR)+
  1100. #endif // _CAIRO_
  1101. max(sizeof(LMR_REQUEST_PACKET),
  1102. sizeof(LMDR_REQUEST_PACKET));
  1103. //
  1104. // Allocate memory for redirector/datagram receiver request packet
  1105. //
  1106. if ((Rrp = (PVOID) LocalAlloc(LMEM_ZEROINIT, (UINT) RequestPacketSize)) == NULL) {
  1107. return GetLastError();
  1108. }
  1109. //
  1110. // Get redirector to unbind from transport
  1111. //
  1112. Rrp->Version = REQUEST_PACKET_VERSION;
  1113. Rrp->Level = ForceLevel;
  1114. Rrp->Parameters.Unbind.TransportNameLength = TransportNameSize;
  1115. STRCPY(Rrp->Parameters.Unbind.TransportName, TransportName);
  1116. if ((status = WsRedirFsControl(
  1117. WsRedirDeviceHandle,
  1118. FSCTL_LMR_UNBIND_FROM_TRANSPORT,
  1119. Rrp,
  1120. sizeof(LMR_REQUEST_PACKET) +
  1121. Rrp->Parameters.Unbind.TransportNameLength,
  1122. NULL,
  1123. 0,
  1124. NULL
  1125. )) != NERR_Success) {
  1126. (void) LocalFree(Rrp);
  1127. return status;
  1128. }
  1129. //
  1130. // Get datagram receiver to unbind from transport
  1131. //
  1132. //
  1133. // Make use of the same request packet buffer as FSCtl to
  1134. // redirector.
  1135. //
  1136. Drrp = (PLMDR_REQUEST_PACKET) Rrp;
  1137. Drrp->Version = LMDR_REQUEST_PACKET_VERSION;
  1138. Drrp->Level = ForceLevel;
  1139. Drrp->Parameters.Unbind.TransportNameLength = TransportNameSize;
  1140. STRCPY(Drrp->Parameters.Unbind.TransportName, TransportName);
  1141. #ifdef _CAIRO_
  1142. Where = ((LPBYTE)&Drrp->Parameters.Unbind.TransportName) +
  1143. Drrp->Parameters.Unbind.TransportNameLength;
  1144. wcscpy( (LPWSTR) Where, WsInfo.WsPrimaryDomainName);
  1145. RtlInitUnicodeString( &Drrp->EmulatedDomainName, (LPWSTR) Where );
  1146. #endif // _CAIRO_
  1147. if ((status = WsDgReceiverIoControl(
  1148. WsDgReceiverDeviceHandle,
  1149. IOCTL_LMDR_UNBIND_FROM_TRANSPORT,
  1150. Drrp,
  1151. RequestPacketSize,
  1152. NULL,
  1153. 0,
  1154. NULL
  1155. )) != NERR_Success) {
  1156. // NTRAID-70693-2/6/2000 davey This is a hack until the bowser supports XNS and LOOP.
  1157. if (status == NERR_UseNotFound) {
  1158. status = NERR_Success;
  1159. }
  1160. }
  1161. (void) LocalFree(Rrp);
  1162. return status;
  1163. }
  1164. NET_API_STATUS
  1165. WsDeleteDomainName(
  1166. IN PLMDR_REQUEST_PACKET Drp,
  1167. IN DWORD DrpSize,
  1168. IN LPTSTR DomainName,
  1169. IN DWORD DomainNameSize
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. This function deletes a domain name from the datagram receiver for
  1174. the current user. It assumes that enough memory is allocate for the
  1175. request packet that is passed in.
  1176. Arguments:
  1177. Drp - Pointer to a datagram receiver request packet with the
  1178. request packet version, and name type initialized.
  1179. DrpSize - Length of datagram receiver request packet in bytes.
  1180. DomainName - Pointer to the domain name to delete.
  1181. DomainNameSize - Length of the domain name in bytes.
  1182. Return Value:
  1183. NET_API_STATUS - NERR_Success or reason for failure.
  1184. --*/
  1185. {
  1186. Drp->Parameters.AddDelName.DgReceiverNameLength = DomainNameSize;
  1187. memcpy(
  1188. (LPBYTE) Drp->Parameters.AddDelName.Name,
  1189. (LPBYTE) DomainName,
  1190. DomainNameSize
  1191. );
  1192. return WsDgReceiverIoControl(
  1193. WsDgReceiverDeviceHandle,
  1194. IOCTL_LMDR_DELETE_NAME,
  1195. Drp,
  1196. DrpSize,
  1197. NULL,
  1198. 0,
  1199. NULL
  1200. );
  1201. }
  1202. NET_API_STATUS
  1203. WsAddDomainName(
  1204. IN PLMDR_REQUEST_PACKET Drp,
  1205. IN DWORD DrpSize,
  1206. IN LPTSTR DomainName,
  1207. IN DWORD DomainNameSize
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This function adds a domain name to the datagram receiver for the
  1212. current user. It assumes that enough memory is allocate for the
  1213. request packet that is passed in.
  1214. Arguments:
  1215. Drp - Pointer to a datagram receiver request packet with the
  1216. request packet version, and name type initialized.
  1217. DrpSize - Length of datagram receiver request packet in bytes.
  1218. DomainName - Pointer to the domain name to delete.
  1219. DomainNameSize - Length of the domain name in bytes.
  1220. Return Value:
  1221. NET_API_STATUS - NERR_Success or reason for failure.
  1222. --*/
  1223. {
  1224. Drp->Parameters.AddDelName.DgReceiverNameLength = DomainNameSize;
  1225. memcpy(
  1226. (LPBYTE) Drp->Parameters.AddDelName.Name,
  1227. (LPBYTE) DomainName,
  1228. DomainNameSize
  1229. );
  1230. return WsDgReceiverIoControl(
  1231. WsDgReceiverDeviceHandle,
  1232. IOCTL_LMDR_ADD_NAME,
  1233. Drp,
  1234. DrpSize,
  1235. NULL,
  1236. 0,
  1237. NULL
  1238. );
  1239. }
  1240. NET_API_STATUS
  1241. WsTryToLoadSmbMiniRedirector(
  1242. VOID
  1243. );
  1244. NET_API_STATUS
  1245. WsLoadRedirector(
  1246. VOID
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. This routine loads rdr.sys or mrxsmb.sys et al depending on whether
  1251. the conditions for loading mrxsmb.sys are met.
  1252. Arguments:
  1253. None.
  1254. Return Value:
  1255. NET_API_STATUS - NERR_Success or reason for failure.
  1256. Notes:
  1257. The new redirector consists of two parts -- the RDBSS (redirected drive buffering
  1258. subsystem ) and the corresponding smb mini redirectors. Only the minirdr is loaded here;
  1259. the minirdr loads the RDBSS itself.
  1260. As a stopgap measure the old redirector is loaded in the event of any problem
  1261. associated with loading the new redirector.
  1262. --*/
  1263. {
  1264. NET_API_STATUS status;
  1265. status = WsTryToLoadSmbMiniRedirector();
  1266. if ((status != ERROR_SUCCESS) &&
  1267. (status != ERROR_SERVICE_ALREADY_RUNNING)) {
  1268. // Either the new redirector load did not succeed or it does not exist.
  1269. // Load the old redirector.
  1270. LoadedMRxSmbInsteadOfRdr = FALSE;
  1271. status = WsLoadDriver(REDIRECTOR);
  1272. }
  1273. return(status);
  1274. }
  1275. VOID
  1276. WsUnloadRedirector(
  1277. VOID
  1278. )
  1279. /*++
  1280. Routine Description:
  1281. This routine unloads the drivers that we loaded above.
  1282. Arguments:
  1283. None.
  1284. Return Value:
  1285. None.
  1286. --*/
  1287. {
  1288. NET_API_STATUS status;
  1289. DWORD NameLength,NameOffset;
  1290. HKEY hRedirectorKey;
  1291. DWORD FinalStatus;
  1292. if (!LoadedMRxSmbInsteadOfRdr) {
  1293. WsUnloadDriver(REDIRECTOR);
  1294. return;
  1295. }
  1296. status = WsUnloadDriver(SMB_MINIRDR);
  1297. if (status == ERROR_SUCCESS) {
  1298. WsUnloadDriver(RDBSS);
  1299. }
  1300. status = RegOpenKeyEx(
  1301. HKEY_LOCAL_MACHINE,
  1302. MRXSMB_REGISTRY_KEY,
  1303. 0,
  1304. KEY_ALL_ACCESS,
  1305. &hRedirectorKey);
  1306. if (status == ERROR_SUCCESS) {
  1307. // if the unloading was successful, reset the LastLoadStatus so that
  1308. // the new redirector will be loaded on the next attempt as well.
  1309. FinalStatus = ERROR_SUCCESS;
  1310. status = RegSetValueEx(
  1311. hRedirectorKey,
  1312. LAST_LOAD_STATUS,
  1313. 0,
  1314. REG_DWORD,
  1315. (PCHAR)&FinalStatus,
  1316. sizeof(DWORD));
  1317. if (status == ERROR_SUCCESS) {
  1318. NetpKdPrint((PREFIX_WKSTA "New RDR will be loaded on restart\n"));
  1319. }
  1320. RegCloseKey(hRedirectorKey);
  1321. }
  1322. return;
  1323. }
  1324. ////////////////////// minirdr stuff
  1325. NET_API_STATUS
  1326. WsTryToLoadSmbMiniRedirector(
  1327. VOID
  1328. )
  1329. /*++
  1330. Routine Description:
  1331. This routine loads rdr.sys or mrxsmb.sys et al depending on whether
  1332. the conditions for loading mrxsmb.sys are met.
  1333. Arguments:
  1334. None.
  1335. Return Value:
  1336. NET_API_STATUS - NERR_Success or reason for failure.
  1337. Notes:
  1338. The new redirector consists of two parts -- the RDBSS (redirected drive buffering
  1339. subsystem ) and the corresponding smb mini redirectors. Only the minirdr is loaded here;
  1340. the minirdr loads the RDBSS itself.
  1341. As a stopgap measure the old redirector is loaded in the event of any problem
  1342. associated with loading the new redirector.
  1343. --*/
  1344. {
  1345. NET_API_STATUS status;
  1346. ULONG Attributes;
  1347. DWORD ValueType;
  1348. DWORD ValueSize;
  1349. DWORD NameLength,NameOffset;
  1350. HKEY hRedirectorKey;
  1351. DWORD FinalStatus; // Temporary till the new rdr is the default
  1352. DWORD LastLoadStatus;
  1353. //try to open the minirdr's registry key....if fails GET OUT IMMEDIATELY!!!!
  1354. status = RegOpenKeyEx(
  1355. HKEY_LOCAL_MACHINE,
  1356. MRXSMB_REGISTRY_KEY,
  1357. 0,
  1358. KEY_ALL_ACCESS,
  1359. &hRedirectorKey);
  1360. if (status != ERROR_SUCCESS) {
  1361. return(status);
  1362. } else {
  1363. status = WsLoadDriver(RDBSS);
  1364. if ((status == ERROR_SUCCESS) || (status == ERROR_SERVICE_ALREADY_RUNNING)) {
  1365. status = WsLoadDriver(SMB_MINIRDR);
  1366. if (status == ERROR_SUCCESS) {
  1367. LoadedMRxSmbInsteadOfRdr = TRUE;
  1368. } else if (status == ERROR_SERVICE_ALREADY_RUNNING) {
  1369. NetpKdPrint((PREFIX_WKSTA "Reactivating Previously Loaded Service\n"));
  1370. LoadedMRxSmbInsteadOfRdr = TRUE;
  1371. status = ERROR_SUCCESS;
  1372. } else {
  1373. // error loading the minirdr
  1374. //WsUnloadDriver(RDBSS);
  1375. NetpKdPrint((PREFIX_WKSTA "Error Loading MRxSmb\n"));
  1376. }
  1377. }
  1378. // NetpKdPrint((PREFIX_WKSTA "New redirector(RDR2) load status %lx\n",status));
  1379. }
  1380. // Close the handle to the registry key irrespective of the result.
  1381. RegCloseKey(hRedirectorKey);
  1382. return(status);
  1383. }
  1384. NET_API_STATUS
  1385. WsCSCReportStartRedir(
  1386. VOID
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. Arguments:
  1391. None.
  1392. Return Value:
  1393. NET_API_STATUS - NERR_Success or reason for failure.
  1394. Notes:
  1395. --*/
  1396. {
  1397. NET_API_STATUS status = ERROR_SUCCESS;
  1398. DWORD dwError = ERROR_GEN_FAILURE;
  1399. // NetpKdPrint(("Wkssvc: Reporting redir start \n"));
  1400. // ensure that there are named autoreset events
  1401. if (!heventWkssvcToAgentStart)
  1402. {
  1403. NetpAssert(!heventAgentToWkssvc);
  1404. heventWkssvcToAgentStart = CreateNamedEvent(wszWkssvcToAgentStartEvent);
  1405. if (!heventWkssvcToAgentStart)
  1406. {
  1407. dwError = GetLastError();
  1408. NetpKdPrint(("Wkssvc: Failed to create heventWkssvcToAgentStart, error = %d\n", dwError));
  1409. goto bailout;
  1410. }
  1411. heventWkssvcToAgentStop = CreateNamedEvent(wszWkssvcToAgentStopEvent);
  1412. if (!heventWkssvcToAgentStop)
  1413. {
  1414. dwError = GetLastError();
  1415. NetpKdPrint(("Wkssvc: Failed to create heventWkssvcToAgentStop, error = %d\n", dwError));
  1416. goto bailout;
  1417. }
  1418. heventAgentToWkssvc = CreateNamedEvent(wszAgentToWkssvcEvent);
  1419. if (!heventAgentToWkssvc)
  1420. {
  1421. dwError = GetLastError();
  1422. NetpKdPrint(("Wkssvc: Failed to create heventAgentToWkssvc, error = %d\n", dwError));
  1423. goto bailout;
  1424. }
  1425. }
  1426. // NetpAssert(!vfRedirStarted);
  1427. if (!vfRedirStarted)
  1428. {
  1429. SetEvent(heventWkssvcToAgentStart);
  1430. vfRedirStarted = TRUE;
  1431. // NetpKdPrint(("Wkssvc: Reported redir start \n"));
  1432. }
  1433. dwError = ERROR_SUCCESS;
  1434. bailout:
  1435. if (dwError != ERROR_SUCCESS)
  1436. {
  1437. if (heventWkssvcToAgentStart)
  1438. {
  1439. CloseHandle(heventWkssvcToAgentStart);
  1440. heventWkssvcToAgentStart = NULL;
  1441. }
  1442. if (heventWkssvcToAgentStop)
  1443. {
  1444. CloseHandle(heventWkssvcToAgentStop);
  1445. heventWkssvcToAgentStop = NULL;
  1446. }
  1447. if (heventAgentToWkssvc)
  1448. {
  1449. CloseHandle(heventAgentToWkssvc);
  1450. heventAgentToWkssvc = NULL;
  1451. }
  1452. NetpKdPrint(("Wkssvc: Failed to report redir start error code=%d\n", dwError));
  1453. }
  1454. return (dwError);
  1455. }
  1456. NET_API_STATUS
  1457. WsCSCWantToStopRedir(
  1458. VOID
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. Arguments:
  1463. None.
  1464. Return Value:
  1465. NET_API_STATUS - NERR_Success or reason for failure.
  1466. Notes:
  1467. --*/
  1468. {
  1469. NET_API_STATUS status = ERROR_SUCCESS;
  1470. DWORD dwError;
  1471. // NetpKdPrint(("Wkssvc: Asking agent to stop, so the redir can be stopped\n"));
  1472. if (!vfRedirStarted)
  1473. {
  1474. NetpKdPrint(("Wkssvc: getting a stop without a start\n"));
  1475. return ERROR_GEN_FAILURE;
  1476. }
  1477. if (!heventWkssvcToAgentStop)
  1478. {
  1479. NetpAssert(!heventWkssvcToAgentStart && !heventAgentToWkssvc);
  1480. NetpKdPrint(("Wkssvc: Need events for redir stop\n"));
  1481. return ERROR_GEN_FAILURE;
  1482. }
  1483. // Bleed the event
  1484. WaitForSingleObject(heventAgentToWkssvc, 0);
  1485. if (!AgentIsAlive())
  1486. {
  1487. // the agent isn't up
  1488. // no need to issue stop
  1489. NetpKdPrint(("Wkssvc: Agent not alive\n"));
  1490. }
  1491. else
  1492. {
  1493. // NetpKdPrint(("Wkssvc: Agent Alive\n"));
  1494. // agent is up
  1495. // tell him to stop
  1496. SetEvent(heventWkssvcToAgentStop);
  1497. // Wait some reasonable time to see if he stops
  1498. dwError = WaitForSingleObject(heventAgentToWkssvc, CSC_WAIT_TIME);
  1499. if (dwError!=WAIT_OBJECT_0)
  1500. {
  1501. HANDLE hT[2];
  1502. NetpKdPrint(("Wkssvc: Agent didn't disbale CSC in %d milli-seconds\n", CSC_WAIT_TIME));
  1503. // let us try to reset our event in a way that we don't just miss the agent
  1504. hT[0] = heventWkssvcToAgentStop;
  1505. hT[1] = heventAgentToWkssvc;
  1506. dwError = WaitForMultipleObjects(2, hT, FALSE, 0);
  1507. // if we fired because of 1, then the agent gave us an ack
  1508. // otherwise the stop event would be reset and the agent won't get confused
  1509. if (dwError == WAIT_OBJECT_0+1)
  1510. {
  1511. // NetpKdPrint(("Wkssvc: Agent disabled CSC\n"));
  1512. vfRedirStarted = FALSE;
  1513. }
  1514. ResetEvent(heventWkssvcToAgentStop);
  1515. }
  1516. else
  1517. {
  1518. // NetpKdPrint(("Wkssvc: Agent disabled CSC\n"));
  1519. vfRedirStarted = FALSE;
  1520. }
  1521. }
  1522. return status;
  1523. }
  1524. HANDLE
  1525. CreateNamedEvent(
  1526. LPWSTR lpwEventName
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. Arguments:
  1531. lpwEventName Name of the event to create.
  1532. Return Value:
  1533. Notes:
  1534. --*/
  1535. {
  1536. HANDLE hevent = NULL;
  1537. hevent = CreateEvent(NULL, FALSE, FALSE, lpwEventName);
  1538. return hevent;
  1539. }
  1540. BOOL
  1541. AgentIsAlive(
  1542. VOID
  1543. )
  1544. /*++
  1545. Routine Description:
  1546. Arguments:
  1547. None.
  1548. Return Value:
  1549. TRUE if agent is alive, FALSE otherwise
  1550. Notes:
  1551. The named event is created by the agent thread when it comes up.
  1552. --*/
  1553. {
  1554. HANDLE hT;
  1555. BOOL fRet = FALSE;
  1556. // see whether the agent has already created the event
  1557. hT = OpenEvent(SYNCHRONIZE, FALSE, wzAgentExistsEvent);
  1558. if (hT != NULL)
  1559. {
  1560. CloseHandle(hT);
  1561. fRet = TRUE;
  1562. }
  1563. else
  1564. {
  1565. NetpKdPrint(("Wkssvc: Agent error = %d\n", GetLastError()));
  1566. }
  1567. return (fRet);
  1568. }