Howdy!
I have run into a problem when renaming a large number of files and
directories. It appears that the file renames go through fine. And for a
few directories, the rename works fine. But if I try to rename a large
number of files and directories I run into a problem where my rename IRP
calls down into NTFS land and doesn’t come back (looks like a deadlock).
Are there special ways to handle the renames of directories as opposed to
files? The following code is my rename code:
TIA! - jb
=======================================================
NTSTATUS FileMove(PDEVICE_OBJECT deviceObject, PFILE_OBJECT fileObject,
PWCHAR newName, ULONG newNameLen, BOOLEAN replaceIfExists)
{
PIRP irp;
PKEVENT event;
PIO_STACK_LOCATION ioStackLocation;
KIRQL oldIrql;
NTSTATUS ntStatus;
ULONG renameBufferSize;
PFILE_RENAME_INFORMATION renameInfo = NULL;
PFILE_OBJECT targetDirFileObject;
HANDLE targetDirHandle;
IO_STATUS_BLOCK ioStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING newNameUni;
// -----------------------------------------------------
// get target directory file handle
// -----------------------------------------------------
RtlZeroMemory( &ObjectAttributes, sizeof(OBJECT_ATTRIBUTES) );
RtlZeroMemory( &ioStatusBlock, sizeof(IO_STATUS_BLOCK) );
RtlInitUnicodeString(&newNameUni, newName);
InitializeObjectAttributes(&ObjectAttributes, &newNameUni,
OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = IoCreateFile( &targetDirHandle, // File handle
DELETE, // Desired access
&ObjectAttributes, // object attributes
&ioStatusBlock, // io status block
0, // allocation size (optional)
FILE_ATTRIBUTE_NORMAL, // file attributes
0, // exclusive access
FILE_OPEN_IF, // disposition
0, // Create Options
NULL, // ea buffer
0, // ea buffer length
CreateFileTypeNone, // create file type - must be CreateFileTypeNum
(0)
NULL, // extra create parameters - must be null
IO_NO_PARAMETER_CHECKING | // options
IO_OPEN_TARGET_DIRECTORY // options continued
);
if( !NT_SUCCESS(ntStatus) )
{
DbgPrint( (“ERROR in IoCreateFile: %08lx”, ntStatus) );
return( ntStatus );
}
// -----------------------------------------------------
// Get file object from handle to file…
// -----------------------------------------------------
ntStatus = ObReferenceObjectByHandle(targetDirHandle, 0, NULL, KernelMode,
&targetDirFileObject, NULL );
if( !NT_SUCCESS(ntStatus) )
{
DbgPrint( (“ERROR in ObReferenceObjectByHandle: %08lx”, ntStatus) );
ZwClose( targetDirHandle );
return( STATUS_INSUFFICIENT_RESOURCES );
}
ZwClose(targetDirHandle);
event = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT),
‘zzQP’);
if( event == NULL )
{
DbgPrint( (“ERROR allocating event”) );
ZwClose( targetDirHandle );
return( STATUS_INSUFFICIENT_RESOURCES );
}
KeInitializeEvent( event, SynchronizationEvent, FALSE );
// -----------------------------------------------------
// prep IRP for rename call
// -----------------------------------------------------
renameBufferSize = sizeof(FILE_RENAME_INFORMATION);
renameBufferSize += ( (newNameLen + 1) * sizeof(WCHAR) );
renameInfo = (PFILE_RENAME_INFORMATION)ExAllocatePoolWithTag(NonPagedPool,
renameBufferSize, ‘vmQP’);
if( renameInfo == NULL )
{
ZwClose(targetDirHandle);
ObDereferenceObject(&targetDirFileObject);
return(STATUS_INSUFFICIENT_RESOURCES);
}
// --------------------------------------------------
// Set the rename information
// --------------------------------------------------
renameInfo->ReplaceIfExists = replaceIfExists;
renameInfo->RootDirectory = NULL;
renameInfo->FileNameLength = newNameLen*sizeof(WCHAR); // length is size
in bytes not wide-characters
RtlCopyMemory(renameInfo->FileName, newName, renameInfo->FileNameLength);
renameInfo->FileName[newNameLen] = L’\0’;
// --------------------------------------------------
// Allocate an IRP for this event
// --------------------------------------------------
irp = IoAllocateIrp(deviceObject->StackSize, FALSE);
if( irp == NULL )
{
ExFreePool( renameInfo );
ExFreePool( event );
ObDereferenceObject(&targetDirFileObject);
return(STATUS_INSUFFICIENT_RESOURCES);
}
// --------------------------------------------------
// Build the irp
// --------------------------------------------------
ioStatusBlock.Status = 0;
ioStatusBlock.Information = 0;
irp->AssociatedIrp.SystemBuffer = renameInfo;
irp->UserEvent = event;
irp->UserIosb =
&ioStatusBlock;
irp->Tail.Overlay.Thread =
PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject = fileObject;
irp->RequestorMode = KernelMode;
irp->Flags = 0;
// --------------------------------------------------
// Build the io stack location
// --------------------------------------------------
ioStackLocation =
IoGetNextIrpStackLocation(irp);
ioStackLocation->MajorFunction =
IRP_MJ_SET_INFORMATION;
ioStackLocation->DeviceObject = deviceObject;
ioStackLocation->FileObject = fileObject;
ioStackLocation->Parameters.SetFile.Length = renameBufferSize;
ioStackLocation->Parameters.SetFile.FileInformationClass =
FileRenameInformation;
ioStackLocation->Parameters.SetFile.ReplaceIfExists =
renameInfo->ReplaceIfExists;
ioStackLocation->Parameters.SetFile.FileObject = targetDirFileObject;
// --------------------------------------------------
// Set the Completion Routine
// --------------------------------------------------
IoSetCompletionRoutine( irp, FileMoveComplete, NULL, TRUE, TRUE, TRUE );
// -----------------------------------------------------
// Execute rename call
// -----------------------------------------------------
irp->IoStatus.Status = 0;
ntStatus = IoCallDriver(deviceObject, irp);
if( ntStatus == STATUS_PENDING )
{
KeWaitForSingleObject(event, Suspended, KernelMode, FALSE, NULL);
}
// -----------------------------------------------------
// clean up things and return success value
// -----------------------------------------------------
IoFreeIrp( irp );
ExFreePool( renameInfo );
ExFreePool( event );
ObDereferenceObject(&targetDirFileObject);
return( ioStatusBlock.Status );
}
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com