Are there special issues regarding renaming directories?

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