242 lines
6.4 KiB
C
242 lines
6.4 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|