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.

241 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. control.c
  5. Abstract:
  6. This module contains the code to handle the IRP MajorFunctions of
  7. IRP_MJ_DEVICE_CONTROL and IRP_MJ_FILE_SYSTEM_CONTROL. The code will
  8. be responsible for correctly setting these IRP's with any necessary
  9. information and passing them along. Any other support routine which are
  10. directly releated (such as completion routines) to these operations can
  11. be found in this module.
  12. Author:
  13. Robert Gu (robertg) 29-Oct-1996
  14. Environment:
  15. Kernel mode
  16. Revision History:
  17. --*/
  18. #include "efs.h"
  19. #include "efsrtl.h"
  20. #include "efsext.h"
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, EFSFsControl)
  23. #endif
  24. NTSTATUS
  25. EFSFsControl(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp,
  28. IN PFILE_OBJECT FileObject
  29. )
  30. /*++
  31. Routine Description:
  32. This routine is invoked whenever an I/O Request Packet (IRP) w/a major
  33. function code of IRP_MJ_FILE_SYSTEM_CONTROL is encountered. For most
  34. IRPs of this type, the packet is simply passed through. However, for
  35. some requests, special processing is required.
  36. Arguments:
  37. DeviceObject - Pointer to the device object for this driver.
  38. Irp - Pointer to the request packet representing the I/O request.
  39. Return Value:
  40. The function value is the status of the operation.
  41. --*/
  42. {
  43. NTSTATUS status;
  44. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  45. PIO_STACK_LOCATION nextIrpSp;
  46. PDEVICE_OBJECT deviceObject;
  47. PKEVENT finishEvent;
  48. PAGED_CODE();
  49. if ( (irpSp->MinorFunction == IRP_MN_USER_FS_REQUEST) &&
  50. (irpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_SET_COMPRESSION) &&
  51. ( (irpSp->Parameters.FileSystemControl.InputBufferLength >= sizeof (USHORT)) &&
  52. (*(PUSHORT)(Irp->AssociatedIrp.SystemBuffer) != 0 /*COMPRESSION_FORMAT_NONE*/)
  53. )
  54. ){
  55. //
  56. // Compression on encrypted file is not allowed.
  57. // Check if the file is encrypted or not
  58. //
  59. ULONG inputDataLength;
  60. UCHAR *inputDataBuffer, *outputDataBuffer;
  61. ULONG outputDataLength;
  62. KEVENT event;
  63. IO_STATUS_BLOCK ioStatus;
  64. PIRP fsCtlIrp;
  65. PIO_STACK_LOCATION fsCtlIrpSp;
  66. inputDataLength = FIELD_OFFSET(FSCTL_INPUT, EfsFsData[0]) +
  67. FIELD_OFFSET(GENERAL_FS_DATA, EfsData[0]);
  68. inputDataBuffer = ExAllocatePoolWithTag(
  69. PagedPool,
  70. inputDataLength,
  71. 'msfE'
  72. );
  73. //
  74. // The size of output data buffer is not important. We don't
  75. // care the content. We just need to know the $EFS exists.
  76. //
  77. outputDataLength = 1024;
  78. outputDataBuffer = ExAllocatePoolWithTag(
  79. PagedPool,
  80. outputDataLength,
  81. 'msfE'
  82. );
  83. if ( ( NULL == inputDataBuffer ) || ( NULL == outputDataBuffer ) ){
  84. //
  85. // Out of memory
  86. //
  87. if ( inputDataBuffer ){
  88. ExFreePool( inputDataBuffer );
  89. }
  90. if ( outputDataBuffer ){
  91. ExFreePool( outputDataBuffer );
  92. }
  93. return STATUS_INSUFFICIENT_RESOURCES;
  94. }
  95. ((PFSCTL_INPUT)inputDataBuffer)->EfsFsCode = EFS_GET_ATTRIBUTE;
  96. RtlCopyMemory(
  97. &(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]),
  98. &(EfsData.SessionKey),
  99. DES_KEYSIZE
  100. );
  101. RtlCopyMemory(
  102. &(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]) + DES_KEYSIZE + 2 * sizeof( ULONG ),
  103. &(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]),
  104. DES_KEYSIZE + 2 * sizeof( ULONG )
  105. );
  106. //
  107. // Encrypt our Input data
  108. //
  109. EfsEncryptKeyFsData(
  110. inputDataBuffer,
  111. inputDataLength,
  112. sizeof(ULONG),
  113. EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + 2 * sizeof( ULONG ),
  114. DES_KEYSIZE + 2 * sizeof( ULONG )
  115. );
  116. //
  117. // Prepare a FSCTL IRP
  118. //
  119. KeInitializeEvent( &event, SynchronizationEvent, FALSE);
  120. fsCtlIrp = IoBuildDeviceIoControlRequest( FSCTL_ENCRYPTION_FSCTL_IO,
  121. DeviceObject,
  122. inputDataBuffer,
  123. inputDataLength,
  124. outputDataBuffer,
  125. outputDataLength,
  126. FALSE,
  127. &event,
  128. &ioStatus
  129. );
  130. if ( fsCtlIrp ) {
  131. fsCtlIrpSp = IoGetNextIrpStackLocation( fsCtlIrp );
  132. fsCtlIrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  133. fsCtlIrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST;
  134. fsCtlIrpSp->FileObject = irpSp->FileObject;
  135. status = IoCallDriver( DeviceObject, fsCtlIrp);
  136. if (status == STATUS_PENDING) {
  137. status = KeWaitForSingleObject( &event,
  138. Executive,
  139. KernelMode,
  140. FALSE,
  141. (PLARGE_INTEGER) NULL );
  142. status = ioStatus.Status;
  143. }
  144. ExFreePool( inputDataBuffer );
  145. ExFreePool( outputDataBuffer );
  146. if ( NT_SUCCESS(status) || ( STATUS_BUFFER_TOO_SMALL == status) ){
  147. //
  148. // $EFS exist, encrypted file. Deny compression
  149. //
  150. return STATUS_INVALID_DEVICE_REQUEST;
  151. }
  152. } else {
  153. //
  154. // Failed allocate IRP
  155. //
  156. ExFreePool( inputDataBuffer );
  157. ExFreePool( outputDataBuffer );
  158. return STATUS_INSUFFICIENT_RESOURCES;
  159. }
  160. //
  161. // Compression allowed. Simply pass this file system control request through.
  162. //
  163. status = STATUS_SUCCESS;
  164. } else {
  165. //
  166. // Simply pass this file system control request through.
  167. //
  168. status = STATUS_SUCCESS;
  169. }
  170. //
  171. // Any special processing has been completed, so simply pass the request
  172. // along to the next driver.
  173. //
  174. return status;
  175. }