- Zero out the OPEN_PACKET and only set non-zero members in functions that use it.

- NtCancelIoFile:
  - Don't use macro-based list looping.
  - Update operation counts.
  - Wait 10ms instead of 100ms.

svn path=/trunk/; revision=22941
This commit is contained in:
Alex Ionescu 2006-07-08 19:28:08 +00:00
parent 0535c5d920
commit 8395aae6a0

View file

@ -1099,33 +1099,19 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION)); IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION));
/* Setup the Open Packet */ /* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET; OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET); OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.FileObject = NULL;
OpenPacket.FinalStatus = STATUS_SUCCESS;
OpenPacket.Information = 0;
OpenPacket.ParseCheck = 0;
OpenPacket.RelatedFileObject = NULL;
OpenPacket.AllocationSize.QuadPart = 0;
OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT;
OpenPacket.FileAttributes = 0;
OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
OpenPacket.EaBuffer = NULL;
OpenPacket.EaLength = 0;
OpenPacket.Options = 0;
OpenPacket.Disposition = FILE_OPEN; OpenPacket.Disposition = FILE_OPEN;
OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL; OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL;
OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo : OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo :
(AccessMode != KernelMode) ? (AccessMode != KernelMode) ?
&NetworkOpenInfo : FileInformation; &NetworkOpenInfo : FileInformation;
OpenPacket.CreateFileType = 0;
OpenPacket.MailslotOrPipeParameters = NULL;
OpenPacket.Override = FALSE;
OpenPacket.QueryOnly = TRUE; OpenPacket.QueryOnly = TRUE;
OpenPacket.DeleteOnly = FALSE;
OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE; OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE;
OpenPacket.DummyFileObject = &DummyFileObject; OpenPacket.DummyFileObject = &DummyFileObject;
OpenPacket.InternalFlags = 0;
/* Update the operation count */ /* Update the operation count */
IopUpdateOperationCount(IopOtherTransfer); IopUpdateOperationCount(IopOtherTransfer);
@ -1314,13 +1300,9 @@ IoCreateFile(OUT PHANDLE FileHandle,
} }
/* Setup the Open Packet */ /* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET; OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET); OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.FileObject = NULL;
OpenPacket.FinalStatus = STATUS_SUCCESS;
OpenPacket.Information = 0;
OpenPacket.ParseCheck = 0;
OpenPacket.RelatedFileObject = NULL;
OpenPacket.OriginalAttributes = *ObjectAttributes; OpenPacket.OriginalAttributes = *ObjectAttributes;
OpenPacket.AllocationSize = SafeAllocationSize; OpenPacket.AllocationSize = SafeAllocationSize;
OpenPacket.CreateOptions = CreateOptions; OpenPacket.CreateOptions = CreateOptions;
@ -1330,16 +1312,8 @@ IoCreateFile(OUT PHANDLE FileHandle,
OpenPacket.EaLength = EaLength; OpenPacket.EaLength = EaLength;
OpenPacket.Options = Options; OpenPacket.Options = Options;
OpenPacket.Disposition = CreateDisposition; OpenPacket.Disposition = CreateDisposition;
OpenPacket.BasicInformation = NULL;
OpenPacket.NetworkInformation = NULL;
OpenPacket.CreateFileType = CreateFileType; OpenPacket.CreateFileType = CreateFileType;
OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters; OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters;
OpenPacket.Override = FALSE;
OpenPacket.QueryOnly = FALSE;
OpenPacket.DeleteOnly = FALSE;
OpenPacket.FullAttributes = FALSE;
OpenPacket.DummyFileObject = NULL;
OpenPacket.InternalFlags = 0;
/* Update the operation count */ /* Update the operation count */
IopUpdateOperationCount(IopOtherTransfer); IopUpdateOperationCount(IopOtherTransfer);
@ -1596,31 +1570,17 @@ IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
PAGED_CODE(); PAGED_CODE();
/* Setup the Open Packet */ /* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET; OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET); OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.FileObject = NULL;
OpenPacket.FinalStatus = STATUS_SUCCESS;
OpenPacket.Information = 0;
OpenPacket.ParseCheck = 0;
OpenPacket.RelatedFileObject = NULL;
OpenPacket.AllocationSize.QuadPart = 0;
OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT; OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT;
OpenPacket.FileAttributes = 0;
OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
OpenPacket.EaBuffer = NULL;
OpenPacket.EaLength = 0;
OpenPacket.Options = IO_FORCE_ACCESS_CHECK; OpenPacket.Options = IO_FORCE_ACCESS_CHECK;
OpenPacket.Disposition = FILE_OPEN; OpenPacket.Disposition = FILE_OPEN;
OpenPacket.BasicInformation = NULL;
OpenPacket.NetworkInformation = Buffer; OpenPacket.NetworkInformation = Buffer;
OpenPacket.CreateFileType = 0;
OpenPacket.MailslotOrPipeParameters = NULL;
OpenPacket.Override = FALSE;
OpenPacket.QueryOnly = TRUE; OpenPacket.QueryOnly = TRUE;
OpenPacket.DeleteOnly = FALSE;
OpenPacket.FullAttributes = TRUE; OpenPacket.FullAttributes = TRUE;
OpenPacket.DummyFileObject = &DummyFileObject; OpenPacket.DummyFileObject = &DummyFileObject;
OpenPacket.InternalFlags = 0;
/* /*
* Attempt opening the file. This will call the I/O Parse Routine for * Attempt opening the file. This will call the I/O Parse Routine for
@ -2146,25 +2106,32 @@ NtCancelIoFile(IN HANDLE FileHandle,
LARGE_INTEGER Interval; LARGE_INTEGER Interval;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PLIST_ENTRY ListHead, NextEntry;
PAGED_CODE(); PAGED_CODE();
/* Check the previous mode */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
/* Enter SEH for probing */
_SEH_TRY _SEH_TRY
{ {
/* Probe the I/O Status Block */
ProbeForWrite(IoStatusBlock, ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK), sizeof(IO_STATUS_BLOCK),
sizeof(ULONG)); sizeof(ULONG));
} }
_SEH_HANDLE _SEH_HANDLE
{ {
/* Get the exception code */
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
/* Return exception code on failure */
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
} }
/* Reference the file object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
0, 0,
IoFileObjectType, IoFileObjectType,
@ -2176,59 +2143,77 @@ NtCancelIoFile(IN HANDLE FileHandle,
/* IRP cancellations are synchronized at APC_LEVEL. */ /* IRP cancellations are synchronized at APC_LEVEL. */
OldIrql = KfRaiseIrql(APC_LEVEL); OldIrql = KfRaiseIrql(APC_LEVEL);
/* /* Get the current thread */
* Walk the list of active IRPs and cancel the ones that belong to
* our file object.
*/
Thread = PsGetCurrentThread(); Thread = PsGetCurrentThread();
LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry) /* Update the operation counts */
IopUpdateOperationCount(IopOtherTransfer);
/* Loop the list */
ListHead = &Thread->IrpList;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{ {
/* Get the IRP and check if the File Object matches */
Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
if (Irp->Tail.Overlay.OriginalFileObject == FileObject) if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
{ {
/* Cancel this IRP and keep looping */
IoCancelIrp(Irp); IoCancelIrp(Irp);
/* Don't break here, we want to cancel all IRPs for the file object. */
OurIrpsInList = TRUE; OurIrpsInList = TRUE;
} }
/* Go to the next entry */
NextEntry = NextEntry->Flink;
} }
/* Lower the IRQL */
KfLowerIrql(OldIrql); KfLowerIrql(OldIrql);
while (OurIrpsInList) /* Check if we had found an IRP */
if (OurIrpsInList)
{ {
OurIrpsInList = FALSE; /* Setup a 10ms wait */
Interval.QuadPart = -100000;
/* Wait a short while and then look if all our IRPs were completed. */ /* Start looping */
Interval.QuadPart = -1000000; /* 100 milliseconds */ while (OurIrpsInList)
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
OldIrql = KfRaiseIrql(APC_LEVEL);
/*
* Look in the list if all IRPs for the specified file object
* are completed (or cancelled). If someone sends a new IRP
* for our file object while we're here we can happily loop
* forever.
*/
LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
{ {
if (Irp->Tail.Overlay.OriginalFileObject == FileObject) /* Do the wait */
{ KeDelayExecutionThread(KernelMode, FALSE, &Interval);
OurIrpsInList = TRUE; OurIrpsInList = FALSE;
break;
}
}
KfLowerIrql(OldIrql); /* Raise IRQL */
OldIrql = KfRaiseIrql(APC_LEVEL);
/* Now loop the list again */
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the IRP and check if the File Object matches */
Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
{
/* Keep looping */
OurIrpsInList = TRUE;
break;
}
/* Go to the next entry */
NextEntry = NextEntry->Flink;
}
/* Lower the IRQL */
KeLowerIrql(OldIrql);
}
} }
/* Enter SEH for writing back the I/O Status */
_SEH_TRY _SEH_TRY
{ {
/* Write success */
IoStatusBlock->Status = STATUS_SUCCESS; IoStatusBlock->Status = STATUS_SUCCESS;
IoStatusBlock->Information = 0; IoStatusBlock->Information = 0;
Status = STATUS_SUCCESS;
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -2236,8 +2221,9 @@ NtCancelIoFile(IN HANDLE FileHandle,
} }
_SEH_END; _SEH_END;
/* Dereference the file object and return success */
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return Status; return STATUS_SUCCESS;
} }
/* /*
@ -2255,33 +2241,16 @@ NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
PAGED_CODE(); PAGED_CODE();
/* Setup the Open Packet */ /* Setup the Open Packet */
RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
OpenPacket.Type = IO_TYPE_OPEN_PACKET; OpenPacket.Type = IO_TYPE_OPEN_PACKET;
OpenPacket.Size = sizeof(OPEN_PACKET); OpenPacket.Size = sizeof(OPEN_PACKET);
OpenPacket.FileObject = NULL;
OpenPacket.FinalStatus = STATUS_SUCCESS;
OpenPacket.Information = 0;
OpenPacket.ParseCheck = 0;
OpenPacket.RelatedFileObject = NULL;
OpenPacket.AllocationSize.QuadPart = 0;
OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE; OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE;
OpenPacket.FileAttributes = 0;
OpenPacket.ShareAccess = FILE_SHARE_READ | OpenPacket.ShareAccess = FILE_SHARE_READ |
FILE_SHARE_WRITE | FILE_SHARE_WRITE |
FILE_SHARE_DELETE; FILE_SHARE_DELETE;
OpenPacket.EaBuffer = NULL;
OpenPacket.EaLength = 0;
OpenPacket.Options = 0;
OpenPacket.Disposition = FILE_OPEN; OpenPacket.Disposition = FILE_OPEN;
OpenPacket.BasicInformation = NULL;
OpenPacket.NetworkInformation = NULL;
OpenPacket.CreateFileType = 0;
OpenPacket.MailslotOrPipeParameters = NULL;
OpenPacket.Override = FALSE;
OpenPacket.QueryOnly = FALSE;
OpenPacket.DeleteOnly = TRUE; OpenPacket.DeleteOnly = TRUE;
OpenPacket.FullAttributes = FALSE;
OpenPacket.DummyFileObject = &DummyFileObject; OpenPacket.DummyFileObject = &DummyFileObject;
OpenPacket.InternalFlags = 0;
/* Update the operation counts */ /* Update the operation counts */
IopUpdateOperationCount(IopOtherTransfer); IopUpdateOperationCount(IopOtherTransfer);