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.

1178 lines
31 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. This module contains the dispatch routines for SAC.
  7. Author:
  8. Sean Selitrennikoff (v-seans) - Jan 13, 1999
  9. Brian Guarraci (briangu), 2001
  10. Revision History:
  11. --*/
  12. #include <initguid.h>
  13. #include "sac.h"
  14. DEFINE_GUID(SAC_CMD_CHANNEL_APPLICATION_GUID, 0x63d02271, 0x8aa4, 0x11d5, 0xbc, 0xcf, 0x00, 0xb0, 0xd0, 0x14, 0xa2, 0xd0);
  15. NTSTATUS
  16. DispatchClose(
  17. IN PSAC_DEVICE_CONTEXT DeviceContext,
  18. IN PIRP Irp
  19. );
  20. NTSTATUS
  21. DispatchCreate(
  22. IN PSAC_DEVICE_CONTEXT DeviceContext,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. Dispatch(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp
  29. )
  30. /*++
  31. Routine Description:
  32. This is the dispatch routine for SAC.
  33. Arguments:
  34. DeviceObject - Pointer to device object for target device
  35. Irp - Pointer to I/O request packet
  36. Return Value:
  37. NTSTATUS -- Indicates whether the request was successfully queued.
  38. Security:
  39. interface:
  40. external --> internal
  41. exposed to anything that can get a handle device object
  42. --*/
  43. {
  44. PSAC_DEVICE_CONTEXT DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  45. PIO_STACK_LOCATION IrpSp;
  46. NTSTATUS Status;
  47. //
  48. //
  49. //
  50. Status = STATUS_UNSUCCESSFUL;
  51. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC Dispatch: Entering.\n")));
  52. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  53. switch (IrpSp->MajorFunction) {
  54. case IRP_MJ_CREATE:
  55. Status = DispatchCreate(DeviceContext, Irp);
  56. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  57. KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status)));
  58. break;
  59. case IRP_MJ_CLEANUP:
  60. #if ENABLE_SERVICE_FILE_OBJECT_CHECKING
  61. //
  62. // Determine if the process that is closing
  63. // their driver handle owns any channels or
  64. // is the process that registered the cmd event info.
  65. // If it is any of these, close the respective
  66. // resource.
  67. //
  68. //
  69. // Compare the FileObject against
  70. //
  71. // the service fileobject
  72. // the existing channel fileobjects
  73. //
  74. //
  75. if (IsCmdEventRegistrationProcess(IrpSp->FileObject)) {
  76. Status = UnregisterSacCmdEvent(IrpSp->FileObject);
  77. if (NT_SUCCESS(Status)) {
  78. //
  79. // Notify the Console Manager that the service has unregistered
  80. //
  81. Status = IoMgrHandleEvent(
  82. IO_MGR_EVENT_UNREGISTER_SAC_CMD_EVENT,
  83. NULL,
  84. NULL
  85. );
  86. }
  87. }
  88. #endif
  89. else {
  90. //
  91. // Find all channels that have the same File object
  92. // and notify the Io Mgr that they should be closed
  93. //
  94. Status = ChanMgrCloseChannelsWithFileObject(IrpSp->FileObject);
  95. }
  96. //
  97. // we return SUCCESS regardless of our attempts to clean up
  98. // the service or channels.
  99. //
  100. Status = STATUS_SUCCESS;
  101. Irp->IoStatus.Status = STATUS_SUCCESS;
  102. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  103. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  104. KdPrint(("SAC Dispatch: Exiting cleanup status 0x%x\n", Status)));
  105. break;
  106. case IRP_MJ_CLOSE:
  107. Status = DispatchClose(DeviceContext, Irp);
  108. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  109. KdPrint(("SAC Dispatch: Exiting close status 0x%x\n", Status)));
  110. break;
  111. case IRP_MJ_DEVICE_CONTROL:
  112. ASSERT(0);
  113. Status = DispatchDeviceControl(DeviceObject, Irp);
  114. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  115. KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status)));
  116. break;
  117. default:
  118. IF_SAC_DEBUG(SAC_DEBUG_FAILS,
  119. KdPrint(( "SAC Dispatch: Invalid major function %lx\n", IrpSp->MajorFunction )));
  120. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  121. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  122. Status = STATUS_NOT_IMPLEMENTED;
  123. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  124. KdPrint(("SAC Dispatch: Exiting with status 0x%x\n", Status)));
  125. break;
  126. }
  127. return Status;
  128. } // Dispatch
  129. NTSTATUS
  130. DispatchDeviceControl(
  131. IN PDEVICE_OBJECT DeviceObject,
  132. IN PIRP Irp
  133. )
  134. /*++
  135. Routine Description:
  136. This is the dispatch routine for SAC IOCTLs.
  137. Arguments:
  138. DeviceObject - Pointer to device object for target device
  139. Irp - Pointer to I/O request packet
  140. Return Value:
  141. NTSTATUS -- Indicates whether the request was successfully queued.
  142. Security:
  143. interface:
  144. external -> internal
  145. internal -> external
  146. --*/
  147. {
  148. NTSTATUS Status;
  149. PSAC_DEVICE_CONTEXT DeviceContext;
  150. PIO_STACK_LOCATION IrpSp;
  151. ULONG i;
  152. ULONG ResponseLength;
  153. ULONG IoControlCode;
  154. ResponseLength = 0;
  155. DeviceContext = (PSAC_DEVICE_CONTEXT)DeviceObject->DeviceExtension;
  156. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  157. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchDeviceControl: Entering.\n")));
  158. //
  159. // Get the IOCTL code
  160. //
  161. IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  162. switch (IoControlCode) {
  163. case IOCTL_SAC_OPEN_CHANNEL: {
  164. PSAC_CHANNEL Channel;
  165. PSAC_CMD_OPEN_CHANNEL OpenChannelCmd;
  166. PSAC_RSP_OPEN_CHANNEL OpenChannelRsp;
  167. PSAC_CHANNEL_OPEN_ATTRIBUTES Attributes;
  168. //
  169. //
  170. //
  171. Channel = NULL;
  172. //
  173. // Verify the parameters of the IRP
  174. //
  175. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_OPEN_CHANNEL)) {
  176. Status = STATUS_INVALID_BUFFER_SIZE;
  177. break;
  178. }
  179. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(SAC_RSP_OPEN_CHANNEL)) {
  180. Status = STATUS_INVALID_BUFFER_SIZE;
  181. break;
  182. }
  183. //
  184. // Get the IRP buffers
  185. //
  186. OpenChannelCmd = (PSAC_CMD_OPEN_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  187. OpenChannelRsp = (PSAC_RSP_OPEN_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  188. //
  189. // Get the attributes from the command structure
  190. //
  191. Attributes = &OpenChannelCmd->Attributes;
  192. //
  193. // Verify that the Channel Type is valid
  194. //
  195. if (! ChannelIsValidType(Attributes->Type)) {
  196. Status = STATUS_INVALID_PARAMETER_1;
  197. break;
  198. }
  199. //
  200. // Verify that if the user wants to use the CLOSE_EVENT, we received on to use
  201. //
  202. if (Attributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT) {
  203. #if DEBUG_DISPATCH
  204. ASSERT(Attributes->CloseEvent != NULL);
  205. #endif
  206. if (Attributes->CloseEvent == NULL) {
  207. Status = STATUS_INVALID_PARAMETER_5;
  208. break;
  209. }
  210. } else {
  211. #if DEBUG_DISPATCH
  212. ASSERT(Attributes->CloseEvent == NULL);
  213. #endif
  214. if (Attributes->CloseEvent != NULL) {
  215. Status = STATUS_INVALID_PARAMETER_5;
  216. break;
  217. }
  218. }
  219. //
  220. // Verify that if the user wants to use the HAS_NEW_DATA_EVENT, we received one to use
  221. //
  222. if (Attributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) {
  223. #if DEBUG_DISPATCH
  224. ASSERT(Attributes->HasNewDataEvent);
  225. #endif
  226. if (! Attributes->HasNewDataEvent) {
  227. Status = STATUS_INVALID_PARAMETER_6;
  228. break;
  229. }
  230. } else {
  231. #if DEBUG_DISPATCH
  232. ASSERT(Attributes->HasNewDataEvent == NULL);
  233. #endif
  234. if (Attributes->HasNewDataEvent != NULL) {
  235. Status = STATUS_INVALID_PARAMETER_6;
  236. break;
  237. }
  238. }
  239. #if ENABLE_CHANNEL_LOCKING
  240. //
  241. // Verify that if the user wants to use the LOCK_EVENT, we received one to use
  242. //
  243. if (Attributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT) {
  244. #if DEBUG_DISPATCH
  245. ASSERT(Attributes->LockEvent);
  246. #endif
  247. if (! Attributes->LockEvent) {
  248. Status = STATUS_INVALID_PARAMETER_7;
  249. break;
  250. }
  251. } else {
  252. #if DEBUG_DISPATCH
  253. ASSERT(Attributes->LockEvent == NULL);
  254. #endif
  255. if (Attributes->LockEvent != NULL) {
  256. Status = STATUS_INVALID_PARAMETER_7;
  257. break;
  258. }
  259. }
  260. #endif
  261. //
  262. // Verify that if the user wants to use the REDRAW_EVENT, we received one to use
  263. //
  264. if (Attributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT) {
  265. #if DEBUG_DISPATCH
  266. ASSERT(Attributes->RedrawEvent);
  267. #endif
  268. if (! Attributes->RedrawEvent) {
  269. Status = STATUS_INVALID_PARAMETER_8;
  270. break;
  271. }
  272. } else {
  273. #if DEBUG_DISPATCH
  274. ASSERT(Attributes->RedrawEvent == NULL);
  275. #endif
  276. if (Attributes->RedrawEvent != NULL) {
  277. Status = STATUS_INVALID_PARAMETER_8;
  278. break;
  279. }
  280. }
  281. //
  282. // SECURITY:
  283. //
  284. // at this point we have at least a properly formed set of flags
  285. // and event handles. The events still need to be validated, however.
  286. // this is done via ChanMgrCreateChannel.
  287. //
  288. //
  289. // Create the channel based on type
  290. //
  291. if (Attributes->Type == ChannelTypeCmd) {
  292. PSAC_CHANNEL_OPEN_ATTRIBUTES tmpAttributes;
  293. PWCHAR Name;
  294. PCWSTR Description;
  295. //
  296. //
  297. //
  298. tmpAttributes = NULL;
  299. Name = NULL;
  300. Description = NULL;
  301. //
  302. // Create a channel for this IRP
  303. //
  304. do {
  305. //
  306. // the cmd channel requires all of the events
  307. // hence, ensure we have them
  308. //
  309. if (!(Attributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT) ||
  310. !(Attributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) ||
  311. !(Attributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT) ||
  312. !(Attributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)) {
  313. Status = STATUS_INVALID_PARAMETER_7;
  314. break;
  315. }
  316. //
  317. // Allocate a temporary attributes structure that
  318. // we'll populate with attributes appropriate for
  319. // creating a cmd type channel
  320. //
  321. tmpAttributes = ALLOCATE_POOL(sizeof(SAC_CHANNEL_OPEN_ATTRIBUTES), GENERAL_POOL_TAG);
  322. if (! tmpAttributes) {
  323. Status = STATUS_NO_MEMORY;
  324. break;
  325. }
  326. //
  327. // Allocate a buffer for the channel's name
  328. //
  329. Name = ALLOCATE_POOL(SAC_MAX_CHANNEL_NAME_SIZE, GENERAL_POOL_TAG);
  330. if (! Name) {
  331. Status = STATUS_NO_MEMORY;
  332. break;
  333. }
  334. //
  335. // Generate a name for the command console channel
  336. //
  337. Status = ChanMgrGenerateUniqueCmdName(Name);
  338. if (! NT_SUCCESS(Status)) {
  339. break;
  340. }
  341. //
  342. // Initialize the Command Console attributes
  343. //
  344. RtlZeroMemory(tmpAttributes, sizeof(SAC_CHANNEL_OPEN_ATTRIBUTES));
  345. tmpAttributes->Type = Attributes->Type;
  346. // attempt to copy the name
  347. wcsncpy(tmpAttributes->Name, Name, SAC_MAX_CHANNEL_NAME_LENGTH);
  348. tmpAttributes->Name[SAC_MAX_CHANNEL_NAME_LENGTH] = UNICODE_NULL;
  349. // attempt to copy the channel description
  350. Description = GetMessage(CMD_CHANNEL_DESCRIPTION);
  351. ASSERT(Description);
  352. if (!Description) {
  353. Status = STATUS_NO_MEMORY;
  354. break;
  355. }
  356. wcsncpy(tmpAttributes->Description, Description, SAC_MAX_CHANNEL_DESCRIPTION_LENGTH);
  357. tmpAttributes->Description[SAC_MAX_CHANNEL_DESCRIPTION_LENGTH] = UNICODE_NULL;
  358. tmpAttributes->Flags = Attributes->Flags |
  359. SAC_CHANNEL_FLAG_APPLICATION_TYPE;
  360. tmpAttributes->CloseEvent = Attributes->CloseEvent;
  361. tmpAttributes->HasNewDataEvent = Attributes->HasNewDataEvent;
  362. #if ENABLE_CHANNEL_LOCKING
  363. tmpAttributes->LockEvent = Attributes->LockEvent;
  364. #endif
  365. tmpAttributes->RedrawEvent = Attributes->RedrawEvent;
  366. tmpAttributes->ApplicationType = SAC_CMD_CHANNEL_APPLICATION_GUID;
  367. //
  368. // attempt to create the new channel
  369. //
  370. Status = ChanMgrCreateChannel(
  371. &Channel,
  372. tmpAttributes
  373. );
  374. } while (FALSE);
  375. //
  376. // Cleanup
  377. //
  378. SAFE_FREE_POOL(&Name);
  379. SAFE_FREE_POOL(&tmpAttributes);
  380. } else {
  381. //
  382. // Validate the Name & Description strings
  383. //
  384. //
  385. // Verify name string is NULL terminated.
  386. //
  387. i = 0;
  388. while (i < SAC_MAX_CHANNEL_NAME_LENGTH) {
  389. if (Attributes->Name[i] == UNICODE_NULL) {
  390. break;
  391. }
  392. i++;
  393. }
  394. //
  395. // fail if string is not NULL terminated or if string is empty
  396. //
  397. if ((i == SAC_MAX_CHANNEL_NAME_LENGTH) || (i == 0)) {
  398. Status = STATUS_INVALID_PARAMETER_2;
  399. break;
  400. }
  401. //
  402. // Verify description string is NULL terminated.
  403. // Note: the Description is allowed to have zero length, so we don't check it.
  404. //
  405. i = 0;
  406. while (i < SAC_MAX_CHANNEL_DESCRIPTION_LENGTH) {
  407. if (Attributes->Description[i] == UNICODE_NULL) {
  408. break;
  409. }
  410. i++;
  411. }
  412. if (i == SAC_MAX_CHANNEL_DESCRIPTION_LENGTH) {
  413. Status = STATUS_INVALID_PARAMETER_3;
  414. break;
  415. }
  416. //
  417. // attempt to create the new channel
  418. //
  419. Status = ChanMgrCreateChannel(
  420. &Channel,
  421. Attributes
  422. );
  423. }
  424. if (NT_SUCCESS(Status)) {
  425. //
  426. // Keep track of the File Object used to reference the driver
  427. //
  428. ChannelSetFileObject(Channel, IrpSp->FileObject);
  429. //
  430. // Populate the response message with the new channel handle
  431. //
  432. OpenChannelRsp->Handle = ChannelGetHandle(Channel);
  433. ResponseLength = sizeof(SAC_RSP_OPEN_CHANNEL);
  434. //
  435. // Notify the Console Manager that a new channel has been created
  436. //
  437. IoMgrHandleEvent(
  438. IO_MGR_EVENT_CHANNEL_CREATE,
  439. Channel,
  440. NULL
  441. );
  442. }
  443. break;
  444. }
  445. case IOCTL_SAC_CLOSE_CHANNEL: {
  446. PSAC_CMD_CLOSE_CHANNEL ChannelCloseCmd;
  447. PSAC_CHANNEL Channel;
  448. //
  449. // Verify the parameters of the IRP
  450. //
  451. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_CLOSE_CHANNEL)) {
  452. Status = STATUS_INVALID_BUFFER_SIZE;
  453. break;
  454. }
  455. //
  456. // Close the given channel.
  457. //
  458. ChannelCloseCmd = (PSAC_CMD_CLOSE_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  459. //
  460. // Get the referred channel by it's handle while making
  461. // sure the driver handle is the same one as the one
  462. // that created the channel - the same process
  463. //
  464. Status = ChanMgrGetByHandleAndFileObject(
  465. ChannelCloseCmd->Handle,
  466. IrpSp->FileObject,
  467. &Channel
  468. );
  469. if (NT_SUCCESS(Status)) {
  470. //
  471. // close the channel
  472. //
  473. Status = ChanMgrCloseChannel(Channel);
  474. //
  475. // We are done with the channel
  476. //
  477. ChanMgrReleaseChannel(Channel);
  478. }
  479. break;
  480. }
  481. case IOCTL_SAC_WRITE_CHANNEL: {
  482. PSAC_CMD_WRITE_CHANNEL ChannelWriteCmd;
  483. PSAC_CHANNEL Channel;
  484. //
  485. // Verify the parameters of the IRP
  486. //
  487. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SAC_CMD_WRITE_CHANNEL)) {
  488. Status = STATUS_BUFFER_TOO_SMALL;
  489. break;
  490. }
  491. //
  492. // Get the Write cmd structure
  493. //
  494. ChannelWriteCmd = (PSAC_CMD_WRITE_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  495. //
  496. // Verify that the specified write bufferSize is reasonable
  497. //
  498. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  499. (sizeof(SAC_CMD_WRITE_CHANNEL) + ChannelWriteCmd->Size)) {
  500. //
  501. // if the buffer sizes dont match,
  502. // then the specified the wrong size
  503. //
  504. Status = STATUS_INVALID_PARAMETER_2;
  505. break;
  506. }
  507. //
  508. // Get the referred channel by it's handle while making
  509. // sure the driver handle is the same one as the one
  510. // that created the channel - the same process
  511. //
  512. Status = ChanMgrGetByHandleAndFileObject(
  513. ChannelWriteCmd->Handle,
  514. IrpSp->FileObject,
  515. &Channel
  516. );
  517. if (NT_SUCCESS(Status)) {
  518. //
  519. // Call the I/O Manager's OWrite method
  520. //
  521. Status = IoMgrHandleEvent(
  522. IO_MGR_EVENT_CHANNEL_WRITE,
  523. Channel,
  524. ChannelWriteCmd
  525. );
  526. //
  527. // We are done with the channel
  528. //
  529. ChanMgrReleaseChannel(Channel);
  530. }
  531. #if DEBUG_DISPATCH
  532. ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND);
  533. #endif
  534. break;
  535. }
  536. case IOCTL_SAC_READ_CHANNEL: {
  537. PSAC_CHANNEL Channel;
  538. PSAC_CMD_READ_CHANNEL ChannelReadCmd;
  539. PSAC_RSP_READ_CHANNEL ChannelReadRsp;
  540. //
  541. //
  542. //
  543. Channel = NULL;
  544. //
  545. // Verify the parameters of the IRP
  546. //
  547. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_READ_CHANNEL)) {
  548. Status = STATUS_INVALID_BUFFER_SIZE;
  549. break;
  550. }
  551. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SAC_RSP_READ_CHANNEL)) {
  552. Status = STATUS_BUFFER_TOO_SMALL;
  553. break;
  554. }
  555. //
  556. // Read from the given channel.
  557. //
  558. ChannelReadCmd = (PSAC_CMD_READ_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  559. //
  560. // Get the referred channel by it's handle while making
  561. // sure the driver handle is the same one as the one
  562. // that created the channel - the same process
  563. //
  564. Status = ChanMgrGetByHandleAndFileObject(
  565. ChannelReadCmd->Handle,
  566. IrpSp->FileObject,
  567. &Channel
  568. );
  569. if (NT_SUCCESS(Status)) {
  570. ChannelReadRsp = (PSAC_RSP_READ_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  571. //
  572. // SECURITY:
  573. //
  574. // it is safe to use the OutputBufferLength since we know the buffer
  575. // is large enough to hold at least one byte.
  576. // the response structure is essentially a byte array of bytes
  577. // read, we read the # of bytes specified by OutputBufferLength
  578. //
  579. Status = ChannelIRead(
  580. Channel,
  581. &(ChannelReadRsp->Buffer[0]),
  582. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  583. &ResponseLength
  584. );
  585. //
  586. // We are done with the channel
  587. //
  588. ChanMgrReleaseChannel(Channel);
  589. }
  590. #if DEBUG_DISPATCH
  591. ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND);
  592. #endif
  593. break;
  594. }
  595. case IOCTL_SAC_POLL_CHANNEL: {
  596. PSAC_CHANNEL Channel;
  597. PSAC_CMD_POLL_CHANNEL PollChannelCmd;
  598. PSAC_RSP_POLL_CHANNEL PollChannelRsp;
  599. //
  600. //
  601. //
  602. Channel = NULL;
  603. //
  604. // Verify the parameters of the IRP
  605. //
  606. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_POLL_CHANNEL)) {
  607. Status = STATUS_INVALID_BUFFER_SIZE;
  608. break;
  609. }
  610. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(SAC_RSP_POLL_CHANNEL)) {
  611. Status = STATUS_INVALID_BUFFER_SIZE;
  612. break;
  613. }
  614. //
  615. // get the channel specified by the incoming channel handle
  616. //
  617. PollChannelCmd = (PSAC_CMD_POLL_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  618. PollChannelRsp = (PSAC_RSP_POLL_CHANNEL)Irp->AssociatedIrp.SystemBuffer;
  619. //
  620. // Get the referred channel by it's handle while making
  621. // sure the driver handle is the same one as the one
  622. // that created the channel - the same process
  623. //
  624. Status = ChanMgrGetByHandleAndFileObject(
  625. PollChannelCmd->Handle,
  626. IrpSp->FileObject,
  627. &Channel
  628. );
  629. if (NT_SUCCESS(Status)) {
  630. //
  631. // see if there is data waiting
  632. //
  633. // SECURITY:
  634. //
  635. // the InputWaiting variable is guaranteed to be safe since
  636. // we validated the OutputBufferLength
  637. //
  638. PollChannelRsp->InputWaiting = ChannelHasNewIBufferData(Channel);
  639. ResponseLength = sizeof(SAC_RSP_POLL_CHANNEL);
  640. //
  641. // We are done with the channel
  642. //
  643. Status = ChanMgrReleaseChannel(Channel);
  644. }
  645. #if DEBUG_DISPATCH
  646. ASSERT(NT_SUCCESS(Status) || Status == STATUS_NOT_FOUND);
  647. #endif
  648. break;
  649. }
  650. case IOCTL_SAC_REGISTER_CMD_EVENT: {
  651. PSAC_CMD_SETUP_CMD_EVENT SetupCmdEvent;
  652. //
  653. // Verify the parameters of the IRP
  654. //
  655. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SAC_CMD_SETUP_CMD_EVENT)) {
  656. Status = STATUS_INVALID_BUFFER_SIZE;
  657. break;
  658. }
  659. //
  660. // get the event info
  661. //
  662. SetupCmdEvent = (PSAC_CMD_SETUP_CMD_EVENT)Irp->AssociatedIrp.SystemBuffer;
  663. #if ENABLE_CMD_SESSION_PERMISSION_CHECKING
  664. //
  665. // If we are not able to launch cmd sessions,
  666. // then notify that we cannot peform this action
  667. //
  668. if (! IsCommandConsoleLaunchingEnabled()) {
  669. Status = STATUS_UNSUCCESSFUL;
  670. break;
  671. }
  672. #endif
  673. //
  674. // Attempt to register the callers cmd event info
  675. //
  676. // SECURITY:
  677. //
  678. // the SAC_CMD_SETUP_CMD_EVENT has events handles that must be
  679. // validated as part of the registration process
  680. //
  681. Status = RegisterSacCmdEvent(
  682. IrpSp->FileObject,
  683. SetupCmdEvent
  684. );
  685. if (NT_SUCCESS(Status)) {
  686. //
  687. // Notify the Console Manager that the Command Prompt
  688. // service has REGISTERED
  689. //
  690. Status = IoMgrHandleEvent(
  691. IO_MGR_EVENT_REGISTER_SAC_CMD_EVENT,
  692. NULL,
  693. NULL
  694. );
  695. }
  696. #if DEBUG_DISPATCH
  697. ASSERT(NT_SUCCESS(Status));
  698. #endif
  699. break;
  700. }
  701. case IOCTL_SAC_UNREGISTER_CMD_EVENT: {
  702. Status = STATUS_UNSUCCESSFUL;
  703. #if ENABLE_CMD_SESSION_PERMISSION_CHECKING
  704. //
  705. // If we are not able to launch cmd sessions,
  706. // then notify that we cannot peform this action
  707. //
  708. if (! IsCommandConsoleLaunchingEnabled()) {
  709. break;
  710. }
  711. #endif
  712. #if ENABLE_SERVICE_FILE_OBJECT_CHECKING
  713. //
  714. // If the current process is the one that registered
  715. // the cmd event info,
  716. // then unregister
  717. //
  718. if (! IsCmdEventRegistrationProcess(IrpSp->FileObject)) {
  719. break;
  720. }
  721. #endif
  722. Status = UnregisterSacCmdEvent(IrpSp->FileObject);
  723. if (NT_SUCCESS(Status)) {
  724. //
  725. // Notify the Console Manager that the Command Prompt
  726. // service has UNREGISTERED
  727. //
  728. Status = IoMgrHandleEvent(
  729. IO_MGR_EVENT_UNREGISTER_SAC_CMD_EVENT,
  730. NULL,
  731. NULL
  732. );
  733. }
  734. #if DEBUG_DISPATCH
  735. ASSERT(NT_SUCCESS(Status));
  736. #endif
  737. break;
  738. }
  739. default:
  740. Status = STATUS_INVALID_DEVICE_REQUEST;
  741. break;
  742. }
  743. Irp->IoStatus.Status = Status;
  744. Irp->IoStatus.Information = ResponseLength;
  745. if (Status != STATUS_PENDING) {
  746. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  747. }
  748. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  749. KdPrint(("SAC DispatchDeviceControl: Exiting with status 0x%x\n", Status)));
  750. return Status;
  751. } // DispatchDeviceControl
  752. NTSTATUS
  753. DispatchShutdownControl(
  754. IN PDEVICE_OBJECT DeviceObject,
  755. IN PIRP Irp
  756. )
  757. /*++
  758. Routine Description:
  759. This is the dispatch routine which receives the shutdown IRP.
  760. Arguments:
  761. DeviceObject - Pointer to device object for target device
  762. Irp - Pointer to I/O request packet
  763. Return Value:
  764. NTSTATUS -- Indicates whether the request was successfully queued.
  765. --*/
  766. {
  767. UNREFERENCED_PARAMETER(DeviceObject);
  768. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchShutdownControl: Entering.\n")));
  769. //
  770. // Notify any user.
  771. //
  772. IoMgrHandleEvent(
  773. IO_MGR_EVENT_SHUTDOWN,
  774. NULL,
  775. NULL
  776. );
  777. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchShutdownControl: Exiting.\n")));
  778. Irp->IoStatus.Status = STATUS_SUCCESS;
  779. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  780. return STATUS_SUCCESS;
  781. } // DispatchShutdownControl
  782. NTSTATUS
  783. DispatchCreate(
  784. IN PSAC_DEVICE_CONTEXT DeviceContext,
  785. IN PIRP Irp
  786. )
  787. /*++
  788. Routine Description:
  789. This is the dispatch routine for SAC IOCTL Create
  790. Arguments:
  791. DeviceContext - Pointer to device context for target device
  792. Irp - Pointer to I/O request packet
  793. Return Value:
  794. NTSTATUS -- Indicates whether the request was successfully queued.
  795. --*/
  796. {
  797. NTSTATUS Status;
  798. PIO_STACK_LOCATION IrpSp;
  799. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchCreate: Entering.\n")));
  800. //
  801. // Check to see if we are done initializing.
  802. //
  803. if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) {
  804. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  805. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  806. Status = STATUS_INVALID_DEVICE_STATE;
  807. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  808. KdPrint(("SAC DispatchCreate: Exiting with status 0x%x\n", Status)));
  809. //
  810. // We need to catch this state
  811. //
  812. ASSERT(0);
  813. return Status;
  814. }
  815. //
  816. // Get a pointer to the current stack location in the IRP. This is where
  817. // the function codes and parameters are stored.
  818. //
  819. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  820. //
  821. // Case on the function that is being performed by the requestor. If the
  822. // operation is a valid one for this device, then make it look like it was
  823. // successfully completed, where possible.
  824. //
  825. switch (IrpSp->MajorFunction) {
  826. //
  827. // The Create function opens a connection to this device.
  828. //
  829. case IRP_MJ_CREATE:
  830. Status = STATUS_SUCCESS;
  831. break;
  832. default:
  833. Status = STATUS_INVALID_DEVICE_REQUEST;
  834. }
  835. Irp->IoStatus.Status = Status;
  836. Irp->IoStatus.Information = 0;
  837. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  838. //
  839. // Return the immediate status code to the caller.
  840. //
  841. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  842. KdPrint(("SAC DispatchCreate: Exiting with status 0x%x\n", Status)));
  843. //
  844. // We need to catch this state
  845. //
  846. ASSERT(NT_SUCCESS(Status));
  847. return Status;
  848. }
  849. NTSTATUS
  850. DispatchClose(
  851. IN PSAC_DEVICE_CONTEXT DeviceContext,
  852. IN PIRP Irp
  853. )
  854. /*++
  855. Routine Description:
  856. This is the dispatch routine for SAC IOCTL Close
  857. Arguments:
  858. DeviceContext - Pointer to device context for target device
  859. Irp - Pointer to I/O request packet
  860. Return Value:
  861. NTSTATUS -- Indicates whether the request was successfully queued.
  862. --*/
  863. {
  864. NTSTATUS Status;
  865. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC DispatchClose: Entering.\n")));
  866. //
  867. // Check to see if we are done initializing.
  868. //
  869. if (!GlobalDataInitialized || !DeviceContext->InitializedAndReady) {
  870. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  871. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  872. Status = STATUS_INVALID_DEVICE_STATE;
  873. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE,
  874. KdPrint(("SAC DispatchClose: Exiting with status 0x%x\n", Status)));
  875. return Status;
  876. }
  877. Irp->IoStatus.Status = STATUS_SUCCESS;
  878. IoCompleteRequest(Irp, DeviceContext->PriorityBoost);
  879. Status = STATUS_SUCCESS;
  880. return Status;
  881. }