windows-nt/Source/XPSP1/NT/base/fs/efs/control.c

242 lines
6.4 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
control.c
Abstract:
This module contains the code to handle the IRP MajorFunctions of
IRP_MJ_DEVICE_CONTROL and IRP_MJ_FILE_SYSTEM_CONTROL. The code will
be responsible for correctly setting these IRP's with any necessary
information and passing them along. Any other support routine which are
directly releated (such as completion routines) to these operations can
be found in this module.
Author:
Robert Gu (robertg) 29-Oct-1996
Environment:
Kernel mode
Revision History:
--*/
#include "efs.h"
#include "efsrtl.h"
#include "efsext.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, EFSFsControl)
#endif
NTSTATUS
EFSFsControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PFILE_OBJECT FileObject
)
/*++
Routine Description:
This routine is invoked whenever an I/O Request Packet (IRP) w/a major
function code of IRP_MJ_FILE_SYSTEM_CONTROL is encountered. For most
IRPs of this type, the packet is simply passed through. However, for
some requests, special processing is required.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
--*/
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
PIO_STACK_LOCATION nextIrpSp;
PDEVICE_OBJECT deviceObject;
PKEVENT finishEvent;
PAGED_CODE();
if ( (irpSp->MinorFunction == IRP_MN_USER_FS_REQUEST) &&
(irpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_SET_COMPRESSION) &&
( (irpSp->Parameters.FileSystemControl.InputBufferLength >= sizeof (USHORT)) &&
(*(PUSHORT)(Irp->AssociatedIrp.SystemBuffer) != 0 /*COMPRESSION_FORMAT_NONE*/)
)
){
//
// Compression on encrypted file is not allowed.
// Check if the file is encrypted or not
//
ULONG inputDataLength;
UCHAR *inputDataBuffer, *outputDataBuffer;
ULONG outputDataLength;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP fsCtlIrp;
PIO_STACK_LOCATION fsCtlIrpSp;
inputDataLength = FIELD_OFFSET(FSCTL_INPUT, EfsFsData[0]) +
FIELD_OFFSET(GENERAL_FS_DATA, EfsData[0]);
inputDataBuffer = ExAllocatePoolWithTag(
PagedPool,
inputDataLength,
'msfE'
);
//
// The size of output data buffer is not important. We don't
// care the content. We just need to know the $EFS exists.
//
outputDataLength = 1024;
outputDataBuffer = ExAllocatePoolWithTag(
PagedPool,
outputDataLength,
'msfE'
);
if ( ( NULL == inputDataBuffer ) || ( NULL == outputDataBuffer ) ){
//
// Out of memory
//
if ( inputDataBuffer ){
ExFreePool( inputDataBuffer );
}
if ( outputDataBuffer ){
ExFreePool( outputDataBuffer );
}
return STATUS_INSUFFICIENT_RESOURCES;
}
((PFSCTL_INPUT)inputDataBuffer)->EfsFsCode = EFS_GET_ATTRIBUTE;
RtlCopyMemory(
&(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]),
&(EfsData.SessionKey),
DES_KEYSIZE
);
RtlCopyMemory(
&(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]) + DES_KEYSIZE + 2 * sizeof( ULONG ),
&(((PFSCTL_INPUT)inputDataBuffer)->EfsFsData[0]),
DES_KEYSIZE + 2 * sizeof( ULONG )
);
//
// Encrypt our Input data
//
EfsEncryptKeyFsData(
inputDataBuffer,
inputDataLength,
sizeof(ULONG),
EFS_FSCTL_HEADER_LENGTH + DES_KEYSIZE + 2 * sizeof( ULONG ),
DES_KEYSIZE + 2 * sizeof( ULONG )
);
//
// Prepare a FSCTL IRP
//
KeInitializeEvent( &event, SynchronizationEvent, FALSE);
fsCtlIrp = IoBuildDeviceIoControlRequest( FSCTL_ENCRYPTION_FSCTL_IO,
DeviceObject,
inputDataBuffer,
inputDataLength,
outputDataBuffer,
outputDataLength,
FALSE,
&event,
&ioStatus
);
if ( fsCtlIrp ) {
fsCtlIrpSp = IoGetNextIrpStackLocation( fsCtlIrp );
fsCtlIrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
fsCtlIrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST;
fsCtlIrpSp->FileObject = irpSp->FileObject;
status = IoCallDriver( DeviceObject, fsCtlIrp);
if (status == STATUS_PENDING) {
status = KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER) NULL );
status = ioStatus.Status;
}
ExFreePool( inputDataBuffer );
ExFreePool( outputDataBuffer );
if ( NT_SUCCESS(status) || ( STATUS_BUFFER_TOO_SMALL == status) ){
//
// $EFS exist, encrypted file. Deny compression
//
return STATUS_INVALID_DEVICE_REQUEST;
}
} else {
//
// Failed allocate IRP
//
ExFreePool( inputDataBuffer );
ExFreePool( outputDataBuffer );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Compression allowed. Simply pass this file system control request through.
//
status = STATUS_SUCCESS;
} else {
//
// Simply pass this file system control request through.
//
status = STATUS_SUCCESS;
}
//
// Any special processing has been completed, so simply pass the request
// along to the next driver.
//
return status;
}