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.

909 lines
23 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. BOOLEAN *pbSystemClient)
  174. {
  175. PACCESS_STATE accessState;
  176. PIO_SECURITY_CONTEXT securityContext;
  177. PACCESS_TOKEN CallerAccessToken;
  178. PACCESS_TOKEN ClientAccessToken;
  179. PTOKEN_USER userId = NULL;
  180. BOOLEAN result = FALSE;
  181. NTSTATUS status = STATUS_SUCCESS;
  182. PSID systemSid;
  183. ASSERT(Irp != NULL);
  184. ASSERT(IrpSp != NULL);
  185. ASSERT(pbSystemClient != NULL);
  186. *pbSystemClient = FALSE;
  187. securityContext = IrpSp->Parameters.Create.SecurityContext;
  188. ASSERT(securityContext != NULL);
  189. //
  190. // Get the well-known system SID.
  191. //
  192. systemSid = ExAllocatePoolWithTag(
  193. PagedPool,
  194. RtlLengthRequiredSid(1),
  195. ICA_POOL_TAG
  196. );
  197. if (systemSid) {
  198. SID_IDENTIFIER_AUTHORITY identifierAuthority = SECURITY_NT_AUTHORITY;
  199. *(RtlSubAuthoritySid(systemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID;
  200. status = RtlInitializeSid(systemSid, &identifierAuthority, (UCHAR)1);
  201. }
  202. else {
  203. status = STATUS_INSUFFICIENT_RESOURCES;
  204. }
  205. accessState = securityContext->AccessState;
  206. //
  207. // Get the non-impersonated, primary token for the IRP request.
  208. //
  209. CallerAccessToken = accessState->SubjectSecurityContext.PrimaryToken;
  210. //
  211. // get the impersonated token.
  212. //
  213. ClientAccessToken = accessState->SubjectSecurityContext.ClientToken;
  214. //
  215. // We got the system SID. Now compare the caller and client's SIDs.
  216. //
  217. if (NT_SUCCESS(status) && CallerAccessToken){
  218. //
  219. // Get the user ID associated with the primary token for the process
  220. // that generated the IRP.
  221. //
  222. status = SeQueryInformationToken(
  223. CallerAccessToken,
  224. TokenUser,
  225. &userId
  226. );
  227. //
  228. // Do the comparison.
  229. //
  230. if (NT_SUCCESS(status)) {
  231. result = RtlEqualSid(systemSid, userId->User.Sid);
  232. ExFreePool(userId);
  233. }
  234. if (ClientAccessToken)
  235. {
  236. //
  237. // Get the user ID associated with the client token (impersonation token)
  238. //
  239. status = SeQueryInformationToken(
  240. ClientAccessToken,
  241. TokenUser,
  242. &userId
  243. );
  244. //
  245. // Do the comparison.
  246. //
  247. if (NT_SUCCESS(status)) {
  248. *pbSystemClient = RtlEqualSid(systemSid, userId->User.Sid);
  249. ExFreePool(userId);
  250. }
  251. }
  252. else
  253. {
  254. //
  255. // we dont have ClientAccessToken, impling there is no impersonation going on.
  256. // in this case lets set *pbSystemClient = caller
  257. //
  258. *pbSystemClient = result;
  259. }
  260. }
  261. if (systemSid) {
  262. ExFreePool(systemSid);
  263. }
  264. return result;
  265. }
  266. NTSTATUS
  267. IcaCreate (
  268. IN PIRP Irp,
  269. IN PIO_STACK_LOCATION IrpSp
  270. )
  271. /*++
  272. Routine Description:
  273. This is the routine that handles Create IRPs in ICA.
  274. Arguments:
  275. Irp - Pointer to I/O request packet.
  276. IrpSp - pointer to the IO stack location to use for this request.
  277. Return Value:
  278. NTSTATUS -- Indicates whether the request was successfully queued.
  279. --*/
  280. {
  281. PICA_OPEN_PACKET openPacket;
  282. PFILE_FULL_EA_INFORMATION eaBuffer;
  283. PFILE_OBJECT pConnectFileObject;
  284. PICA_CONNECTION pConnect;
  285. NTSTATUS Status;
  286. BOOLEAN bSystemCaller; // was the caller of this IRP system?
  287. BOOLEAN bSystemClient; // was the client of this IRP system?
  288. PAGED_CODE( );
  289. // Save result in FsContext2: if the requestor is system process or not
  290. bSystemCaller = IcaIsSystemProcessRequest(Irp, IrpSp, &bSystemClient);
  291. IrpSp->FileObject->FsContext2 = (VOID *)bSystemCaller;
  292. /*
  293. * Find the open packet from the EA buffer in the system buffer of
  294. * the associated IRP. If no EA buffer was specified, then this
  295. * is a request to open a new ICA connection.
  296. */
  297. eaBuffer = Irp->AssociatedIrp.SystemBuffer;
  298. if ( eaBuffer == NULL ) {
  299. if ( (Irp->RequestorMode != KernelMode) && !bSystemCaller) {
  300. return STATUS_ACCESS_DENIED;
  301. }
  302. return( IcaCreateConnection( Irp, IrpSp ) );
  303. }
  304. if (eaBuffer->EaValueLength < sizeof(ICA_OPEN_PACKET)) {
  305. ASSERT(FALSE);
  306. return STATUS_INVALID_PARAMETER;
  307. }
  308. openPacket = (PICA_OPEN_PACKET)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);
  309. /*
  310. * Validate parameters in the open packet.
  311. */
  312. if ( openPacket->OpenType != IcaOpen_Stack &&
  313. openPacket->OpenType != IcaOpen_Channel ) {
  314. ASSERT(FALSE);
  315. return STATUS_INVALID_PARAMETER;
  316. }
  317. /*
  318. * If this open is not for a virtual channel then the caller has to be system or kernel mode.
  319. */
  320. if ((openPacket->OpenType == IcaOpen_Stack) || openPacket->TypeInfo.ChannelClass != Channel_Virtual) {
  321. if ( (Irp->RequestorMode != KernelMode) && !bSystemCaller) {
  322. return STATUS_ACCESS_DENIED;
  323. }
  324. }
  325. /*
  326. * if we are creating a Virtual Channel, then add some more restriction on security. as an RPC caller
  327. * can cause us to open the v channel, mark the object so if the either caller or client is non system.
  328. */
  329. if (openPacket->OpenType == IcaOpen_Channel && openPacket->TypeInfo.ChannelClass == Channel_Virtual)
  330. {
  331. if (!_stricmp(VIRTUAL_THINWIRE, openPacket->TypeInfo.VirtualName))
  332. {
  333. // THIS IS A UGLY SPECIAL CASE. IN SHADOWWORKER, THIS CHANNEL IS CREATED WHILE IMPERSONATED.
  334. // BUT WE DONT LET THIS CHANNLE TO BE OPENED BY RPCOPENVIRTUAL CHANNEL. SO LETS MARK MAKE AN EXCEPTION FOR THIS.
  335. }
  336. else
  337. {
  338. IrpSp->FileObject->FsContext2 = (VOID *)(BOOLEAN)(bSystemClient && bSystemCaller);
  339. }
  340. }
  341. /*
  342. * Use the specified ICA connection handle to get a pointer to
  343. * the connection object.
  344. */
  345. Status = ObReferenceObjectByHandle(
  346. openPacket->IcaHandle,
  347. STANDARD_RIGHTS_READ, // DesiredAccess
  348. *IoFileObjectType,
  349. Irp->RequestorMode,
  350. (PVOID *)&pConnectFileObject,
  351. NULL
  352. );
  353. if ( !NT_SUCCESS(Status) )
  354. return( Status );
  355. /*
  356. * Ensure what we have is a connection object
  357. */
  358. if (pConnectFileObject->DeviceObject != IcaDeviceObject) {
  359. ASSERT(FALSE);
  360. ObDereferenceObject( pConnectFileObject );
  361. return STATUS_INVALID_PARAMETER;
  362. }
  363. pConnect = pConnectFileObject->FsContext;
  364. ASSERT( pConnect->Header.Type == IcaType_Connection );
  365. if ( pConnect->Header.Type != IcaType_Connection ) {
  366. ObDereferenceObject( pConnectFileObject );
  367. return( STATUS_INVALID_CONNECTION );
  368. }
  369. /*
  370. * Create a new stack or new channel
  371. */
  372. IcaReferenceConnection( pConnect );
  373. switch ( openPacket->OpenType ) {
  374. case IcaOpen_Stack :
  375. Status = IcaCreateStack( pConnect, openPacket, Irp, IrpSp );
  376. break;
  377. case IcaOpen_Channel :
  378. Status = IcaCreateChannel( pConnect, openPacket, Irp, IrpSp );
  379. break;
  380. }
  381. IcaDereferenceConnection( pConnect );
  382. ObDereferenceObject( pConnectFileObject );
  383. return( Status );
  384. }
  385. NTSTATUS
  386. IcaRead (
  387. IN PIRP Irp,
  388. IN PIO_STACK_LOCATION IrpSp
  389. )
  390. /*++
  391. Routine Description:
  392. This is the read routine for ICA.
  393. Arguments:
  394. Irp - Pointer to I/O request packet
  395. IrpSp - pointer to the stack location to use for this request.
  396. Return Value:
  397. NTSTATUS -- Indicates whether the request was successfully queued.
  398. --*/
  399. {
  400. PICA_HEADER pIcaHeader;
  401. NTSTATUS Status;
  402. /*
  403. * Get pointer to ICA object header.
  404. * If a read routine is not defined, return an error.
  405. */
  406. pIcaHeader = IrpSp->FileObject->FsContext;
  407. if ( pIcaHeader->pDispatchTable[IRP_MJ_READ] == NULL ) {
  408. Status = STATUS_INVALID_DEVICE_REQUEST;
  409. Irp->IoStatus.Status = Status;
  410. IoCompleteRequest( Irp, IcaPriorityBoost );
  411. return( Status );
  412. }
  413. /*
  414. * Call the read routine for this ICA object.
  415. */
  416. Status = (pIcaHeader->pDispatchTable[IRP_MJ_READ])(
  417. pIcaHeader, Irp, IrpSp );
  418. return( Status );
  419. }
  420. NTSTATUS
  421. IcaWrite (
  422. IN PIRP Irp,
  423. IN PIO_STACK_LOCATION IrpSp
  424. )
  425. /*++
  426. Routine Description:
  427. This is the write routine for ICA.
  428. Arguments:
  429. Irp - Pointer to I/O request packet
  430. IrpSp - pointer to the stack location to use for this request.
  431. Return Value:
  432. NTSTATUS -- Indicates whether the request was successfully queued.
  433. --*/
  434. {
  435. PICA_HEADER pIcaHeader;
  436. NTSTATUS Status;
  437. /*
  438. * Get pointer to ICA object header.
  439. * If a write routine is not defined, return an error.
  440. */
  441. pIcaHeader = IrpSp->FileObject->FsContext;
  442. if ( pIcaHeader->pDispatchTable[IRP_MJ_WRITE] == NULL ) {
  443. Status = STATUS_INVALID_DEVICE_REQUEST;
  444. Irp->IoStatus.Status = Status;
  445. IoCompleteRequest( Irp, IcaPriorityBoost );
  446. return( Status );
  447. }
  448. /*
  449. * Call the write routine for this ICA object.
  450. */
  451. Status = (pIcaHeader->pDispatchTable[IRP_MJ_WRITE])(
  452. pIcaHeader, Irp, IrpSp );
  453. return( Status );
  454. }
  455. NTSTATUS
  456. IcaWriteSync (
  457. IN PIRP Irp,
  458. IN PIO_STACK_LOCATION IrpSp
  459. )
  460. /*++
  461. Routine Description:
  462. This is the flush routine for ICA.
  463. Arguments:
  464. Irp - Pointer to I/O request packet
  465. IrpSp - pointer to the stack location to use for this request.
  466. Return Value:
  467. NTSTATUS -- Indicates whether the request was successfully queued.
  468. --*/
  469. {
  470. PICA_HEADER pIcaHeader;
  471. NTSTATUS Status;
  472. /*
  473. * Get pointer to ICA object header.
  474. * If a flush routine is not defined, return an error.
  475. */
  476. pIcaHeader = IrpSp->FileObject->FsContext;
  477. if ( pIcaHeader->pDispatchTable[IRP_MJ_FLUSH_BUFFERS] == NULL )
  478. return( STATUS_INVALID_DEVICE_REQUEST );
  479. /*
  480. * Call the flush routine for this ICA object.
  481. */
  482. Status = (pIcaHeader->pDispatchTable[IRP_MJ_FLUSH_BUFFERS])(
  483. pIcaHeader, Irp, IrpSp );
  484. return( Status );
  485. }
  486. NTSTATUS
  487. IcaDeviceControl (
  488. IN PIRP Irp,
  489. IN PIO_STACK_LOCATION IrpSp
  490. )
  491. /*++
  492. Routine Description:
  493. This is the dispatch routine for ICA IOCTLs.
  494. Arguments:
  495. Irp - Pointer to I/O request packet.
  496. IrpSp - pointer to the stack location to use for this request.
  497. Return Value:
  498. NTSTATUS -- Indicates whether the request was successfully queued.
  499. --*/
  500. {
  501. PICA_HEADER pIcaHeader;
  502. NTSTATUS Status;
  503. /*
  504. * Get pointer to ICA object header.
  505. * If a device control routine is not defined, return an error.
  506. */
  507. pIcaHeader = IrpSp->FileObject->FsContext;
  508. if ( pIcaHeader->pDispatchTable[IRP_MJ_DEVICE_CONTROL] == NULL )
  509. return( STATUS_INVALID_DEVICE_REQUEST );
  510. /*
  511. * Call the device control routine for this ICA object.
  512. */
  513. Status = (pIcaHeader->pDispatchTable[IRP_MJ_DEVICE_CONTROL])(
  514. pIcaHeader, Irp, IrpSp );
  515. return( Status );
  516. }
  517. NTSTATUS
  518. IcaCleanup (
  519. IN PIRP Irp,
  520. IN PIO_STACK_LOCATION IrpSp
  521. )
  522. /*++
  523. Routine Description:
  524. This is the routine that handles Cleanup IRPs in ICA.
  525. Arguments:
  526. Irp - Pointer to I/O request packet.
  527. IrpSp - pointer to the IO stack location to use for this request.
  528. Return Value:
  529. NTSTATUS --
  530. --*/
  531. {
  532. PICA_HEADER pIcaHeader;
  533. NTSTATUS Status;
  534. /*
  535. * Get pointer to ICA object header.
  536. * If a cleanup routine is not defined, return an error.
  537. */
  538. pIcaHeader = IrpSp->FileObject->FsContext;
  539. if ( pIcaHeader->pDispatchTable[IRP_MJ_CLEANUP] == NULL )
  540. return( STATUS_INVALID_DEVICE_REQUEST );
  541. Status = (pIcaHeader->pDispatchTable[IRP_MJ_CLEANUP])(
  542. pIcaHeader, Irp, IrpSp );
  543. return( Status );
  544. }
  545. NTSTATUS
  546. IcaClose (
  547. IN PIRP Irp,
  548. IN PIO_STACK_LOCATION IrpSp
  549. )
  550. /*++
  551. Routine Description:
  552. This is the routine that handles Close IRPs in ICA. It
  553. dereferences the endpoint specified in the IRP, which will result in
  554. the endpoint being freed when all other references go away.
  555. Arguments:
  556. Irp - Pointer to I/O request packet.
  557. IrpSp - pointer to the IO stack location to use for this request.
  558. Return Value:
  559. NTSTATUS -- Indicates whether the request was successfully queued.
  560. --*/
  561. {
  562. PICA_HEADER pIcaHeader;
  563. NTSTATUS Status;
  564. PAGED_CODE( );
  565. /*
  566. * Get pointer to ICA object header.
  567. * If a close routine is not defined, return an error.
  568. */
  569. pIcaHeader = IrpSp->FileObject->FsContext;
  570. if ( pIcaHeader->pDispatchTable[IRP_MJ_CLOSE] == NULL )
  571. return( STATUS_INVALID_DEVICE_REQUEST );
  572. Status = (pIcaHeader->pDispatchTable[IRP_MJ_CLOSE])(
  573. pIcaHeader, Irp, IrpSp );
  574. return( Status );
  575. }
  576. NTSTATUS
  577. CaptureUsermodeBuffer (
  578. IN PIRP Irp,
  579. IN PIO_STACK_LOCATION IrpSp,
  580. OUT PVOID *pInBuffer,
  581. IN ULONG InBufferSize,
  582. OUT PVOID *pOutBuffer,
  583. IN ULONG OutBufferSize,
  584. IN BOOLEAN MethodBuffered,
  585. OUT PVOID *pAllocatedTemporaryBuffer
  586. )
  587. {
  588. NTSTATUS Status = STATUS_SUCCESS;
  589. PVOID pBuffer = NULL;
  590. try {
  591. if (MethodBuffered) {
  592. if (pInBuffer != NULL) {
  593. *pInBuffer = Irp->AssociatedIrp.SystemBuffer;
  594. }
  595. if (pOutBuffer != NULL) {
  596. *pOutBuffer = Irp->AssociatedIrp.SystemBuffer;
  597. }
  598. if (pAllocatedTemporaryBuffer != NULL) {
  599. *pAllocatedTemporaryBuffer = NULL;
  600. }
  601. } else{
  602. ULONG AlignedInputSize = (InBufferSize + sizeof(BYTE*) - 1) & ~(sizeof(BYTE*) - 1);
  603. ULONG AllocationSize = AlignedInputSize +OutBufferSize;
  604. if (AllocationSize != 0 ) {
  605. if (gCapture && (Irp->RequestorMode == UserMode) ) {
  606. pBuffer = ExAllocatePoolWithTag(PagedPool, AllocationSize, ICA_POOL_TAG);
  607. if (pBuffer == NULL) {
  608. ExRaiseStatus(STATUS_NO_MEMORY);
  609. } else{
  610. if (pInBuffer != NULL) {
  611. *pInBuffer = pBuffer;
  612. }
  613. if (pOutBuffer != NULL) {
  614. *pOutBuffer = (PVOID)((BYTE*)pBuffer+AlignedInputSize);
  615. }
  616. if (pAllocatedTemporaryBuffer != NULL) {
  617. *pAllocatedTemporaryBuffer = pBuffer;
  618. }
  619. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != 0) {
  620. RtlCopyMemory( pBuffer,
  621. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  622. IrpSp->Parameters.DeviceIoControl.InputBufferLength);
  623. }
  624. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0 ) {
  625. RtlCopyMemory((PVOID) ((BYTE*)pBuffer+AlignedInputSize),
  626. Irp->UserBuffer,
  627. IrpSp->Parameters.DeviceIoControl.OutputBufferLength);
  628. }
  629. }
  630. } else{
  631. if (pInBuffer != NULL) {
  632. *pInBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  633. }
  634. if (pOutBuffer != NULL) {
  635. *pOutBuffer = Irp->UserBuffer;
  636. }
  637. if (pAllocatedTemporaryBuffer != NULL) {
  638. *pAllocatedTemporaryBuffer = NULL;
  639. }
  640. }
  641. }else {
  642. if (pInBuffer != NULL) {
  643. *pInBuffer = NULL;
  644. }
  645. if (pOutBuffer != NULL) {
  646. *pOutBuffer = NULL;
  647. }
  648. if (pAllocatedTemporaryBuffer != NULL) {
  649. *pAllocatedTemporaryBuffer = NULL;
  650. }
  651. }
  652. }
  653. } except(EXCEPTION_EXECUTE_HANDLER){
  654. if (pBuffer != NULL) {
  655. ExFreePool(pBuffer);
  656. }
  657. if (pAllocatedTemporaryBuffer != NULL) {
  658. *pAllocatedTemporaryBuffer = NULL;
  659. }
  660. Status = GetExceptionCode();
  661. }
  662. return Status;
  663. }