STATUS_REPARSE and Delete File From explorer 's context menu

a file systems filter driver,in the IRP_MJ_CREATE routine£¬I modified

the FileObject->FileName with new file name then return

STATUS_REPARSE.

when open a file(and directory)or create a file(and directory),it

work well.such as open C:\My Document\XXXX\xxx.txt,it will redirect

the path to d:\My Document\yyyyy\xxx.txt.( C:\My Document\XXXX\ will

rediret to d:\My Document\yyyyy).and the content of the C:\My

Document\XXXX\ are the same of d:\My Document\yyyyy.

but when in C:\My Document\XXXX,i select a directory,right click it,

come out the context menu,select the “Delete”,come out a dialog to

confirm and click “OK”,come out a dialog say: the directory is used

by another…

it is the same to delete a file from context menu but can delete a

file with press the “Delete” key in keyboard and can not delete a

directory.

the follow is my code of IRP_MJ_CREATE:

TSTATUS PadLockFilterCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP

Irp )

{

NTSTATUS status;

#if WINVER >= 0x0501

KLOCK_QUEUE_HANDLE LockHandle;

#else

KIRQL oldIrql;

#endif

// KEVENT waitEvent;

PIO_STACK_LOCATION irpSp;

//////////////////////////////////////////////////////////////////////////

//Brilly added

PUNICODE_STRING FileName=NULL;

PVOID FileNameBuffer=NULL;

//UNICODE_STRING NewFileName;

GET_NAME_CONTROL nameControl;

PLIST_ENTRY pEntry,pHead;

PPADLOCKFILTER_MAP_INFO_LIST pdElement;

PWSTR FindPos=NULL;

BOOLEAN bRedirectFileOpen = FALSE;

ULONG ulOrignalFileLen=0;

ULONG ulNewFileLen=0;

//Added end

//////////////////////////////////////////////////////////////////////////

PAGED_CODE();

//////////////////////////////////////////////////////////////////////////

//

// Get current IRP stack

//

irpSp = IoGetCurrentIrpStackLocation( Irp );

//

// If this is for our control device object, don’t allow it to be

opened.

//

if ( IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ) && irpSp-

MajorFunction != IRP_MJ_QUERY_INFORMATION )

{

DBGS(“IRP_Create IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject )”);

// Ô­À´µÄ´úÂ룬²»´¦Àí

//Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

//Irp->IoStatus.Information = 0;

//IoCompleteRequest( Irp, IO_NO_INCREMENT );

//return STATUS_INVALID_DEVICE_REQUEST;

//End

//

// A CREATE request is being made on our gControlDeviceObject.

// See if someone else has it open. If so, disallow this open.

//

#if WINVER >= 0x0501

KeAcquireInStackQueuedSpinLock(

&gPadLockFilter_ControlDeviceStateLock,&LockHandle );

#else

KeAcquireSpinLock( &gPadLockFilter_ControlDeviceStateLock, &oldIrql

);

#endif

if (gPadLockFilter_ControlDeviceState != CLOSED)

{

Irp->IoStatus.Status = STATUS_DEVICE_ALREADY_ATTACHED;

Irp->IoStatus.Information = 0;

}

else

{

Irp->IoStatus.Status = STATUS_SUCCESS;

Irp->IoStatus.Information = FILE_OPENED;

gPadLockFilter_ControlDeviceState = OPENED;

}

#if WINVER >= 0x0501

KeReleaseInStackQueuedSpinLock( &LockHandle );

#else

KeReleaseSpinLock( &gPadLockFilter_ControlDeviceStateLock, oldIrql

);

#endif

//

// Since this is our gControlDeviceObject, we complete the

// irp here.

//

status = Irp->IoStatus.Status;

IoCompleteRequest( Irp, IO_NO_INCREMENT );

return status;

}

ASSERT( IS_MY_DEVICE_OBJECT( DeviceObject ) );

//

// Copy the stack and set our Completion routine

//

FileName = PadLockFilterGetFullPathName(irpSp->FileObject,

&nameControl);

#if WINVER >= 0x0501

KeAcquireInStackQueuedSpinLock( &gPadLockFilter_MapListAccessLock,

&LockHandle );

#else

KeAcquireSpinLock( &gPadLockFilter_MapListAccessLock,&oldIrql);

#endif

pEntry = pHead = & gPadLockFilter_FileMapHead;

if ( pEntry != NULL )

{

while ( pEntry->Flink != pHead ) //look up the list to find that

is filename will modify.

{

ASSERT( pEntry->Flink != NULL );

pdElement = CONTAINING_RECORD( pEntry->Flink ,

PADLOCKFILTER_MAP_INFO_LIST ,linkfield);

ASSERT (pdElement != NULL );

ASSERT ( pdElement->pwstrRealFilePath != NULL );

ASSERT ( pdElement->pwstrMapFilePath != NULL );

ASSERT ( FileName != NULL );

ASSERT ( FileName->Buffer != NULL );

FindPos = wcsstr( FileName->Buffer,pdElement->pwstrRealFilePath);

if ( FindPos != NULL ) //ÔÚFileNameÖÐÕÒµ½Á˶ÔÓ¦µÄÓ³Éä·¾¶,µ«²»Ò»¶¨ÍêÈ«ÎǺÏ

{

BOOLEAN bDoRemap=FALSE;

size_t l;

size_t BufferMustLength=0;

size_t MaxBufferSize=0;

size_t lFileName=0;

RtlStringCchLengthW( FileName->Buffer, MAXPATHLEN, &lFileName);

DBGPUS(FileName);

RtlStringCchLengthW( pdElement->pwstrRealFilePath, MAXPATHLEN, &l

);

DBGX(“the realfilepath=%S”,pdElement->pwstrRealFilePath);

if ( wcscmp( FileName->Buffer,pdElement->pwstrRealFilePath) == 0

) //ÍêÈ«ÎǺÏ

{

DBGS(“the same!”);

bDoRemap = TRUE;

}

else if ( ( FindPos + l ) <= (FileName->Buffer + lFileName ) )

{

//DBGX(" the FindPos + l = %C", ( *(FindPos + l ) ) );

if ( *(FindPos + l ) == L’\’ ) //ÊǸÃÎļþ¼ÐϵÄÎļþ»òÎļþ¼Ð

{

DBGL;

bDoRemap = TRUE;

}

}

//bDoRemap = TRUE;

DBGD1( " bDoRemap " ,bDoRemap );

if ( TRUE == bDoRemap )

{

// \Device\Harddisk3\XXXX\yyyy\aaa.txt ===>ÕæÊµÂ·¾¶

// ------> \Device\Harddisk4\XXXX ===>Ó°Éä·¾¶

RtlStringCchLengthW( pdElement->pwstrMapFilePath , MAXPATHLEN,

&l);

BufferMustLength += l;

RtlStringCchLengthW( FindPos , MAXPATHLEN, &l);

BufferMustLength += l;

MaxBufferSize = MAXPATHLEN > BufferMustLength ? MAXPATHLEN :

BufferMustLength;

FileNameBuffer = ExAllocatePoolWithTag( NonPagedPool,

MaxBufferSize , PKFL_POOL_TAG );

if ( FileNameBuffer == NULL )

{

DBGBP;

goto FLAG_DONONE;

}

RtlZeroMemory( FileNameBuffer,MaxBufferSize);

RtlStringCchCatW( FileNameBuffer, MaxBufferSize ,pdElement-

pwstrMapFilePath );

RtlStringCchLengthW( pdElement->pwstrRealFilePath ,MAXPATHLEN,

&l);

if ( RtlStringCchCatW( FileNameBuffer,MaxBufferSize,FindPos + l

) == STATUS_BUFFER_OVERFLOW )

{

ExFreePool( FileNameBuffer );

DBGBP;

goto FLAG_DONONE;

}

//RtlAppendUnicodeToString( &NewFileName,FindPos+wcslen(

pdElement->pwstrRealFilePath ) );

DBGX(“the new file name=%S”,FileNameBuffer);

//ExFreePool( irpSp->FileObject->FileName.Buffer );

RtlFreeUnicodeString( &irpSp->FileObject->FileName);

RtlInitUnicodeString( &irpSp->FileObject->FileName,

FileNameBuffer);

#if WINVER >= 0x0501

KeReleaseInStackQueuedSpinLock( &LockHandle );

#else

KeReleaseSpinLock( &gPadLockFilter_MapListAccessLock, oldIrql );

#endif

PadLockFilterGetFileNameCleanup( &nameControl );

//RtlInitEmptyUnicodeString( &irpSp->FileObject->FileName ,

FileNameBuffer, MAXPATHLEN );

//RtlCopyUnicodeString( &irpSp->FileObject->FileName,

&NewFileName );

Irp->IoStatus.Information = IO_REPARSE;

//ExFreePool( FileNameBuffer);

Irp->IoStatus.Status = STATUS_REPARSE;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return STATUS_REPARSE;

}

}

pEntry = pEntry->Flink ;

}

}

FLAG_DONONE:

#if WINVER >= 0x0501

KeReleaseInStackQueuedSpinLock( &LockHandle );

#else

KeReleaseSpinLock( &gPadLockFilter_MapListAccessLock, oldIrql );

#endif

PadLockFilterGetFileNameCleanup( &nameControl );

//

// Don’t put us on the stack then call the next driver

//

IoSkipCurrentIrpStackLocation( Irp );

return IoCallDriver( ( ( PPADLOCKFILTER_DEVICE_EXTENSION

)DeviceObject->DeviceExtension )->AttachedToDeviceObject, Irp );

I found that when redirect the path C:\aaa to c:\bbb,the problem does
not appear.