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

723 lines
16 KiB

  1. /*************************************************************************
  2. *
  3. * dispatch.c
  4. *
  5. * This module contains the dispatch routines for the TERMDD driver.
  6. *
  7. * Copyright 1998, Microsoft.
  8. *
  9. *************************************************************************/
  10. /*
  11. * Includes
  12. */
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. #include "ptdrvcom.h"
  16. NTSTATUS
  17. IcaDeviceControl (
  18. IN PIRP Irp,
  19. IN PIO_STACK_LOCATION IrpSp
  20. );
  21. NTSTATUS
  22. IcaCreate (
  23. IN PIRP Irp,
  24. IN PIO_STACK_LOCATION IrpSp
  25. );
  26. NTSTATUS
  27. IcaRead (
  28. IN PIRP Irp,
  29. IN PIO_STACK_LOCATION IrpSp
  30. );
  31. NTSTATUS
  32. IcaWrite (
  33. IN PIRP Irp,
  34. IN PIO_STACK_LOCATION IrpSp
  35. );
  36. NTSTATUS
  37. IcaWriteSync (
  38. IN PIRP Irp,
  39. IN PIO_STACK_LOCATION IrpSp
  40. );
  41. NTSTATUS
  42. IcaCleanup (
  43. IN PIRP Irp,
  44. IN PIO_STACK_LOCATION IrpSp
  45. );
  46. NTSTATUS
  47. IcaClose (
  48. IN PIRP Irp,
  49. IN PIO_STACK_LOCATION IrpSp
  50. );
  51. NTSTATUS
  52. IcaDispatch (
  53. IN PDEVICE_OBJECT DeviceObject,
  54. IN PIRP Irp
  55. )
  56. /*++
  57. Routine Description:
  58. This is the dispatch routine for ICA.
  59. Arguments:
  60. DeviceObject - Pointer to device object for target device
  61. Irp - Pointer to I/O request packet
  62. Return Value:
  63. NTSTATUS -- Indicates whether the request was successfully queued.
  64. --*/
  65. {
  66. PIO_STACK_LOCATION irpSp;
  67. KIRQL saveIrql;
  68. NTSTATUS Status;
  69. irpSp = IoGetCurrentIrpStackLocation( Irp );
  70. /*
  71. * Fan out the IRPs based on device type
  72. */
  73. if (*((ULONG *)(DeviceObject->DeviceExtension)) != DEV_TYPE_TERMDD)
  74. {
  75. /*
  76. * This is for the port driver part of TermDD
  77. */
  78. switch ( irpSp->MajorFunction ) {
  79. case IRP_MJ_CREATE:
  80. return PtCreate(DeviceObject, Irp);
  81. case IRP_MJ_CLOSE:
  82. return PtClose(DeviceObject, Irp);
  83. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  84. return PtInternalDeviceControl(DeviceObject, Irp);
  85. case IRP_MJ_DEVICE_CONTROL:
  86. return PtDeviceControl(DeviceObject, Irp);
  87. case IRP_MJ_FLUSH_BUFFERS:
  88. return STATUS_NOT_IMPLEMENTED;
  89. case IRP_MJ_PNP:
  90. return PtPnP(DeviceObject, Irp);
  91. case IRP_MJ_POWER:
  92. return PtPower(DeviceObject, Irp);
  93. case IRP_MJ_SYSTEM_CONTROL:
  94. return PtSystemControl(DeviceObject, Irp);
  95. default:
  96. KdPrint(( "IcaDispatch: Invalid major function FOR PORT DRIVER %lx\n",
  97. irpSp->MajorFunction ));
  98. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  99. IoCompleteRequest( Irp, IcaPriorityBoost );
  100. return STATUS_NOT_IMPLEMENTED;
  101. }
  102. }
  103. else
  104. {
  105. switch ( irpSp->MajorFunction ) {
  106. case IRP_MJ_WRITE:
  107. ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Write.Length ) ==
  108. FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.OutputBufferLength ) );
  109. ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Write.Key ) ==
  110. FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.InputBufferLength ) );
  111. saveIrql = KeGetCurrentIrql();
  112. irpSp->Parameters.Write.Key = 0;
  113. Status = IcaWrite( Irp, irpSp );
  114. ASSERT( KeGetCurrentIrql( ) == saveIrql );
  115. return Status;
  116. case IRP_MJ_READ:
  117. ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Read.Length ) ==
  118. FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.OutputBufferLength ) );
  119. ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Read.Key ) ==
  120. FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.InputBufferLength ) );
  121. saveIrql = KeGetCurrentIrql();
  122. irpSp->Parameters.Read.Key = 0;
  123. Status = IcaRead( Irp, irpSp );
  124. ASSERT( KeGetCurrentIrql( ) == saveIrql );
  125. return Status;
  126. case IRP_MJ_DEVICE_CONTROL:
  127. saveIrql = KeGetCurrentIrql();
  128. Status = IcaDeviceControl( Irp, irpSp );
  129. ASSERT( KeGetCurrentIrql( ) == saveIrql );
  130. Irp->IoStatus.Status = Status;
  131. IoCompleteRequest( Irp, IcaPriorityBoost );
  132. return( Status );
  133. case IRP_MJ_CREATE:
  134. Status = IcaCreate( Irp, irpSp );
  135. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  136. Irp->IoStatus.Status = Status;
  137. IoCompleteRequest( Irp, IcaPriorityBoost );
  138. return Status;
  139. case IRP_MJ_FLUSH_BUFFERS :
  140. Status = IcaWriteSync( Irp, irpSp );
  141. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  142. Irp->IoStatus.Status = Status;
  143. IoCompleteRequest( Irp, IcaPriorityBoost );
  144. return Status;
  145. case IRP_MJ_CLEANUP:
  146. Status = IcaCleanup( Irp, irpSp );
  147. Irp->IoStatus.Status = Status;
  148. IoCompleteRequest( Irp, IcaPriorityBoost );
  149. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  150. return Status;
  151. case IRP_MJ_CLOSE:
  152. Status = IcaClose( Irp, irpSp );
  153. Irp->IoStatus.Status = Status;
  154. IoCompleteRequest( Irp, IcaPriorityBoost );
  155. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  156. return Status;
  157. case IRP_MJ_QUERY_SECURITY:
  158. Status = STATUS_INVALID_DEVICE_REQUEST;
  159. Irp->IoStatus.Status = Status;
  160. IoCompleteRequest( Irp, IcaPriorityBoost );
  161. return Status;
  162. default:
  163. Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  164. IoCompleteRequest( Irp, IcaPriorityBoost );
  165. return STATUS_NOT_IMPLEMENTED;
  166. }
  167. }
  168. }
  169. BOOLEAN
  170. IcaIsSystemProcessRequest (
  171. PIRP Irp,
  172. PIO_STACK_LOCATION IrpSp)
  173. {
  174. PACCESS_STATE accessState;
  175. PIO_SECURITY_CONTEXT securityContext;
  176. PACCESS_TOKEN accessToken;
  177. PTOKEN_USER userId = NULL;
  178. BOOLEAN result = FALSE;
  179. NTSTATUS status = STATUS_SUCCESS;
  180. PSID systemSid;
  181. ASSERT(Irp != NULL);
  182. ASSERT(IrpSp != NULL);
  183. securityContext = IrpSp->Parameters.Create.SecurityContext;
  184. ASSERT(securityContext != NULL);
  185. //
  186. // Get the well-known system SID.
  187. //
  188. systemSid = ExAllocatePoolWithTag(
  189. PagedPool,
  190. RtlLengthRequiredSid(1),
  191. ICA_POOL_TAG
  192. );
  193. if (systemSid) {
  194. SID_IDENTIFIER_AUTHORITY identifierAuthority = SECURITY_NT_AUTHORITY;
  195. *(RtlSubAuthoritySid(systemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID;
  196. status = RtlInitializeSid(systemSid, &identifierAuthority, (UCHAR)1);
  197. }
  198. else {
  199. status = STATUS_INSUFFICIENT_RESOURCES;
  200. }
  201. //
  202. // Get the non-impersonated, primary token for the IRP request.
  203. //
  204. accessState = securityContext->AccessState;
  205. accessToken = accessState->SubjectSecurityContext.PrimaryToken;
  206. //
  207. // We got the system SID. Now compare the caller's SID.
  208. //
  209. if (NT_SUCCESS(status) && accessToken){
  210. //
  211. // Get the user ID associated with the primary token for the process
  212. // that generated the IRP.
  213. //
  214. status = SeQueryInformationToken(
  215. accessToken,
  216. TokenUser,
  217. &userId
  218. );
  219. //
  220. // Do the comparison.
  221. //
  222. if (NT_SUCCESS(status)) {
  223. result = RtlEqualSid(systemSid, userId->User.Sid);
  224. ExFreePool(userId);
  225. }
  226. }
  227. if (systemSid) {
  228. ExFreePool(systemSid);
  229. }
  230. return result;
  231. }
  232. NTSTATUS
  233. IcaCreate (
  234. IN PIRP Irp,
  235. IN PIO_STACK_LOCATION IrpSp
  236. )
  237. /*++
  238. Routine Description:
  239. This is the routine that handles Create IRPs in ICA.
  240. Arguments:
  241. Irp - Pointer to I/O request packet.
  242. IrpSp - pointer to the IO stack location to use for this request.
  243. Return Value:
  244. NTSTATUS -- Indicates whether the request was successfully queued.
  245. --*/
  246. {
  247. PICA_OPEN_PACKET openPacket;
  248. PFILE_FULL_EA_INFORMATION eaBuffer;
  249. PFILE_OBJECT pConnectFileObject;
  250. PICA_CONNECTION pConnect;
  251. NTSTATUS Status;
  252. PAGED_CODE( );
  253. // Save result in FsContext2: if the requestor is system process or not
  254. IrpSp->FileObject->FsContext2 = (VOID*) IcaIsSystemProcessRequest(Irp, IrpSp);
  255. /*
  256. * Find the open packet from the EA buffer in the system buffer of
  257. * the associated IRP. If no EA buffer was specified, then this
  258. * is a request to open a new ICA connection.
  259. */
  260. eaBuffer = Irp->AssociatedIrp.SystemBuffer;
  261. if ( eaBuffer == NULL ) {
  262. return( IcaCreateConnection( Irp, IrpSp ) );
  263. }
  264. if (eaBuffer->EaValueLength < sizeof(ICA_OPEN_PACKET)) {
  265. ASSERT(FALSE);
  266. return STATUS_INVALID_PARAMETER;
  267. }
  268. openPacket = (PICA_OPEN_PACKET)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);
  269. /*
  270. * Validate parameters in the open packet.
  271. */
  272. if ( openPacket->OpenType != IcaOpen_Stack &&
  273. openPacket->OpenType != IcaOpen_Channel ) {
  274. ASSERT(FALSE);
  275. return STATUS_INVALID_PARAMETER;
  276. }
  277. /*
  278. * Use the specified ICA connection handle to get a pointer to
  279. * the connection object.
  280. */
  281. Status = ObReferenceObjectByHandle(
  282. openPacket->IcaHandle,
  283. STANDARD_RIGHTS_READ, // DesiredAccess
  284. *IoFileObjectType,
  285. Irp->RequestorMode,
  286. (PVOID *)&pConnectFileObject,
  287. NULL
  288. );
  289. if ( !NT_SUCCESS(Status) )
  290. return( Status );
  291. /*
  292. * Ensure what we have is a connection object
  293. */
  294. if (pConnectFileObject->DeviceObject != IcaDeviceObject) {
  295. ASSERT(FALSE);
  296. ObDereferenceObject( pConnectFileObject );
  297. return STATUS_INVALID_PARAMETER;
  298. }
  299. pConnect = pConnectFileObject->FsContext;
  300. ASSERT( pConnect->Header.Type == IcaType_Connection );
  301. if ( pConnect->Header.Type != IcaType_Connection ) {
  302. ObDereferenceObject( pConnectFileObject );
  303. return( STATUS_INVALID_CONNECTION );
  304. }
  305. /*
  306. * Create a new stack or new channel
  307. */
  308. IcaReferenceConnection( pConnect );
  309. switch ( openPacket->OpenType ) {
  310. case IcaOpen_Stack :
  311. Status = IcaCreateStack( pConnect, openPacket, Irp, IrpSp );
  312. break;
  313. case IcaOpen_Channel :
  314. Status = IcaCreateChannel( pConnect, openPacket, Irp, IrpSp );
  315. break;
  316. }
  317. IcaDereferenceConnection( pConnect );
  318. ObDereferenceObject( pConnectFileObject );
  319. return( Status );
  320. }
  321. NTSTATUS
  322. IcaRead (
  323. IN PIRP Irp,
  324. IN PIO_STACK_LOCATION IrpSp
  325. )
  326. /*++
  327. Routine Description:
  328. This is the read routine for ICA.
  329. Arguments:
  330. Irp - Pointer to I/O request packet
  331. IrpSp - pointer to the stack location to use for this request.
  332. Return Value:
  333. NTSTATUS -- Indicates whether the request was successfully queued.
  334. --*/
  335. {
  336. PICA_HEADER pIcaHeader;
  337. NTSTATUS Status;
  338. /*
  339. * Get pointer to ICA object header.
  340. * If a read routine is not defined, return an error.
  341. */
  342. pIcaHeader = IrpSp->FileObject->FsContext;
  343. if ( pIcaHeader->pDispatchTable[IRP_MJ_READ] == NULL ) {
  344. Status = STATUS_INVALID_DEVICE_REQUEST;
  345. Irp->IoStatus.Status = Status;
  346. IoCompleteRequest( Irp, IcaPriorityBoost );
  347. return( Status );
  348. }
  349. /*
  350. * Call the read routine for this ICA object.
  351. */
  352. Status = (pIcaHeader->pDispatchTable[IRP_MJ_READ])(
  353. pIcaHeader, Irp, IrpSp );
  354. return( Status );
  355. }
  356. NTSTATUS
  357. IcaWrite (
  358. IN PIRP Irp,
  359. IN PIO_STACK_LOCATION IrpSp
  360. )
  361. /*++
  362. Routine Description:
  363. This is the write routine for ICA.
  364. Arguments:
  365. Irp - Pointer to I/O request packet
  366. IrpSp - pointer to the stack location to use for this request.
  367. Return Value:
  368. NTSTATUS -- Indicates whether the request was successfully queued.
  369. --*/
  370. {
  371. PICA_HEADER pIcaHeader;
  372. NTSTATUS Status;
  373. /*
  374. * Get pointer to ICA object header.
  375. * If a write routine is not defined, return an error.
  376. */
  377. pIcaHeader = IrpSp->FileObject->FsContext;
  378. if ( pIcaHeader->pDispatchTable[IRP_MJ_WRITE] == NULL ) {
  379. Status = STATUS_INVALID_DEVICE_REQUEST;
  380. Irp->IoStatus.Status = Status;
  381. IoCompleteRequest( Irp, IcaPriorityBoost );
  382. return( Status );
  383. }
  384. /*
  385. * Call the write routine for this ICA object.
  386. */
  387. Status = (pIcaHeader->pDispatchTable[IRP_MJ_WRITE])(
  388. pIcaHeader, Irp, IrpSp );
  389. return( Status );
  390. }
  391. NTSTATUS
  392. IcaWriteSync (
  393. IN PIRP Irp,
  394. IN PIO_STACK_LOCATION IrpSp
  395. )
  396. /*++
  397. Routine Description:
  398. This is the flush routine for ICA.
  399. Arguments:
  400. Irp - Pointer to I/O request packet
  401. IrpSp - pointer to the stack location to use for this request.
  402. Return Value:
  403. NTSTATUS -- Indicates whether the request was successfully queued.
  404. --*/
  405. {
  406. PICA_HEADER pIcaHeader;
  407. NTSTATUS Status;
  408. /*
  409. * Get pointer to ICA object header.
  410. * If a flush routine is not defined, return an error.
  411. */
  412. pIcaHeader = IrpSp->FileObject->FsContext;
  413. if ( pIcaHeader->pDispatchTable[IRP_MJ_FLUSH_BUFFERS] == NULL )
  414. return( STATUS_INVALID_DEVICE_REQUEST );
  415. /*
  416. * Call the flush routine for this ICA object.
  417. */
  418. Status = (pIcaHeader->pDispatchTable[IRP_MJ_FLUSH_BUFFERS])(
  419. pIcaHeader, Irp, IrpSp );
  420. return( Status );
  421. }
  422. NTSTATUS
  423. IcaDeviceControl (
  424. IN PIRP Irp,
  425. IN PIO_STACK_LOCATION IrpSp
  426. )
  427. /*++
  428. Routine Description:
  429. This is the dispatch routine for ICA IOCTLs.
  430. Arguments:
  431. Irp - Pointer to I/O request packet.
  432. IrpSp - pointer to the stack location to use for this request.
  433. Return Value:
  434. NTSTATUS -- Indicates whether the request was successfully queued.
  435. --*/
  436. {
  437. PICA_HEADER pIcaHeader;
  438. NTSTATUS Status;
  439. /*
  440. * Get pointer to ICA object header.
  441. * If a device control routine is not defined, return an error.
  442. */
  443. pIcaHeader = IrpSp->FileObject->FsContext;
  444. if ( pIcaHeader->pDispatchTable[IRP_MJ_DEVICE_CONTROL] == NULL )
  445. return( STATUS_INVALID_DEVICE_REQUEST );
  446. /*
  447. * Call the device control routine for this ICA object.
  448. */
  449. Status = (pIcaHeader->pDispatchTable[IRP_MJ_DEVICE_CONTROL])(
  450. pIcaHeader, Irp, IrpSp );
  451. return( Status );
  452. }
  453. NTSTATUS
  454. IcaCleanup (
  455. IN PIRP Irp,
  456. IN PIO_STACK_LOCATION IrpSp
  457. )
  458. /*++
  459. Routine Description:
  460. This is the routine that handles Cleanup IRPs in ICA.
  461. Arguments:
  462. Irp - Pointer to I/O request packet.
  463. IrpSp - pointer to the IO stack location to use for this request.
  464. Return Value:
  465. NTSTATUS --
  466. --*/
  467. {
  468. PICA_HEADER pIcaHeader;
  469. NTSTATUS Status;
  470. /*
  471. * Get pointer to ICA object header.
  472. * If a cleanup routine is not defined, return an error.
  473. */
  474. pIcaHeader = IrpSp->FileObject->FsContext;
  475. if ( pIcaHeader->pDispatchTable[IRP_MJ_CLEANUP] == NULL )
  476. return( STATUS_INVALID_DEVICE_REQUEST );
  477. Status = (pIcaHeader->pDispatchTable[IRP_MJ_CLEANUP])(
  478. pIcaHeader, Irp, IrpSp );
  479. return( Status );
  480. }
  481. NTSTATUS
  482. IcaClose (
  483. IN PIRP Irp,
  484. IN PIO_STACK_LOCATION IrpSp
  485. )
  486. /*++
  487. Routine Description:
  488. This is the routine that handles Close IRPs in ICA. It
  489. dereferences the endpoint specified in the IRP, which will result in
  490. the endpoint being freed when all other references go away.
  491. Arguments:
  492. Irp - Pointer to I/O request packet.
  493. IrpSp - pointer to the IO stack location to use for this request.
  494. Return Value:
  495. NTSTATUS -- Indicates whether the request was successfully queued.
  496. --*/
  497. {
  498. PICA_HEADER pIcaHeader;
  499. NTSTATUS Status;
  500. PAGED_CODE( );
  501. /*
  502. * Get pointer to ICA object header.
  503. * If a close routine is not defined, return an error.
  504. */
  505. pIcaHeader = IrpSp->FileObject->FsContext;
  506. if ( pIcaHeader->pDispatchTable[IRP_MJ_CLOSE] == NULL )
  507. return( STATUS_INVALID_DEVICE_REQUEST );
  508. Status = (pIcaHeader->pDispatchTable[IRP_MJ_CLOSE])(
  509. pIcaHeader, Irp, IrpSp );
  510. return( Status );
  511. }