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.

2656 lines
68 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. rdpdr.cpp
  5. Abstract:
  6. This module implements the driver initialization for the RDP redirector,
  7. and the dispatch routines for the master device object. The master
  8. device object mostly ignores real I/O operations
  9. Environment:
  10. Kernel mode
  11. --*/
  12. #include "precomp.hxx"
  13. #define TRC_FILE "rdpdr"
  14. #include "trc.h"
  15. #include "ntddmup.h"
  16. #include "TSQPublic.h"
  17. HANDLE DrSystemProcessId;
  18. PSECURITY_DESCRIPTOR DrAdminSecurityDescriptor = NULL;
  19. ULONG DrSecurityDescriptorLength = 0;
  20. extern ULONG DebugBreakOnEntry;
  21. //
  22. // Default USBMON Port Write Size. Need to keep it under 64k for
  23. // 16-bit clients ... otherwise, the go off the end of a segment.
  24. //
  25. ULONG PrintPortWriteSize;
  26. ULONG PrintPortWriteSizeDefault = 63000; // bytes
  27. //
  28. // Maximum numer of TS worker threads
  29. //
  30. #define MAX_WORKER_THREADS_COUNT 5
  31. ULONG MaxWorkerThreadsDefault = MAX_WORKER_THREADS_COUNT;
  32. ULONG MaxWorkerThreads = MAX_WORKER_THREADS_COUNT;
  33. // The TS Worker Queue pointer
  34. PVOID RDPDR_TsQueue = NULL;
  35. //
  36. // Configure Devices to send IO packets to client at low priority.
  37. //
  38. ULONG DeviceLowPrioSendFlags;
  39. ULONG DeviceLowPrioSendFlagsDefault = DEVICE_LOWPRIOSEND_PRINTERS;
  40. extern "C" BOOLEAN RxForceQFIPassThrough;
  41. NTSTATUS DrCreateSCardDevice(SmartPtr<DrSession> &Session, PV_NET_ROOT pVNetRoot,
  42. SmartPtr<DrDevice> &Device);
  43. //
  44. // This is the minirdr dispatch table. It is initialized by DrInitializeTables.
  45. // This table will be used by the wrapper to call into this minirdr
  46. //
  47. struct _MINIRDR_DISPATCH DrDispatch;
  48. #if DBG
  49. UCHAR IrpNames[IRP_MJ_MAXIMUM_FUNCTION + 1][40] = {
  50. "IRP_MJ_CREATE ",
  51. "IRP_MJ_CREATE_NAMED_PIPE ",
  52. "IRP_MJ_CLOSE ",
  53. "IRP_MJ_READ ",
  54. "IRP_MJ_WRITE ",
  55. "IRP_MJ_QUERY_INFORMATION ",
  56. "IRP_MJ_SET_INFORMATION ",
  57. "IRP_MJ_QUERY_EA ",
  58. "IRP_MJ_SET_EA ",
  59. "IRP_MJ_FLUSH_BUFFERS ",
  60. "IRP_MJ_QUERY_VOLUME_INFORMATION",
  61. "IRP_MJ_SET_VOLUME_INFORMATION ",
  62. "IRP_MJ_DIRECTORY_CONTROL ",
  63. "IRP_MJ_FILE_SYSTEM_CONTROL ",
  64. "IRP_MJ_DEVICE_CONTROL ",
  65. "IRP_MJ_INTERNAL_DEVICE_CONTROL ",
  66. "IRP_MJ_SHUTDOWN ",
  67. "IRP_MJ_LOCK_CONTROL ",
  68. "IRP_MJ_CLEANUP ",
  69. "IRP_MJ_CREATE_MAILSLOT ",
  70. "IRP_MJ_QUERY_SECURITY ",
  71. "IRP_MJ_SET_SECURITY ",
  72. "IRP_MJ_POWER ",
  73. "IRP_MJ_SYSTEM_CONTROL ",
  74. "IRP_MJ_DEVICE_CHANGE ",
  75. "IRP_MJ_QUERY_QUOTA ",
  76. "IRP_MJ_SET_QUOTA ",
  77. "IRP_MJ_PNP "
  78. };
  79. #endif // DBG
  80. //
  81. // Pointer to the device Object for this minirdr. Since the device object is created
  82. // by the wrapper when this minirdr registers, this pointer is initialized in the
  83. // DriverEntry routine below (see RxRegisterMinirdr)
  84. //
  85. PRDBSS_DEVICE_OBJECT DrDeviceObject = NULL;
  86. PRDBSS_DEVICE_OBJECT DrPortDeviceObject = NULL;
  87. DrSessionManager *Sessions = NULL;
  88. //
  89. // A global spinlock
  90. //
  91. KSPIN_LOCK DrSpinLock;
  92. KIRQL DrOldIrql;
  93. //
  94. // A global mutex
  95. //
  96. FAST_MUTEX DrMutex;
  97. //
  98. // Global Registry Path for RDPDR.SYS
  99. //
  100. UNICODE_STRING DrRegistryPath;
  101. //
  102. // The following enumerated values signify the current state of the minirdr
  103. // initialization. With the aid of this state information, it is possible
  104. // to determine which resources to deallocate, whether deallocation comes
  105. // as a result of a normal stop/unload, or as the result of an exception
  106. //
  107. typedef enum tagDrInitStates {
  108. DrUninitialized,
  109. DrRegistered,
  110. DrInitialized
  111. } DrInitStates;
  112. //
  113. // function prototypes
  114. //
  115. extern "C" {
  116. NTSTATUS
  117. DrInitializeTables(
  118. void
  119. );
  120. NTSTATUS
  121. CreateAdminSecurityDescriptor(
  122. VOID
  123. );
  124. NTSTATUS
  125. BuildDeviceAcl(
  126. OUT PACL *DeviceAcl
  127. );
  128. NTSTATUS
  129. DriverEntry(
  130. IN PDRIVER_OBJECT DriverObject,
  131. IN PUNICODE_STRING RegistryPath
  132. );
  133. NTSTATUS
  134. DrPeekDispatch (
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PIRP Irp
  137. );
  138. VOID
  139. DrUninitialize(
  140. IN PDRIVER_OBJECT DriverObject,
  141. IN DrInitStates DrInitState
  142. );
  143. NTSTATUS
  144. DrLoadRegistrySettings (
  145. IN PCWSTR RegistryPath
  146. );
  147. NTSTATUS
  148. DrStart(
  149. PRX_CONTEXT RxContext,
  150. IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
  151. );
  152. NTSTATUS
  153. DrStop(
  154. PRX_CONTEXT RxContext,
  155. IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
  156. );
  157. NTSTATUS
  158. DrDeallocateForFcb(
  159. IN OUT PMRX_FCB pFcb
  160. );
  161. NTSTATUS
  162. ObGetObjectSecurity(
  163. IN PVOID Object,
  164. OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
  165. OUT PBOOLEAN MemoryAllocated
  166. );
  167. VOID
  168. ObReleaseObjectSecurity(
  169. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  170. IN BOOLEAN MemoryAllocated
  171. );
  172. NTSTATUS
  173. DriverEntry(
  174. IN PDRIVER_OBJECT DriverObject,
  175. IN PUNICODE_STRING RegistryPath
  176. );
  177. };
  178. BOOL GetDeviceFromRxContext(PRX_CONTEXT RxContext, SmartPtr<DrDevice> &Device);
  179. #ifdef ALLOC_PRAGMA
  180. #pragma alloc_text(INIT, DriverEntry)
  181. #endif
  182. WCHAR DrDriverName[] = RDPDR_DEVICE_NAME_U;
  183. WCHAR DrPortDriverName[] = RDPDR_PORT_DEVICE_NAME_U;
  184. NTSTATUS
  185. DriverEntry(
  186. IN PDRIVER_OBJECT DriverObject,
  187. IN PUNICODE_STRING RegistryPath
  188. )
  189. /*++
  190. Routine Description:
  191. This is the initialization routine for the RDP mini redirector
  192. Arguments:
  193. DriverObject - Pointer to driver object created by the system.
  194. Return Value:
  195. RXSTATUS - The function value is the final status from the initialization
  196. operation.
  197. --*/
  198. {
  199. NTSTATUS Status;
  200. UNICODE_STRING RdpDrName;
  201. UNICODE_STRING RdpDrPortName;
  202. PDEVICE_OBJECT RdpDrDevice;
  203. DrInitStates DrInitState = DrUninitialized;
  204. PRX_CONTEXT RxContext;
  205. PWCHAR path;
  206. BEGIN_FN("DriverEntry");
  207. #ifdef MONOLITHIC_MINIRDR
  208. Status = RxDriverEntry(DriverObject, RegistryPath);
  209. TRC_NRM((TB, "BackFromInitWrapper %08lx", Status));
  210. if (!NT_SUCCESS(Status)) {
  211. TRC_ERR((TB, "Wrapper failed to initialize. "
  212. "Status = %08lx", Status));
  213. DbgPrint("rdpdr.sys erroring out (#1)\n");
  214. DbgBreakPoint();
  215. return Status;
  216. }
  217. #endif
  218. //
  219. // Copy the registry path for RDPDR.SYS.
  220. //
  221. path = (PWCHAR)new(NonPagedPool) WCHAR[RegistryPath->Length + 1];
  222. if (!path) {
  223. TRC_ERR((TB, "DR:Failed to allocate registry path %Wz",
  224. RegistryPath));
  225. DbgPrint("rdpdr.sys erroring out (#2)\n");
  226. DbgBreakPoint();
  227. Status = STATUS_INSUFFICIENT_RESOURCES;
  228. return (Status);
  229. }
  230. RtlZeroMemory(path, RegistryPath->Length+sizeof(WCHAR));
  231. RtlMoveMemory(path, RegistryPath->Buffer, RegistryPath->Length);
  232. DrRegistryPath.Length = RegistryPath->Length;
  233. DrRegistryPath.MaximumLength = RegistryPath->Length+sizeof(WCHAR);
  234. DrRegistryPath.Buffer = path;
  235. //
  236. // Load registry settings.
  237. //
  238. DrLoadRegistrySettings(path);
  239. #if DBG
  240. if (DebugBreakOnEntry) {
  241. DbgBreakPoint();
  242. }
  243. #endif
  244. CodePageConversionInitialize();
  245. // Initialize the client list
  246. KeInitializeSpinLock(&DrSpinLock);
  247. // Initialize the mutex object for device I/O transaction exchange
  248. ExInitializeFastMutex(&DrMutex);
  249. if (InitializeKernelUtilities()) {
  250. Status = STATUS_SUCCESS;
  251. } else {
  252. Status = STATUS_INSUFFICIENT_RESOURCES;
  253. DbgPrint("rdpdr.sys erroring out (#3)\n");
  254. DbgBreakPoint();
  255. }
  256. if (NT_SUCCESS(Status)) {
  257. Sessions = new(NonPagedPool) DrSessionManager;
  258. if (Sessions != NULL) {
  259. Status = STATUS_SUCCESS;
  260. TRC_NRM((TB, "Created DrSessionManager"));
  261. } else {
  262. TRC_ERR((TB, "Unable to create DrSessionManager"));
  263. Status = STATUS_INSUFFICIENT_RESOURCES;
  264. DbgPrint("rdpdr.sys erroring out (#4)\n");
  265. DbgBreakPoint();
  266. }
  267. }
  268. if (NT_SUCCESS(Status)) {
  269. RtlInitUnicodeString(&RdpDrPortName, DrPortDriverName);
  270. // Create the port device object.
  271. Status = IoCreateDevice(DriverObject,
  272. 0,
  273. &RdpDrPortName,
  274. FILE_DEVICE_NETWORK_REDIRECTOR,
  275. 0,
  276. FALSE,
  277. (PDEVICE_OBJECT *)(&DrPortDeviceObject));
  278. }
  279. else {
  280. TRC_ERR((TB, "IoCreateDevice failed: %08lx", Status ));
  281. DbgPrint("rdpdr.sys erroring out (#5)\n");
  282. DbgBreakPoint();
  283. return Status;
  284. }
  285. if (NT_SUCCESS(Status)) {
  286. //
  287. // Register the RdpDr with the connection engine. Registration
  288. // makes the connection engine aware of the device name, driver
  289. // object, and other characteristics. If registration is successful,
  290. // a new device object is returned
  291. //
  292. // The name of the device is L"\\Device\\RdpDr"
  293. //
  294. RtlInitUnicodeString(&RdpDrName, DrDriverName);
  295. TRC_DBG((TB, "Registering minirdr"));
  296. Status = RxRegisterMinirdr(
  297. &DrDeviceObject, // where the new device object goes
  298. DriverObject, // the Driver Object to register
  299. &DrDispatch, // the dispatch table for this driver
  300. RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS,
  301. &RdpDrName, // the device name for this minirdr
  302. 0, // IN ULONG DeviceExtensionSize,
  303. FILE_DEVICE_NETWORK_FILE_SYSTEM, // In DEVICE_TYPE DeviceType
  304. 0 // IN ULONG DeviceCharacteristics
  305. );
  306. }
  307. if (NT_SUCCESS(Status)) {
  308. PSECURITY_DESCRIPTOR RdpDrSD = NULL;
  309. BOOLEAN memoryAllocated = FALSE;
  310. TRC_NRM((TB, "RxRegisterMinirdr succeeded."));
  311. //
  312. // Get the SD for the rdpdr device object.
  313. // Apply the same SD to the rdp port device object.
  314. //
  315. if (NT_SUCCESS(ObGetObjectSecurity(DrDeviceObject,
  316. &RdpDrSD,
  317. &memoryAllocated))) {
  318. if (!NT_SUCCESS(ObSetSecurityObjectByPointer((PDEVICE_OBJECT)DrPortDeviceObject,
  319. DACL_SECURITY_INFORMATION,
  320. RdpDrSD
  321. ))) {
  322. //
  323. // We will ignore the error.
  324. //
  325. TRC_ERR((TB, "ObSetSecurityObjectByPointer failed: 0x%08lx", Status ));
  326. }
  327. ObReleaseObjectSecurity(RdpDrSD, memoryAllocated);
  328. }
  329. else {
  330. //
  331. // We will ignore the error. Just log the error
  332. //
  333. TRC_ERR((TB, "ObGetObjectSecurity failed: 0x%08lx", Status ));
  334. }
  335. //
  336. // After this we can't just return, some uninitialization is
  337. // needed if we fail or unload
  338. //
  339. DrInitState = DrRegistered;
  340. Status = CreateAdminSecurityDescriptor();
  341. } else {
  342. TRC_ERR((TB, "RxRegisterMinirdr failed: %08lx", Status ));
  343. DbgPrint("rdpdr.sys erroring out (#6)\n");
  344. DbgBreakPoint();
  345. if (DrPortDeviceObject) {
  346. IoDeleteDevice((PDEVICE_OBJECT) DrPortDeviceObject);
  347. DrPortDeviceObject = NULL;
  348. }
  349. return Status;
  350. }
  351. if (NT_SUCCESS(Status)) {
  352. //
  353. // Build the dispatch tables for the minirdr
  354. //
  355. Status = DrInitializeTables();
  356. } else {
  357. TRC_ERR((TB, "CreateAdminSecurityDescriptor failed: 0x%08lx", Status ));
  358. DbgPrint("rdpdr.sys erroring out (#7)\n");
  359. DbgBreakPoint();
  360. }
  361. //
  362. // Initialize our TS worker queue module.
  363. //
  364. TRC_NRM((TB, "RDPDR: Initialize TS Worker Queue"));
  365. RDPDR_TsQueue = TSInitQueue( TSQUEUE_OWN_THREAD,
  366. MaxWorkerThreads,
  367. (PDEVICE_OBJECT)DrDeviceObject );
  368. if ( RDPDR_TsQueue == NULL) {
  369. TRC_ERR((TB, "RDPDR: Failed to initialize the TS Queue"));
  370. DbgPrint("rdpdr.sys erroring out (#8)\n");
  371. Status = STATUS_INSUFFICIENT_RESOURCES;
  372. }
  373. if (NT_SUCCESS(Status)) {
  374. //
  375. // Setup Unload Routine
  376. //
  377. DriverObject->DriverUnload = DrUnload;
  378. //
  379. // Set up the PnP AddDevice entry point.
  380. //
  381. DriverObject->DriverExtension->AddDevice = RDPDRPNP_PnPAddDevice;
  382. //
  383. // setup the DriverDispatch for people who come in here directly
  384. // ....like the browser
  385. //
  386. {
  387. ULONG i;
  388. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  389. {
  390. DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)DrPeekDispatch;
  391. }
  392. }
  393. DrSystemProcessId = PsGetCurrentProcessId();
  394. } else {
  395. DbgPrint("rdpdr.sys erroring out (#9)\n");
  396. DbgBreakPoint();
  397. DrUninitialize(DriverObject, DrInitState);
  398. }
  399. return Status;
  400. }
  401. VOID
  402. DrUninitialize(
  403. IN PDRIVER_OBJECT DriverObject,
  404. IN DrInitStates DrInitState
  405. )
  406. /*++
  407. Routine Description:
  408. This routine does the common uninit work
  409. Arguments:
  410. DrInitState - tells how far we got into the intialization
  411. Return Value:
  412. None
  413. --*/
  414. {
  415. PRX_CONTEXT RxContext;
  416. NTSTATUS Status;
  417. BEGIN_FN("DrUninitialize");
  418. PAGED_CODE();
  419. RxContext = RxCreateRxContext(
  420. NULL,
  421. DrDeviceObject,
  422. RX_CONTEXT_FLAG_IN_FSP);
  423. if (RxContext != NULL) {
  424. Status = RxStopMinirdr(
  425. RxContext,
  426. &RxContext->PostRequest);
  427. RxDereferenceAndDeleteRxContext(RxContext);
  428. } else {
  429. Status = STATUS_INSUFFICIENT_RESOURCES;
  430. }
  431. CodePageConversionCleanup();
  432. if (DrAdminSecurityDescriptor) {
  433. delete DrAdminSecurityDescriptor;
  434. DrAdminSecurityDescriptor = NULL;
  435. DrSecurityDescriptorLength = 0;
  436. }
  437. if (Sessions != NULL) {
  438. delete Sessions;
  439. Sessions = NULL;
  440. }
  441. if (DrRegistryPath.Buffer != NULL) {
  442. delete DrRegistryPath.Buffer;
  443. DrRegistryPath.Buffer = NULL;
  444. }
  445. //
  446. // Delete the TS Queue
  447. //
  448. if ( RDPDR_TsQueue != NULL) {
  449. if (TSDeleteQueue( RDPDR_TsQueue ) != STATUS_SUCCESS) {
  450. TRC_ERR((TB, "RDPDR: TsDeleteQueue Failed"));
  451. }
  452. }
  453. UninitializeKernelUtilities();
  454. switch (DrInitState) {
  455. case DrInitialized:
  456. #ifdef MONOLITHIC_MINIRDR
  457. RxUnload(DriverObject);
  458. #endif
  459. case DrRegistered:
  460. RxUnregisterMinirdr(DrDeviceObject);
  461. }
  462. if (DrPortDeviceObject) {
  463. IoDeleteDevice((PDEVICE_OBJECT) DrPortDeviceObject);
  464. DrPortDeviceObject = NULL;
  465. }
  466. }
  467. VOID
  468. DrUnload(
  469. IN PDRIVER_OBJECT DriverObject
  470. )
  471. /*++
  472. Routine Description:
  473. This is the dispatch routine for Unload.
  474. Arguments:
  475. DriverObject - Pointer to the driver object controling all of the
  476. devices.
  477. Return Value:
  478. None.
  479. --*/
  480. {
  481. BEGIN_FN("DrUnload");
  482. PAGED_CODE();
  483. TRC_NRM((TB, "DriverObject =%p", DriverObject));
  484. DrUninitialize(DriverObject, DrInitialized);
  485. TRC_NRM((TB, "MRxIfsUnload exit: DriverObject =%p",
  486. DriverObject));
  487. }
  488. NTSTATUS
  489. DrFlush(
  490. IN OUT PRX_CONTEXT RxContext
  491. )
  492. /*++
  493. Routine Description:
  494. This is the dispatch routine for flush operations.
  495. Arguments:
  496. RxContext - RDBSS context structure for our mini-redir
  497. Return Value:
  498. Could return status success, cancelled, or pending.
  499. --*/
  500. {
  501. BEGIN_FN("DrFlush");
  502. return STATUS_SUCCESS;
  503. }
  504. NTSTATUS
  505. DrWrite(
  506. IN OUT PRX_CONTEXT RxContext
  507. )
  508. /*++
  509. Routine Description:
  510. This is the dispatch routine for write operations.
  511. Arguments:
  512. RxContext - RDBSS context structure for our mini-redir
  513. Return Value:
  514. Could return status success, cancelled, or pending.
  515. --*/
  516. {
  517. SmartPtr<DrDevice> Device;
  518. BEGIN_FN("DrWrite");
  519. TRC_NRM((TB, "DrWrite"));
  520. GetDeviceFromRxContext(RxContext, Device);
  521. return Device->Write(RxContext);
  522. }
  523. NTSTATUS
  524. DrRead(
  525. IN OUT PRX_CONTEXT RxContext
  526. )
  527. /*++
  528. Routine Description:
  529. This is the dispatch routine for read operations.
  530. Arguments:
  531. RxContext - RDBSS context structure for our mini-redir
  532. Return Value:
  533. Could return status success, cancelled, or pending.
  534. --*/
  535. {
  536. SmartPtr<DrDevice> Device;
  537. BEGIN_FN("DrRead");
  538. TRC_NRM((TB, "DrRead"));
  539. GetDeviceFromRxContext(RxContext, Device);
  540. return Device->Read(RxContext);
  541. }
  542. NTSTATUS
  543. DrIoControl(
  544. IN OUT PRX_CONTEXT RxContext
  545. )
  546. /*++
  547. Routine Description:
  548. This is the dispatch routine for IoControl operations.
  549. Arguments:
  550. RxContext - RDBSS context structure for our mini-redir
  551. Return Value:
  552. Could return status success, cancelled, or pending.
  553. --*/
  554. {
  555. SmartPtr<DrDevice> Device;
  556. BEGIN_FN("DrIoControl");
  557. TRC_NRM((TB, "DrIoControl"));
  558. if (GetDeviceFromRxContext(RxContext, Device))
  559. return Device->IoControl(RxContext);
  560. else
  561. return STATUS_UNSUCCESSFUL;
  562. }
  563. NTSTATUS
  564. DrShouldTryToCollapseThisOpen(
  565. IN OUT PRX_CONTEXT RxContext
  566. )
  567. /*++
  568. Routine Description:
  569. This routine determines if the mini knows of a good reason not
  570. to try collapsing on this open.
  571. Arguments:
  572. RxContext - Context for the operation
  573. Return Value:
  574. NTSTATUS - The return status for the operation
  575. SUCCESS --> okay to try collapse
  576. other (MORE_PROCESSING_REQUIRED) --> dont collapse
  577. --*/
  578. {
  579. NTSTATUS Status = STATUS_SUCCESS;
  580. RxCaptureFcb;
  581. BEGIN_FN("DrShouldTryToCollapseThisOpen");
  582. PAGED_CODE();
  583. TRC_NRM((TB, "DrShouldTryToCollapseThisOpen not implemented"));
  584. return STATUS_NOT_IMPLEMENTED;
  585. }
  586. ULONG
  587. DrExtendForNonCache(
  588. IN OUT struct _RX_CONTEXT * RxContext,
  589. IN PLARGE_INTEGER pNewFileSize,
  590. OUT PLARGE_INTEGER pNewAllocationSize
  591. )
  592. /*++
  593. Routine Description:
  594. This routine handles network requests to extend the file for noncached IO. since the write
  595. itself will extend the file, we can pretty much just get out quickly.
  596. Arguments:
  597. RxContext - the RDBSS context
  598. Return Value:
  599. RXSTATUS - The return status for the operation
  600. --*/
  601. {
  602. NTSTATUS Status = STATUS_SUCCESS;
  603. pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
  604. return (ULONG)Status;
  605. }
  606. NTSTATUS
  607. DrTruncate(
  608. IN OUT PRX_CONTEXT RxContext
  609. )
  610. /*++
  611. Routine Description:
  612. This routine determines Truncate operation
  613. Arguments:
  614. RxContext - Context for the operation
  615. Return Value:
  616. NTSTATUS - The return status for the operation
  617. --*/
  618. {
  619. BEGIN_FN("DrTruncate");
  620. TRC_ERR((TB, "DrTruncate not implemented"));
  621. return STATUS_NOT_IMPLEMENTED;
  622. }
  623. NTSTATUS DrCreate(IN OUT PRX_CONTEXT RxContext)
  624. /*++
  625. Routine Description:
  626. Opens a file (or device) across the network
  627. Arguments:
  628. RxContext - Context for the operation
  629. Return Value:
  630. Could return status success, cancelled, or pending.
  631. --*/
  632. {
  633. NTSTATUS Status;
  634. RxCaptureFcb;
  635. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  636. PMRX_NET_ROOT NetRoot = RxContext->Create.pNetRoot;
  637. PMRX_V_NET_ROOT VNetRoot = RxContext->Create.pVNetRoot;
  638. SmartPtr<DrSession> Session;
  639. DrDevice *pDevice;
  640. SmartPtr<DrDevice> Device, DeviceNew;
  641. BEGIN_FN("DrCreate");
  642. TRC_NRM((TB, "DrCreate"));
  643. //
  644. // Make sure the device is still enabled, Protect the
  645. // VNetRoot Context (the DeviceEntry) with the device list
  646. // SpinLock because we may change it
  647. //
  648. DrAcquireSpinLock();
  649. Device = (DrDevice *)VNetRoot->Context;
  650. ASSERT(Device != NULL);
  651. DrReleaseSpinLock();
  652. //
  653. // Make sure it's okay to access the Client at this time
  654. // This is an optimization, we don't need to acquire the spin lock,
  655. // because it is okay if we're not, we'll just catch it later
  656. //
  657. Session = Device->GetSession();
  658. ASSERT(Session != NULL);
  659. if (!Session->IsConnected() && (Device->GetDeviceType() != RDPDR_DTYP_SMARTCARD)) {
  660. TRC_ALT((TB, "Tried to open client device while not "
  661. "connected. State: %ld", Session->GetState()));
  662. return STATUS_DEVICE_NOT_CONNECTED;
  663. }
  664. //
  665. // We leave the SpinLock after we get our reference to the device. It could
  666. // change while we're gone, but since everything is reference counted it
  667. // is safe to put the correct pointer in later
  668. //
  669. if (!Device->IsAvailable()) {
  670. TRC_ALT((TB, "Tried to open client device which is not "
  671. "available. "));
  672. if (Device->GetDeviceType() == RDPDR_DTYP_SMARTCARD &&
  673. !Session->FindDeviceByDosName((UCHAR *)DR_SMARTCARD_SUBSYSTEM,
  674. DeviceNew, TRUE)) {
  675. Status = DrCreateSCardDevice(Session, NULL, DeviceNew);
  676. if (Status != STATUS_SUCCESS) {
  677. return STATUS_DEVICE_NOT_CONNECTED;
  678. }
  679. }
  680. if (Device->GetDeviceType() == RDPDR_DTYP_SMARTCARD ||
  681. Session->FindDeviceById(Device->GetDeviceId(), DeviceNew, TRUE)) {
  682. //
  683. // There's a new DeviceEntry for this device. Replace the old
  684. // one in the VNetRoot with this one. We also need an extra
  685. // reference to stick in the fobx so we can track whether
  686. // this particular open is using an old DeviceEntry or a new
  687. // one
  688. //
  689. // Put it in the netroot, safely swapping in and manually
  690. // bumping the reference count up going in and down going out
  691. DeviceNew->AddRef();
  692. DrAcquireSpinLock();
  693. pDevice = (DrDevice *)VNetRoot->Context;
  694. VNetRoot->Context = (DrDevice *)DeviceNew;
  695. DrReleaseSpinLock();
  696. #if DBG
  697. pDevice->_VNetRoot = NULL;
  698. #endif
  699. pDevice->Release();
  700. pDevice = NULL;
  701. Device = DeviceNew;
  702. } else {
  703. //
  704. // The device is disabled, but we didn't find a shiny new
  705. // version with which to replace it. Leave the icky old disabled
  706. // one there so we know what to look for later, and return the
  707. // device not connected error.
  708. //
  709. return STATUS_DEVICE_NOT_CONNECTED;
  710. }
  711. }
  712. return Device->Create(RxContext);
  713. }
  714. BOOL GetDeviceFromRxContext(PRX_CONTEXT RxContext, SmartPtr<DrDevice> &Device)
  715. {
  716. BOOL rc = FALSE;
  717. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  718. PMRX_V_NET_ROOT VNetRoot;
  719. BEGIN_FN("GetDeviceFromRxContext");
  720. if (SrvOpen == NULL) {
  721. goto Exit;
  722. }
  723. VNetRoot= SrvOpen->pVNetRoot;
  724. if (VNetRoot == NULL) {
  725. goto Exit;
  726. }
  727. DrAcquireSpinLock();
  728. Device = (DrDevice *)VNetRoot->Context;
  729. DrReleaseSpinLock();
  730. ASSERT(Device != NULL);
  731. rc = TRUE;
  732. Exit:
  733. return rc;
  734. }
  735. NTSTATUS DrCloseSrvOpen(IN OUT PRX_CONTEXT RxContext)
  736. /*++
  737. Routine Description:
  738. This is the dispatch routine for close operations.
  739. Arguments:
  740. RxContext - RDBSS context structure for our mini-redir
  741. Return Value:
  742. Could return status success, cancelled, or pending.
  743. --*/
  744. {
  745. SmartPtr<DrDevice> Device;
  746. BEGIN_FN("DrCloseSrvOpen");
  747. TRC_NRM((TB, "DrCloseSrvOpen"));
  748. GetDeviceFromRxContext(RxContext, Device);
  749. return Device->Close(RxContext);
  750. }
  751. NTSTATUS DrCleanupFobx(IN OUT PRX_CONTEXT RxContext)
  752. /*++
  753. Routine Description:
  754. This is the dispatch routine for cleaning up Fobx.
  755. Arguments:
  756. RxContext - RDBSS context structure for our mini-redir
  757. Return Value:
  758. Could return status success, cancelled, or pending.
  759. --*/
  760. {
  761. RxCaptureFobx;
  762. BEGIN_FN("DrCleanupFobx");
  763. TRC_NRM((TB, "DrCleanupFobx"));
  764. return STATUS_SUCCESS;
  765. }
  766. NTSTATUS DrCleanup(IN OUT PRX_CONTEXT RxContext)
  767. /*++
  768. Routine Description:
  769. This is the dispatch routine for cleanup operations.
  770. Arguments:
  771. RxContext - RDBSS context structure for our mini-redir
  772. Return Value:
  773. Could return status success, cancelled, or pending.
  774. --*/
  775. {
  776. SmartPtr<DrDevice> Device;
  777. BEGIN_FN("DrCleanup");
  778. TRC_NRM((TB, "DrCleanup"));
  779. GetDeviceFromRxContext(RxContext, Device);
  780. return Device->Cleanup(RxContext);
  781. }
  782. NTSTATUS
  783. DrQueryDirectory(
  784. IN OUT PRX_CONTEXT RxContext
  785. )
  786. /*++
  787. Routine Description:
  788. This is the dispatch routine for Query Direcotry information.
  789. Arguments:
  790. RxContext - RDBSS context structure for our mini-redir
  791. Return Value:
  792. Could return status success, cancelled, or pending.
  793. --*/
  794. {
  795. SmartPtr<DrDevice> Device;
  796. BEGIN_FN("DrQueryDirecotry");
  797. TRC_NRM((TB, "DrQueryDirectory"));
  798. GetDeviceFromRxContext(RxContext, Device);
  799. return Device->QueryDirectory(RxContext);
  800. }
  801. NTSTATUS
  802. DrQueryVolumeInfo(
  803. IN OUT PRX_CONTEXT RxContext
  804. )
  805. /*++
  806. Routine Description:
  807. This is the dispatch routine for Query Volume Information.
  808. Arguments:
  809. RxContext - RDBSS context structure for our mini-redir
  810. Return Value:
  811. Could return status success, cancelled, or pending.
  812. --*/
  813. {
  814. SmartPtr<DrDevice> Device;
  815. BEGIN_FN("DrQueryVolumeInfo");
  816. TRC_NRM((TB, "DrQueryVolumeInfo"));
  817. GetDeviceFromRxContext(RxContext, Device);
  818. return Device->QueryVolumeInfo(RxContext);
  819. }
  820. NTSTATUS
  821. DrSetVolumeInfo(
  822. IN OUT PRX_CONTEXT RxContext
  823. )
  824. /*++
  825. Routine Description:
  826. This is the dispatch routine for Set Volume Information.
  827. Arguments:
  828. RxContext - RDBSS context structure for our mini-redir
  829. Return Value:
  830. Could return status success, cancelled, or pending.
  831. --*/
  832. {
  833. SmartPtr<DrDevice> Device;
  834. BEGIN_FN("DrSetVolumeInfo");
  835. TRC_NRM((TB, "DrSetVolumeInfo"));
  836. GetDeviceFromRxContext(RxContext, Device);
  837. return Device->SetVolumeInfo(RxContext);
  838. }
  839. NTSTATUS
  840. DrQuerySdInfo(
  841. IN OUT PRX_CONTEXT RxContext
  842. )
  843. /*++
  844. Routine Description:
  845. This is the dispatch routine for Query Security Information.
  846. Arguments:
  847. RxContext - RDBSS context structure for our mini-redir
  848. Return Value:
  849. Could return status success, cancelled, or pending.
  850. --*/
  851. {
  852. SmartPtr<DrDevice> Device;
  853. BEGIN_FN("DrQuerySdInfo");
  854. TRC_NRM((TB, "DrQuerySdInfo"));
  855. GetDeviceFromRxContext(RxContext, Device);
  856. return Device->QuerySdInfo(RxContext);
  857. }
  858. NTSTATUS
  859. DrSetSdInfo(
  860. IN OUT PRX_CONTEXT RxContext
  861. )
  862. /*++
  863. Routine Description:
  864. This is the dispatch routine for Set Security Information.
  865. Arguments:
  866. RxContext - RDBSS context structure for our mini-redir
  867. Return Value:
  868. Could return status success, cancelled, or pending.
  869. --*/
  870. {
  871. SmartPtr<DrDevice> Device;
  872. BEGIN_FN("DrSetSdInfo");
  873. TRC_NRM((TB, "DrSetSdInfo"));
  874. GetDeviceFromRxContext(RxContext, Device);
  875. return Device->SetSdInfo(RxContext);
  876. }
  877. NTSTATUS
  878. DrQueryFileInfo(
  879. IN OUT PRX_CONTEXT RxContext
  880. )
  881. /*++
  882. Routine Description:
  883. This is the dispatch routine for Query File Information.
  884. Arguments:
  885. RxContext - RDBSS context structure for our mini-redir
  886. Return Value:
  887. Could return status success, cancelled, or pending.
  888. --*/
  889. {
  890. SmartPtr<DrDevice> Device;
  891. BEGIN_FN("DrQueryFileInfo");
  892. TRC_NRM((TB, "DrQueryFileInfo"));
  893. GetDeviceFromRxContext(RxContext, Device);
  894. return Device->QueryFileInfo(RxContext);
  895. }
  896. NTSTATUS
  897. DrSetFileInfo(
  898. IN OUT PRX_CONTEXT RxContext
  899. )
  900. /*++
  901. Routine Description:
  902. This is the dispatch routine for SetFileInformation.
  903. Arguments:
  904. RxContext - RDBSS context structure for our mini-redir
  905. Return Value:
  906. Could return status success, cancelled, or pending.
  907. --*/
  908. {
  909. SmartPtr<DrDevice> Device;
  910. BEGIN_FN("DrSetFileInfo");
  911. TRC_NRM((TB, "DrSetFileInfo"));
  912. GetDeviceFromRxContext(RxContext, Device);
  913. return Device->SetFileInfo(RxContext);
  914. }
  915. NTSTATUS
  916. DrSetFileInfoAtCleanUp(
  917. IN OUT PRX_CONTEXT RxContext
  918. )
  919. /*++
  920. Routine Description:
  921. This is the dispatch routine for SetFileInformationAtCleanUp.
  922. Arguments:
  923. DeviceObject - Pointer to the device object for this device
  924. Irp - Pointer to the IRP for the current request
  925. Return Value:
  926. Could return status success, cancelled, or pending.
  927. --*/
  928. {
  929. BEGIN_FN("DrSetFileInfoAtCleanUp");
  930. TRC_NRM((TB, "DrSetFileInfoAtCleanUp"));
  931. return STATUS_SUCCESS;
  932. }
  933. NTSTATUS
  934. DrLocks(
  935. IN OUT PRX_CONTEXT RxContext
  936. )
  937. /*++
  938. Routine Description:
  939. This is the dispatch routine for file locking.
  940. Arguments:
  941. RxContext - RDBSS context structure for our mini-redir
  942. Return Value:
  943. Could return status success, cancelled, or pending.
  944. --*/
  945. {
  946. SmartPtr<DrDevice> Device;
  947. BEGIN_FN("DrLocks");
  948. TRC_NRM((TB, "DrLocks"));
  949. GetDeviceFromRxContext(RxContext, Device);
  950. return Device->Locks(RxContext);
  951. }
  952. NTSTATUS
  953. DrIsLockRealizable(
  954. IN OUT PMRX_FCB pFcb,
  955. IN PLARGE_INTEGER ByteOffset,
  956. IN PLARGE_INTEGER Length,
  957. IN ULONG LowIoLockFlags
  958. )
  959. /*++
  960. Routine Description:
  961. This is the dispatch routine for IsLockRealizable.
  962. Arguments:
  963. Return Value:
  964. Could return status success, cancelled, or pending.
  965. --*/
  966. {
  967. BEGIN_FN("DrIsLockRealizable");
  968. TRC_NRM((TB, "DrIsLockRealizable"));
  969. //
  970. // TODO: We do not support share locks for win9x clients
  971. // Can we just return success here and then fail on the
  972. // client share lock function?
  973. //
  974. #if 0
  975. if (!FlagOn(LowIoLockFlags,LOWIO_LOCKSFLAG_EXCLUSIVELOCK)) {
  976. return STATUS_NOT_SUPPORTED;
  977. }
  978. #endif
  979. return STATUS_SUCCESS;
  980. }
  981. NTSTATUS
  982. DrIsValidDirectory(
  983. IN OUT PRX_CONTEXT RxContext,
  984. IN PUNICODE_STRING DirectoryName
  985. )
  986. /*++
  987. Routine Description:
  988. This is the dispatch routine for IsValidDirectory.
  989. Arguments:
  990. RxContext - RDBSS context structure for our mini-redir
  991. DirectoryName - name of directory to verify its validity
  992. Return Value:
  993. Could return status success, cancelled, or pending.
  994. --*/
  995. {
  996. BEGIN_FN("DrIsValidDirectory");
  997. TRC_NRM((TB, "DrIsValidDirectory"));
  998. //
  999. // TODO: Always return success for now. Need to verify later
  1000. //
  1001. return STATUS_SUCCESS;
  1002. }
  1003. NTSTATUS
  1004. DrNotifyChangeDirectory(
  1005. IN OUT PRX_CONTEXT RxContext
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. This is the dispatch routine for DrNotifyChangeDirectory.
  1010. Arguments:
  1011. RxContext - RDBSS context structure for our mini-redir
  1012. Return Value:
  1013. Could return status success, cancelled, or pending.
  1014. --*/
  1015. {
  1016. SmartPtr<DrDevice> Device;
  1017. BEGIN_FN("DrNotifyChangeDirectory");
  1018. TRC_NRM((TB, "DrNotifyChangeDirectory"));
  1019. GetDeviceFromRxContext(RxContext, Device);
  1020. return Device->NotifyChangeDirectory(RxContext);
  1021. }
  1022. NTSTATUS
  1023. DrInitializeTables(
  1024. void
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This routine sets up the rdp redirector dispatch vector and also calls
  1029. to initialize any other tables needed.
  1030. Return Value:
  1031. NTSTATUS - The return status for the operation
  1032. --*/
  1033. {
  1034. BEGIN_FN("DrInitializeTables");
  1035. //
  1036. // Build the local minirdr dispatch table and initialize
  1037. //
  1038. ZeroAndInitializeNodeType(&DrDispatch, RDBSS_NTC_MINIRDR_DISPATCH,
  1039. sizeof(MINIRDR_DISPATCH));
  1040. //
  1041. // redirector extension sizes and allocation policies.
  1042. //
  1043. // REVIEW: wtf?
  1044. DrDispatch.MRxFlags = (RDBSS_MANAGE_FCB_EXTENSION |
  1045. RDBSS_MANAGE_SRV_OPEN_EXTENSION |
  1046. RDBSS_MANAGE_FOBX_EXTENSION);
  1047. DrDispatch.MRxSrvCallSize = 0;
  1048. DrDispatch.MRxNetRootSize = 0;
  1049. DrDispatch.MRxVNetRootSize = 0;
  1050. DrDispatch.MRxFcbSize = 0; // sizeof(MRX_SMB_FCB);
  1051. DrDispatch.MRxSrvOpenSize = 0; // sizeof(MRX_SMB_SRV_OPEN);
  1052. DrDispatch.MRxFobxSize = 0; // sizeof(MRX_SMB_FOBX);
  1053. // Transport update handler
  1054. // REVIEW: How do we indicate we have our own dedicated transport?
  1055. //MRxIfsDispatch.MRxTransportUpdateHandler = MRxIfsTransportUpdateHandler;
  1056. // Mini redirector cancel routine ..
  1057. DrDispatch.MRxCancel = NULL;
  1058. //
  1059. // Mini redirector Start/Stop. Each mini-rdr can be started or stopped
  1060. // while the others continue to operate.
  1061. //
  1062. DrDispatch.MRxStart = DrStart;
  1063. DrDispatch.MRxStop = DrStop;
  1064. DrDispatch.MRxDevFcbXXXControlFile = DrDevFcbXXXControlFile;
  1065. //
  1066. // Mini redirector name resolution.
  1067. //
  1068. DrDispatch.MRxCreateSrvCall = DrCreateSrvCall;
  1069. DrDispatch.MRxSrvCallWinnerNotify = DrSrvCallWinnerNotify;
  1070. DrDispatch.MRxCreateVNetRoot = DrCreateVNetRoot;
  1071. DrDispatch.MRxUpdateNetRootState = DrUpdateNetRootState;
  1072. DrDispatch.MRxExtractNetRootName = DrExtractNetRootName;
  1073. DrDispatch.MRxFinalizeSrvCall = DrFinalizeSrvCall;
  1074. DrDispatch.MRxFinalizeNetRoot = DrFinalizeNetRoot;
  1075. DrDispatch.MRxFinalizeVNetRoot = DrFinalizeVNetRoot;
  1076. //
  1077. // File System Object Creation/Deletion.
  1078. //
  1079. DrDispatch.MRxCreate = DrCreate;
  1080. //
  1081. // TODO: Need to implement this for file system redirect caching
  1082. //
  1083. DrDispatch.MRxShouldTryToCollapseThisOpen = DrShouldTryToCollapseThisOpen;
  1084. //DrDispatch.MRxCollapseOpen = MRxIfsCollapseOpen;
  1085. //DrDispatch.MRxExtendForCache = MRxIfsExtendFile;
  1086. DrDispatch.MRxExtendForNonCache = DrExtendForNonCache;
  1087. DrDispatch.MRxTruncate = DrTruncate; //MRxIfsTruncate;
  1088. DrDispatch.MRxCleanupFobx = DrCleanupFobx;
  1089. DrDispatch.MRxCloseSrvOpen = DrCloseSrvOpen;
  1090. DrDispatch.MRxFlush = DrFlush;
  1091. DrDispatch.MRxForceClosed = DrForceClosed;
  1092. DrDispatch.MRxDeallocateForFcb = DrDeallocateForFcb;
  1093. DrDispatch.MRxDeallocateForFobx = DrDeallocateForFobx;
  1094. DrDispatch.MRxIsLockRealizable = DrIsLockRealizable;
  1095. //
  1096. // File System Objects query/Set
  1097. //
  1098. DrDispatch.MRxQueryDirectory = DrQueryDirectory; //MRxIfsQueryDirectory;
  1099. DrDispatch.MRxQueryVolumeInfo = DrQueryVolumeInfo; //MRxIfsQueryVolumeInformation;
  1100. DrDispatch.MRxSetVolumeInfo = DrSetVolumeInfo; //MRxSmbSetVolumeInformation;
  1101. //DrDispatch.MRxQueryEaInfo = MRxIfsQueryEaInformation;
  1102. //DrDispatch.MRxSetEaInfo = MRxIfsSetEaInformation;
  1103. DrDispatch.MRxQuerySdInfo = DrQuerySdInfo; //MRxIfsQuerySecurityInformation;
  1104. DrDispatch.MRxSetSdInfo = DrSetSdInfo; //MRxIfsSetSecurityInformation;
  1105. //MRxSmbDispatch.MRxQueryQuotaInfo = MRxSmbQueryQuotaInformation;
  1106. //MRxSmbDispatch.MRxSetQuotaInfo = MRxSmbSetQuotaInformation;
  1107. DrDispatch.MRxQueryFileInfo = DrQueryFileInfo; //MRxIfsQueryFileInformation;
  1108. DrDispatch.MRxSetFileInfo = DrSetFileInfo; //MRxIfsSetFileInformation;
  1109. DrDispatch.MRxSetFileInfoAtCleanup = DrSetFileInfoAtCleanUp; //MRxIfsSetFileInformationAtCleanup;
  1110. DrDispatch.MRxIsValidDirectory = DrIsValidDirectory;
  1111. //
  1112. // Buffering state change
  1113. //
  1114. //DrDispatch.MRxComputeNewBufferingState = MRxIfsComputeNewBufferingState;
  1115. //
  1116. // File System Object I/O
  1117. //
  1118. DrDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = DrRead;
  1119. DrDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = DrWrite;
  1120. DrDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = DrLocks;
  1121. DrDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = DrLocks;
  1122. DrDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = DrLocks;
  1123. DrDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = DrLocks;
  1124. DrDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = DrIoControl; //MRxIfsFsCtl;
  1125. DrDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = DrIoControl;
  1126. DrDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = DrNotifyChangeDirectory; //MRxIfsNotifyChangeDirectory;
  1127. //
  1128. // Miscellanous - buffering
  1129. //
  1130. //DrDispatch.MRxCompleteBufferingStateChangeRequest = MRxIfsCompleteBufferingStateChangeRequest;
  1131. return STATUS_SUCCESS;
  1132. }
  1133. BOOLEAN
  1134. DrIsAdminIoRequest(
  1135. PIRP Irp,
  1136. PIO_STACK_LOCATION IrpSp
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. (Lifted from AFD - AfdPerformSecurityCheck)
  1141. Compares security context of the endpoint creator to that
  1142. of the administrator and local system.
  1143. Arguments:
  1144. Irp - Pointer to I/O request packet.
  1145. IrpSp - pointer to the IO stack location to use for this request.
  1146. Return Value:
  1147. TRUE - the socket creator has admin or local system privilige
  1148. FALSE - the socket creator is just a plain user
  1149. --*/
  1150. {
  1151. BOOLEAN accessGranted;
  1152. PACCESS_STATE accessState;
  1153. PIO_SECURITY_CONTEXT securityContext;
  1154. PPRIVILEGE_SET privileges = NULL;
  1155. ACCESS_MASK grantedAccess;
  1156. PGENERIC_MAPPING GenericMapping;
  1157. ACCESS_MASK AccessMask = GENERIC_ALL;
  1158. NTSTATUS Status;
  1159. BEGIN_FN("DrIsAdminIoRequest");
  1160. ASSERT(Irp != NULL);
  1161. ASSERT(IrpSp != NULL);
  1162. ASSERT(IrpSp->MajorFunction == IRP_MJ_CREATE);
  1163. //
  1164. // Enable access to all the globally defined SIDs
  1165. //
  1166. GenericMapping = IoGetFileObjectGenericMapping();
  1167. RtlMapGenericMask( &AccessMask, GenericMapping );
  1168. securityContext = IrpSp->Parameters.Create.SecurityContext;
  1169. ASSERT(securityContext != NULL);
  1170. accessState = securityContext->AccessState;
  1171. SeLockSubjectContext(&accessState->SubjectSecurityContext);
  1172. TRC_ASSERT(DrAdminSecurityDescriptor != NULL,
  1173. (TB, "DrAdminSecurityDescriptor != NULL"));
  1174. accessGranted = SeAccessCheck(
  1175. DrAdminSecurityDescriptor,
  1176. &accessState->SubjectSecurityContext,
  1177. TRUE,
  1178. AccessMask,
  1179. 0,
  1180. &privileges,
  1181. IoGetFileObjectGenericMapping(),
  1182. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  1183. ? UserMode
  1184. : Irp->RequestorMode),
  1185. &grantedAccess,
  1186. &Status
  1187. );
  1188. if (privileges) {
  1189. (VOID) SeAppendPrivileges(
  1190. accessState,
  1191. privileges
  1192. );
  1193. SeFreePrivileges(privileges);
  1194. }
  1195. if (accessGranted) {
  1196. accessState->PreviouslyGrantedAccess |= grantedAccess;
  1197. accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  1198. ASSERT (NT_SUCCESS (Status));
  1199. }
  1200. else {
  1201. ASSERT (!NT_SUCCESS (Status));
  1202. }
  1203. SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
  1204. return accessGranted;
  1205. }
  1206. BOOLEAN
  1207. DrIsSystemProcessRequest(
  1208. PIRP Irp,
  1209. PIO_STACK_LOCATION IrpSp
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. Checks to see if the IRP originated from a system process.
  1214. Arguments:
  1215. Irp - Pointer to I/O request packet.
  1216. IrpSp - pointer to the IO stack location to use for this request.
  1217. Return Value:
  1218. TRUE if the IRP originated from a system process. FALSE, otherwise.
  1219. --*/
  1220. {
  1221. PACCESS_STATE accessState;
  1222. PIO_SECURITY_CONTEXT securityContext;
  1223. PACCESS_TOKEN accessToken;
  1224. PTOKEN_USER userId = NULL;
  1225. BOOLEAN result = FALSE;
  1226. NTSTATUS status = STATUS_SUCCESS;
  1227. PSID systemSid;
  1228. BEGIN_FN("DrIsSystemProcessRequest");
  1229. TRC_NRM((TB, "DrIsSystemProcessRequest called"));
  1230. ASSERT(Irp != NULL);
  1231. ASSERT(IrpSp != NULL);
  1232. ASSERT(IrpSp->MajorFunction == IRP_MJ_CREATE);
  1233. securityContext = IrpSp->Parameters.Create.SecurityContext;
  1234. ASSERT(securityContext != NULL);
  1235. //
  1236. // Get the well-known system SID.
  1237. //
  1238. systemSid = (PSID)new(PagedPool) BYTE[RtlLengthRequiredSid(1)];
  1239. if (systemSid) {
  1240. SID_IDENTIFIER_AUTHORITY identifierAuthority = SECURITY_NT_AUTHORITY;
  1241. *(RtlSubAuthoritySid(systemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID;
  1242. status = RtlInitializeSid(systemSid, &identifierAuthority, (UCHAR)1);
  1243. }
  1244. else {
  1245. TRC_ERR((TB, "Can't allocate %ld bytes for system SID.",
  1246. RtlLengthRequiredSid(1)));
  1247. status = STATUS_INSUFFICIENT_RESOURCES;
  1248. }
  1249. //
  1250. // Get the non-impersonated, primary token for the IRP request.
  1251. //
  1252. accessState = securityContext->AccessState;
  1253. accessToken = accessState->SubjectSecurityContext.PrimaryToken;
  1254. //
  1255. // We got the system SID. Now compare the caller's SID.
  1256. //
  1257. if (NT_SUCCESS(status) && accessToken){
  1258. //
  1259. // Get the user ID associated with the primary token for the process
  1260. // that generated the IRP.
  1261. //
  1262. status = SeQueryInformationToken(
  1263. accessToken,
  1264. TokenUser,
  1265. (PVOID *)&userId
  1266. );
  1267. //
  1268. // Do the comparison.
  1269. //
  1270. if (NT_SUCCESS(status)) {
  1271. result = RtlEqualSid(systemSid, userId->User.Sid);
  1272. ExFreePool(userId);
  1273. }
  1274. else {
  1275. TRC_ERR((TB, "SeQueryInformationToken failed with %08X",
  1276. status));
  1277. }
  1278. }
  1279. else {
  1280. TRC_ERR((TB, "Failed to get system sid because of error %08X",
  1281. status));
  1282. }
  1283. if (systemSid) {
  1284. delete systemSid;
  1285. }
  1286. return result;
  1287. }
  1288. BOOL
  1289. DrQueryServerName(PUNICODE_STRING PathName)
  1290. /*++
  1291. Routine Description:
  1292. This routine check if the pathname belongs to our minirdr.
  1293. Arguments:
  1294. PathName: path name to check
  1295. Return Value:
  1296. TRUE - if the path is to our mini-rdr
  1297. FALSE - if the path not our mini-rdr
  1298. --*/
  1299. {
  1300. PWCHAR ServerName;
  1301. PWCHAR ServerNameEnd;
  1302. unsigned CompareLen; // in characters
  1303. unsigned PathNameLen; // in characters
  1304. BEGIN_FN("DrQueryServerName");
  1305. TRC_NRM((TB, "Got query path for file: %wZ", PathName));
  1306. //
  1307. // Make sure the server name we are comparing has at least length
  1308. // of the server name our rdpdr recongize
  1309. //
  1310. if (PathName->Length >= DRUNCSERVERNAME_U_LENGTH) {
  1311. ServerName = PathName->Buffer;
  1312. // bypass the first backslash
  1313. ServerName++;
  1314. PathNameLen = PathName->Length / sizeof(WCHAR) - 1;
  1315. // Find the next backslash
  1316. ServerNameEnd = ServerName;
  1317. while ((unsigned)(ServerNameEnd - ServerName) < PathNameLen) {
  1318. if (*ServerNameEnd == L'\\') {
  1319. break;
  1320. }
  1321. ServerNameEnd++;
  1322. }
  1323. CompareLen = (unsigned)(ServerNameEnd - ServerName);
  1324. //
  1325. // Determine if this is a server name belongs to our minirdr
  1326. //
  1327. if ( (CompareLen == DRUNCSERVERNAME_A_LENGTH - 1) &&
  1328. _wcsnicmp(ServerName, DRUNCSERVERNAME_U, CompareLen) == 0) {
  1329. TRC_NRM((TB, "Quick return that we know the name"));
  1330. return TRUE;
  1331. }
  1332. }
  1333. return FALSE;
  1334. }
  1335. NTSTATUS
  1336. DrPeekDispatch (
  1337. IN PDEVICE_OBJECT DeviceObject,
  1338. IN PIRP Irp
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. This routine implements the driver dispatch for the rdpdr DRIVER object.
  1343. Arguments:
  1344. DeviceObject - Supplies the device object for the packet being processed.
  1345. Irp - Supplies the Irp being processed
  1346. Return Value:
  1347. NTSTATUS - The status for the Irp
  1348. --*/
  1349. {
  1350. PIO_STACK_LOCATION IoStackLocation;
  1351. NTSTATUS Status;
  1352. ULONG irpSessionId;
  1353. BEGIN_FN("DrPeekDispatch ");
  1354. IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
  1355. #if DBG
  1356. TRC_NRM((TB, "Irp: %s", IrpNames[IoStackLocation->MajorFunction]));
  1357. switch (IoStackLocation->MajorFunction) {
  1358. case IRP_MJ_CREATE:
  1359. TRC_NRM((TB, "CreateFile name: %wZ",
  1360. &IoStackLocation->FileObject->FileName));
  1361. break;
  1362. case IRP_MJ_WRITE:
  1363. TRC_NRM((TB, "IRP_MJ_WRITE"));
  1364. break;
  1365. }
  1366. #endif // DBG
  1367. //
  1368. // For Read and Write IRP, we disable caching because the client
  1369. // is an usermode app and can't synchronize with the server cache
  1370. // manager
  1371. //
  1372. if (IoStackLocation->MajorFunction == IRP_MJ_READ ||
  1373. IoStackLocation->MajorFunction == IRP_MJ_WRITE) {
  1374. Irp->Flags |= IRP_NOCACHE;
  1375. }
  1376. //
  1377. // We need to return immediately for redir_query_path
  1378. //
  1379. if (IoStackLocation->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
  1380. IoStackLocation->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH &&
  1381. Irp->RequestorMode == KernelMode) {
  1382. QUERY_PATH_REQUEST *qpRequest = (QUERY_PATH_REQUEST *)
  1383. IoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer;
  1384. if (qpRequest != NULL) {
  1385. UNICODE_STRING PathName;
  1386. PathName.Length = (USHORT)qpRequest->PathNameLength;
  1387. PathName.Buffer= qpRequest->FilePathName;
  1388. if (DrQueryServerName(&PathName)) {
  1389. //
  1390. // We must now complete the IRP
  1391. //
  1392. Irp->IoStatus.Status = STATUS_SUCCESS;
  1393. Irp->IoStatus.Information = 0;
  1394. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1395. return STATUS_SUCCESS;
  1396. }
  1397. }
  1398. }
  1399. //
  1400. // We want to bypass filesize caching
  1401. //
  1402. RxForceQFIPassThrough = TRUE;
  1403. // If it's not the IFS DO, then let RDPDYN have a shot at it. Eventually,
  1404. // it would be nice to confirm that it is for RDPDYN. We can work this
  1405. // out later ...
  1406. if (DeviceObject != (PDEVICE_OBJECT)DrDeviceObject &&
  1407. DeviceObject != (PDEVICE_OBJECT) DrPortDeviceObject) {
  1408. TRC_NRM((TB, "Pass IRP on to RDPDYN_Dispatch"));
  1409. return RDPDYN_Dispatch(DeviceObject, Irp);
  1410. } else {
  1411. // Only for port device, we deny driver attachment
  1412. if (DeviceObject == (PDEVICE_OBJECT) DrPortDeviceObject) {
  1413. if (DeviceObject->AttachedDevice != NULL ||
  1414. (IoStackLocation->FileObject != NULL &&
  1415. IoStackLocation->FileObject->DeviceObject != (PDEVICE_OBJECT)DrPortDeviceObject)) {
  1416. //
  1417. // We don't accept another device attaches to us or
  1418. // is passing irps to us
  1419. //
  1420. Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  1421. Irp->IoStatus.Information = 0;
  1422. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1423. return STATUS_ACCESS_DENIED;
  1424. }
  1425. //
  1426. // We swap back to the rdpdr device object for port device so it'll go through
  1427. // the rdbss route
  1428. //
  1429. IoStackLocation->DeviceObject = (PDEVICE_OBJECT)DrDeviceObject;
  1430. // For Multi-User TS environment, we need to set the port carete share access
  1431. // to be sharable, otherwise two users can't use com1 at the same time because
  1432. // rdbss check for share access for NET_ROOT \\tsclient\com1.
  1433. if (IoStackLocation->MajorFunction == IRP_MJ_CREATE) {
  1434. IoStackLocation->Parameters.Create.ShareAccess = FILE_SHARE_VALID_FLAGS;
  1435. }
  1436. }
  1437. if ((IoStackLocation->MajorFunction == IRP_MJ_CREATE) &&
  1438. (IoStackLocation->FileObject->FileName.Length == 0) &&
  1439. (IoStackLocation->FileObject->RelatedFileObject == NULL)) {
  1440. //
  1441. // This is a blank create, like rdpwsx uses to open us for
  1442. // session connect disconnect notification. Only allowed
  1443. // by the system because we trust rdpwsx to hold a kernel
  1444. // pointer for us
  1445. //
  1446. //
  1447. // Security check the irp.
  1448. //
  1449. Status = IoGetRequestorSessionId(Irp, &irpSessionId);
  1450. if (NT_SUCCESS(Status)) {
  1451. //
  1452. // If the request is from the console session, it needs to be from a system
  1453. // process.
  1454. //
  1455. if (irpSessionId == CONSOLE_SESSIONID) {
  1456. TRC_NRM((TB, "Create request from console process."));
  1457. if (!DrIsSystemProcessRequest(Irp, IoStackLocation)) {
  1458. TRC_ALT((TB, "Root Create request not from system process."));
  1459. //
  1460. // We may get called from a user process through the UNC
  1461. // network provider. e.g. when user does a net use
  1462. // In this case, we have to allow root access. We have to
  1463. // do the security check on per IRP bases.
  1464. //
  1465. //Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  1466. //Irp->IoStatus.Information = 0;
  1467. //IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1468. //return STATUS_ACCESS_DENIED;
  1469. return RxFsdDispatch((PRDBSS_DEVICE_OBJECT)DrDeviceObject, Irp);
  1470. } else {
  1471. TRC_NRM((TB, "Root Create request from system accepted."));
  1472. return RxFsdDispatch((PRDBSS_DEVICE_OBJECT)DrDeviceObject, Irp);
  1473. }
  1474. } else {
  1475. //
  1476. // If not from the console then deny access.
  1477. //
  1478. TRC_ALT((TB, "Root request from %ld", irpSessionId));
  1479. //
  1480. // We may get called from a user process through the UNC
  1481. // network provider. e.g. when user does a net use
  1482. // In this case, we have to allow root access. We have to
  1483. // do the security check on per IRP bases.
  1484. //
  1485. //Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  1486. //Irp->IoStatus.Information = 0;
  1487. //IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1488. //return STATUS_ACCESS_DENIED;
  1489. return RxFsdDispatch((PRDBSS_DEVICE_OBJECT)DrDeviceObject, Irp);
  1490. }
  1491. }
  1492. else {
  1493. TRC_ERR((TB, "IoGetRequestorSessionId failed with %08X.", Status));
  1494. Irp->IoStatus.Status = Status;
  1495. Irp->IoStatus.Information = 0;
  1496. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1497. return Status;
  1498. }
  1499. } else {
  1500. //
  1501. // This is not a create, or at least not a create to just the root
  1502. //
  1503. TRC_NRM((TB, "Pass IRP on to RxFsdDispatch = %d", IoStackLocation->MajorFunction));
  1504. return RxFsdDispatch((PRDBSS_DEVICE_OBJECT)DrDeviceObject, Irp);
  1505. }
  1506. }
  1507. }
  1508. NTSTATUS DrLoadRegistrySettings (
  1509. IN PCWSTR RegistryPath
  1510. )
  1511. /*++
  1512. Routine Description:
  1513. This routine reads the default configuration data from the
  1514. registry for the device redirector driver.
  1515. Arguments:
  1516. RegistryPath - points to the entry for this driver in the
  1517. current control set of the registry.
  1518. Return Value:
  1519. STATUS_SUCCESS if we got the defaults, otherwise we failed.
  1520. The only way to fail this call is if the STATUS_INSUFFICIENT_RESOURCES.
  1521. --*/
  1522. {
  1523. NTSTATUS Status = STATUS_SUCCESS; // return value
  1524. BEGIN_FN("DrLoadRegistrySettings ");
  1525. #if DBG
  1526. extern TRC_CONFIG TRC_Config;
  1527. int i;
  1528. //
  1529. // We use this to query into the registry for defaults
  1530. // paramTable needs to be one entry larger than the set we
  1531. // need because a NULL entry indicates we're done
  1532. //
  1533. RTL_QUERY_REGISTRY_TABLE paramTable[9];
  1534. TRC_CONFIG trcConfig;
  1535. ULONG DebugBreakOnEntryDefault = FALSE;
  1536. PAGED_CODE();
  1537. RtlZeroMemory(&trcConfig, sizeof(trcConfig));
  1538. trcConfig.FunctionLength = TRC_FUNCNAME_LEN;
  1539. trcConfig.TraceDebugger = FALSE;
  1540. trcConfig.TraceLevel = TRC_LEVEL_ALT;
  1541. trcConfig.TraceProfile = TRUE;
  1542. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  1543. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1544. paramTable[0].Name = L"FunctionLength";
  1545. paramTable[0].EntryContext = &TRC_Config.FunctionLength;
  1546. paramTable[0].DefaultType = REG_DWORD;
  1547. paramTable[0].DefaultData = &trcConfig.FunctionLength;
  1548. paramTable[0].DefaultLength = sizeof(trcConfig.FunctionLength);
  1549. paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1550. paramTable[1].Name = L"TraceLevel";
  1551. paramTable[1].EntryContext = &TRC_Config.TraceLevel;
  1552. paramTable[1].DefaultType = REG_DWORD;
  1553. paramTable[1].DefaultData = &trcConfig.TraceLevel;
  1554. paramTable[1].DefaultLength = sizeof(trcConfig.TraceLevel);
  1555. paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1556. paramTable[2].Name = L"TraceProfile";
  1557. paramTable[2].EntryContext = &TRC_Config.TraceProfile;
  1558. paramTable[2].DefaultType = REG_DWORD;
  1559. paramTable[2].DefaultData = &trcConfig.TraceProfile;
  1560. paramTable[2].DefaultLength = sizeof(trcConfig.TraceProfile);
  1561. paramTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1562. paramTable[3].Name = L"TraceDebugger";
  1563. paramTable[3].EntryContext = &TRC_Config.TraceDebugger;
  1564. paramTable[3].DefaultType = REG_DWORD;
  1565. paramTable[3].DefaultData = &trcConfig.TraceDebugger;
  1566. paramTable[3].DefaultLength = sizeof(trcConfig.TraceDebugger);
  1567. paramTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1568. paramTable[4].Name = L"BreakOnEntry";
  1569. paramTable[4].EntryContext = &DebugBreakOnEntry;
  1570. paramTable[4].DefaultType = REG_DWORD;
  1571. paramTable[4].DefaultData = &DebugBreakOnEntryDefault;
  1572. paramTable[4].DefaultLength = sizeof(ULONG);
  1573. paramTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1574. paramTable[5].Name = L"PrintPortWriteSize";
  1575. paramTable[5].EntryContext = &PrintPortWriteSize;
  1576. paramTable[5].DefaultType = REG_DWORD;
  1577. paramTable[5].DefaultData = &PrintPortWriteSizeDefault;
  1578. paramTable[5].DefaultLength = sizeof(ULONG);
  1579. paramTable[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1580. paramTable[6].Name = L"DeviceLowPrioSendFlags";
  1581. paramTable[6].EntryContext = &DeviceLowPrioSendFlags;
  1582. paramTable[6].DefaultType = REG_DWORD;
  1583. paramTable[6].DefaultData = &DeviceLowPrioSendFlagsDefault;
  1584. paramTable[6].DefaultLength = sizeof(ULONG);
  1585. paramTable[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1586. paramTable[7].Name = L"MaxWorkerThreads";
  1587. paramTable[7].EntryContext = &MaxWorkerThreads;
  1588. paramTable[7].DefaultType = REG_DWORD;
  1589. paramTable[7].DefaultData = &MaxWorkerThreadsDefault;
  1590. paramTable[7].DefaultLength = sizeof(ULONG);
  1591. Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  1592. RegistryPath,
  1593. &paramTable[0],
  1594. NULL,
  1595. NULL);
  1596. if (!NT_SUCCESS(Status)) {
  1597. DebugBreakOnEntry = DebugBreakOnEntryDefault;
  1598. }
  1599. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  1600. WCHAR wcPrefix[10] = L"Prefix";
  1601. WCHAR wcStart[10] = L"Start";
  1602. WCHAR wcEnd[10] = L"End";
  1603. UNICODE_STRING usPrefix;
  1604. UNICODE_STRING usStart;
  1605. UNICODE_STRING usEnd;
  1606. usPrefix.Buffer = &wcPrefix[6]; // Just past "Prefix"
  1607. usPrefix.MaximumLength = 3 * sizeof(WCHAR); // Remaining space, room for null term.
  1608. usStart.Buffer = &wcStart[5]; // Just past "Start"
  1609. usStart.MaximumLength = 4 * sizeof(WCHAR); // Remaining space, room for null term.
  1610. usEnd.Buffer = &wcEnd[4]; // Just past "End"
  1611. usEnd.MaximumLength = 5 * sizeof(WCHAR); // Remaining space, room for null term.
  1612. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1613. paramTable[0].Name = wcPrefix;
  1614. paramTable[0].DefaultType = REG_BINARY;
  1615. paramTable[0].DefaultData = &trcConfig.Prefix[0].name[0];
  1616. paramTable[0].DefaultLength = sizeof(trcConfig.Prefix[0].name);
  1617. paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1618. paramTable[1].Name = wcStart;
  1619. paramTable[1].DefaultType = REG_DWORD;
  1620. paramTable[1].DefaultData = &trcConfig.Prefix[0].start;
  1621. paramTable[1].DefaultLength = sizeof(trcConfig.Prefix[0].start);
  1622. paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1623. paramTable[2].Name = wcEnd;
  1624. paramTable[2].DefaultType = REG_DWORD;
  1625. paramTable[2].DefaultData = &trcConfig.Prefix[0].end;
  1626. paramTable[2].DefaultLength = sizeof(trcConfig.Prefix[0].end);
  1627. //
  1628. // So the registry can have values like:
  1629. // Prefix1 = "rdpdr"
  1630. // Start1 = 400
  1631. // End1 = 425
  1632. //
  1633. // Prefix1 = "channel"
  1634. // Start1 = 765
  1635. // End1 = 765
  1636. //
  1637. // And that will restrict tracing output to rdpdr, lines 400-425
  1638. // and channel, line 765
  1639. //
  1640. for (i = 0; i < TRC_MAX_PREFIX; i ++) {
  1641. RtlZeroMemory(&TRC_Config.Prefix[i].name[0],
  1642. sizeof(TRC_Config.Prefix[i].name[0]));
  1643. // Clear out the end of the strings
  1644. usPrefix.Length = 0; // no length yet
  1645. RtlZeroMemory(usPrefix.Buffer, usPrefix.MaximumLength);
  1646. usStart.Length = 0; // no length yet
  1647. RtlZeroMemory(usStart.Buffer, usStart.MaximumLength);
  1648. usEnd.Length = 0; // no length yet
  1649. RtlZeroMemory(usEnd.Buffer, usEnd.MaximumLength);
  1650. // Append the integer
  1651. RtlIntegerToUnicodeString(i + 1, 10, &usPrefix);
  1652. RtlIntegerToUnicodeString(i + 1, 10, &usStart);
  1653. RtlIntegerToUnicodeString(i + 1, 10, &usEnd);
  1654. paramTable[0].EntryContext = &TRC_Config.Prefix[i].name;
  1655. paramTable[1].EntryContext = &TRC_Config.Prefix[i].start;
  1656. paramTable[2].EntryContext = &TRC_Config.Prefix[i].end;
  1657. Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  1658. RegistryPath,
  1659. &paramTable[0],
  1660. NULL,
  1661. NULL);
  1662. }
  1663. #endif // DBG
  1664. return (Status);
  1665. }
  1666. NTSTATUS DrStart(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
  1667. /*++
  1668. Routine Description:
  1669. This routine completes the initialization of the mini redirector fromn the
  1670. RDBSS perspective. Note that this is different from the initialization done
  1671. in DriverEntry. Any initialization that depends on RDBSS should be done as
  1672. part of this routine while the initialization that is independent of RDBSS
  1673. should be done in the DriverEntry routine.
  1674. Arguments:
  1675. RxContext - Supplies the Irp that was used to startup the rdbss
  1676. Return Value:
  1677. RXSTATUS - The return status for the operation
  1678. --*/
  1679. {
  1680. NTSTATUS Status = STATUS_SUCCESS;
  1681. BEGIN_FN("DrStart");
  1682. return Status;
  1683. }
  1684. NTSTATUS DrStop(PRX_CONTEXT RxContext, IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject)
  1685. /*++
  1686. Routine Description:
  1687. This routine is used to deactivate the mini redirector from the RDBSS perspective
  1688. Arguments:
  1689. RxContext - the context that was used to start the mini redirector
  1690. pContext - the mini rdr context passed in at registration time.
  1691. Return Value:
  1692. RXSTATUS - The return status for the operation
  1693. --*/
  1694. {
  1695. NTSTATUS Status;
  1696. BEGIN_FN("DrStop");
  1697. return STATUS_SUCCESS;
  1698. }
  1699. NTSTATUS DrDeallocateForFcb(IN OUT PMRX_FCB pFcb)
  1700. {
  1701. BEGIN_FN("DrDeallocateForFcb");
  1702. return STATUS_SUCCESS;
  1703. }
  1704. NTSTATUS DrDeallocateForFobx(IN OUT PMRX_FOBX pFobx)
  1705. /*++
  1706. Routine Description:
  1707. This routine is the last gasp of a Fobx. We remove the DeviceEntry ref
  1708. Arguments:
  1709. pFobx - the instance to be closed
  1710. Return Value:
  1711. RXSTATUS - The return status for the operation
  1712. Notes:
  1713. --*/
  1714. {
  1715. DrDevice *Device;
  1716. DrFile *FileObj;
  1717. BEGIN_FN("DrDeallocateForFobx");
  1718. //
  1719. // Dereference the device object.
  1720. //
  1721. if (pFobx->Context != NULL) {
  1722. Device = (DrDevice *)pFobx->Context;
  1723. pFobx->Context = NULL;
  1724. Device->Release();
  1725. }
  1726. //
  1727. // Cleanup the file object
  1728. //
  1729. if (pFobx->Context2 != NULL) {
  1730. FileObj = (DrFile *)pFobx->Context2;
  1731. FileObj->Release();
  1732. pFobx->Context2 = NULL;
  1733. }
  1734. return STATUS_SUCCESS;
  1735. }
  1736. NTSTATUS DrForceClosed(IN PMRX_SRV_OPEN pSrvOpen)
  1737. /*++
  1738. Routine Description:
  1739. This routine closes a file system object
  1740. Arguments:
  1741. pSrvOpen - the instance to be closed
  1742. Return Value:
  1743. RXSTATUS - The return status for the operation
  1744. Notes:
  1745. --*/
  1746. {
  1747. BEGIN_FN("DrForceClosed");
  1748. TRC_NRM((TB, "DrForceClosed not implemented"));
  1749. return STATUS_NOT_IMPLEMENTED;
  1750. }
  1751. NTSTATUS
  1752. BuildDeviceAcl(
  1753. OUT PACL *DeviceAcl
  1754. )
  1755. /*++
  1756. Routine Description:
  1757. (Lifted from AFD - AfdBuildDeviceAcl)
  1758. This routine builds an ACL which gives Administrators and LocalSystem
  1759. principals full access. All other principals have no access.
  1760. Arguments:
  1761. DeviceAcl - Output pointer to the new ACL.
  1762. Return Value:
  1763. STATUS_SUCCESS or an appropriate error code.
  1764. --*/
  1765. {
  1766. PGENERIC_MAPPING GenericMapping;
  1767. PSID AdminsSid;
  1768. PSID SystemSid;
  1769. ULONG AclLength;
  1770. NTSTATUS Status;
  1771. ACCESS_MASK AccessMask = GENERIC_ALL;
  1772. PACL NewAcl;
  1773. BEGIN_FN("BuildDeviceAcl");
  1774. //
  1775. // Enable access to all the globally defined SIDs
  1776. //
  1777. GenericMapping = IoGetFileObjectGenericMapping();
  1778. RtlMapGenericMask( &AccessMask, GenericMapping );
  1779. AdminsSid = SeExports->SeAliasAdminsSid;
  1780. SystemSid = SeExports->SeLocalSystemSid;
  1781. AclLength = sizeof( ACL ) +
  1782. 2 * sizeof( ACCESS_ALLOWED_ACE ) +
  1783. RtlLengthSid( AdminsSid ) +
  1784. RtlLengthSid( SystemSid ) -
  1785. 2 * sizeof( ULONG );
  1786. NewAcl = (PACL)new(PagedPool) BYTE[AclLength];
  1787. if (NewAcl == NULL) {
  1788. return( STATUS_INSUFFICIENT_RESOURCES );
  1789. }
  1790. Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION );
  1791. if (!NT_SUCCESS( Status )) {
  1792. delete NewAcl;
  1793. return( Status );
  1794. }
  1795. Status = RtlAddAccessAllowedAce (
  1796. NewAcl,
  1797. ACL_REVISION2,
  1798. AccessMask,
  1799. AdminsSid
  1800. );
  1801. ASSERT( NT_SUCCESS( Status ));
  1802. Status = RtlAddAccessAllowedAce (
  1803. NewAcl,
  1804. ACL_REVISION2,
  1805. AccessMask,
  1806. SystemSid
  1807. );
  1808. ASSERT( NT_SUCCESS( Status ));
  1809. *DeviceAcl = NewAcl;
  1810. return( STATUS_SUCCESS );
  1811. } // BuildDeviceAcl
  1812. NTSTATUS
  1813. CreateAdminSecurityDescriptor(
  1814. VOID
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. (Lifted from AFD - AfdCreateAdminSecurityDescriptor)
  1819. This routine creates a security descriptor which gives access
  1820. only to Administrtors and LocalSystem. This descriptor is used
  1821. to access check raw endpoint opens and exclisive access to transport
  1822. addresses.
  1823. Arguments:
  1824. None.
  1825. Return Value:
  1826. STATUS_SUCCESS or an appropriate error code.
  1827. --*/
  1828. {
  1829. PACL rawAcl = NULL;
  1830. NTSTATUS status;
  1831. BOOLEAN memoryAllocated = FALSE;
  1832. PSECURITY_DESCRIPTOR drSecurityDescriptor;
  1833. ULONG localDrSecurityDescriptorLength = 0;
  1834. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  1835. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  1836. (PSECURITY_DESCRIPTOR) &buffer;
  1837. PSECURITY_DESCRIPTOR localDrAdminSecurityDescriptor;
  1838. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  1839. BEGIN_FN("CreateAdminSecurityDescriptor");
  1840. //
  1841. // Get a pointer to the security descriptor from the Dr device object.
  1842. //
  1843. status = ObGetObjectSecurity(
  1844. DrDeviceObject,
  1845. &drSecurityDescriptor,
  1846. &memoryAllocated
  1847. );
  1848. if (!NT_SUCCESS(status)) {
  1849. TRC_ERR((TB, "Unable to get security descriptor, error: %x",
  1850. status));
  1851. ASSERT(memoryAllocated == FALSE);
  1852. return(status);
  1853. }
  1854. else {
  1855. if (drSecurityDescriptor == NULL) {
  1856. TRC_ERR((TB, "No security descriptor for DrDeviceObject"));
  1857. status = STATUS_UNSUCCESSFUL;
  1858. return(status);
  1859. }
  1860. }
  1861. //
  1862. // Build a local security descriptor with an ACL giving only
  1863. // administrators and system access.
  1864. //
  1865. status = BuildDeviceAcl(&rawAcl);
  1866. if (!NT_SUCCESS(status)) {
  1867. TRC_ERR((TB, "Unable to create Raw ACL, error: %x", status));
  1868. goto error_exit;
  1869. }
  1870. (VOID) RtlCreateSecurityDescriptor(
  1871. localSecurityDescriptor,
  1872. SECURITY_DESCRIPTOR_REVISION
  1873. );
  1874. (VOID) RtlSetDaclSecurityDescriptor(
  1875. localSecurityDescriptor,
  1876. TRUE,
  1877. rawAcl,
  1878. FALSE
  1879. );
  1880. //
  1881. // Make a copy of the Dr descriptor. This copy will be the raw descriptor.
  1882. //
  1883. localDrSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  1884. drSecurityDescriptor
  1885. );
  1886. localDrAdminSecurityDescriptor = (PSECURITY_DESCRIPTOR)new(PagedPool) BYTE[localDrSecurityDescriptorLength];
  1887. if (localDrAdminSecurityDescriptor == NULL) {
  1888. TRC_ERR((TB, "couldn't allocate security descriptor"));
  1889. status = STATUS_NO_MEMORY;
  1890. goto error_exit;
  1891. }
  1892. RtlMoveMemory(
  1893. localDrAdminSecurityDescriptor,
  1894. drSecurityDescriptor,
  1895. localDrSecurityDescriptorLength
  1896. );
  1897. DrAdminSecurityDescriptor = localDrAdminSecurityDescriptor;
  1898. DrSecurityDescriptorLength = localDrSecurityDescriptorLength;
  1899. //
  1900. // Now apply the local descriptor to the raw descriptor.
  1901. //
  1902. status = SeSetSecurityDescriptorInfo(
  1903. NULL,
  1904. &securityInformation,
  1905. localSecurityDescriptor,
  1906. &DrAdminSecurityDescriptor,
  1907. PagedPool,
  1908. IoGetFileObjectGenericMapping()
  1909. );
  1910. if (!NT_SUCCESS(status)) {
  1911. TRC_ERR((TB, "SeSetSecurity failed, %lx", status));
  1912. ASSERT (DrAdminSecurityDescriptor==localDrAdminSecurityDescriptor);
  1913. delete DrAdminSecurityDescriptor;
  1914. DrAdminSecurityDescriptor = NULL;
  1915. DrSecurityDescriptorLength = 0;
  1916. goto error_exit;
  1917. }
  1918. if (DrAdminSecurityDescriptor != localDrAdminSecurityDescriptor) {
  1919. delete localDrAdminSecurityDescriptor;
  1920. }
  1921. status = STATUS_SUCCESS;
  1922. error_exit:
  1923. ObReleaseObjectSecurity(
  1924. drSecurityDescriptor,
  1925. memoryAllocated
  1926. );
  1927. if (rawAcl!=NULL) {
  1928. delete rawAcl;
  1929. }
  1930. return(status);
  1931. }