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.7 KiB
241 lines
6.7 KiB
/*++
|
|
|
|
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;
|
|
}
|