mirror of
https://github.com/reactos/reactos.git
synced 2025-06-18 20:25:21 +00:00
[NPFS-NEW]: Fix pool corruption and crashing bugs in NpPeek, which was using sizeof instead of FIELD_OFFSET.
[NPFS-NEW]: Actually implement NpCancelWaiter instead of making it ASSERT. [NPFS-NEW]: Critical fixes to NpAddWaiter and NpWaitForNamedPipe to fix logic flaws. NPFS-NEW now behaves without any visible regressions, and exhibits only 2 failures in the kernel32 pipe winetest -- vs 120+ failures with the current NPFS driver. It has 0 ntdll pipe failures, and 0 kmtest pipe failures. svn path=/trunk/; revision=60070
This commit is contained in:
parent
f9cb414f74
commit
f2ca6ff5d0
6 changed files with 179 additions and 84 deletions
|
@ -551,7 +551,7 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
|
||||||
Parameters->NamedPipeType & 0xFFFF,
|
Parameters->NamedPipeType & 0xFFFF,
|
||||||
&Fcb);
|
&Fcb);
|
||||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
Status = NpCreateCcb(Fcb,
|
Status = NpCreateCcb(Fcb,
|
||||||
FileObject,
|
FileObject,
|
||||||
FILE_PIPE_LISTENING_STATE,
|
FILE_PIPE_LISTENING_STATE,
|
||||||
|
|
|
@ -206,7 +206,7 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
NODE_TYPE_CODE Type;
|
NODE_TYPE_CODE Type;
|
||||||
ULONG InputLength;
|
ULONG OutputLength;
|
||||||
ULONG NamedPipeEnd;
|
ULONG NamedPipeEnd;
|
||||||
PNP_CCB Ccb;
|
PNP_CCB Ccb;
|
||||||
PFILE_PIPE_PEEK_BUFFER PeekBuffer;
|
PFILE_PIPE_PEEK_BUFFER PeekBuffer;
|
||||||
|
@ -218,7 +218,7 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
InputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
|
OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
|
||||||
Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
|
Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
|
||||||
|
|
||||||
if (!Type)
|
if (!Type)
|
||||||
|
@ -226,7 +226,8 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
return STATUS_PIPE_DISCONNECTED;
|
return STATUS_PIPE_DISCONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Type != NPFS_NTC_CCB) && (InputLength < sizeof(*PeekBuffer)))
|
if ((Type != NPFS_NTC_CCB) &&
|
||||||
|
(OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +265,7 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PeekBuffer->NumberOfMessages = 0;
|
PeekBuffer->NumberOfMessages = 0;
|
||||||
PeekBuffer->MessageLength = 0;
|
PeekBuffer->MessageLength = 0;
|
||||||
PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
|
PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
|
||||||
BytesPeeked = sizeof(*PeekBuffer);
|
BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data);
|
||||||
|
|
||||||
if (DataQueue->QueueState == WriteEntries)
|
if (DataQueue->QueueState == WriteEntries)
|
||||||
{
|
{
|
||||||
|
@ -279,7 +280,8 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
|
PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
|
||||||
PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
|
PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
|
||||||
}
|
}
|
||||||
if (InputLength == sizeof(*PeekBuffer))
|
|
||||||
|
if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))
|
||||||
{
|
{
|
||||||
Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
|
Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -289,12 +291,12 @@ NpPeek(IN PDEVICE_OBJECT DeviceObject,
|
||||||
TRUE,
|
TRUE,
|
||||||
FALSE,
|
FALSE,
|
||||||
PeekBuffer->Data,
|
PeekBuffer->Data,
|
||||||
InputLength - sizeof(*PeekBuffer),
|
OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data),
|
||||||
Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
|
Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
|
||||||
Ccb,
|
Ccb,
|
||||||
List);
|
List);
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
BytesPeeked = IoStatus.Information + sizeof(*PeekBuffer);
|
BytesPeeked += IoStatus.Information;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -523,14 +525,18 @@ NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
||||||
NODE_TYPE_CODE NodeTypeCode;
|
NODE_TYPE_CODE NodeTypeCode;
|
||||||
PLIST_ENTRY NextEntry;
|
PLIST_ENTRY NextEntry;
|
||||||
PNP_FCB Fcb;
|
PNP_FCB Fcb;
|
||||||
|
PWCHAR OriginalBuffer;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
InLength = IoStack->Parameters.DeviceIoControl.InputBufferLength;
|
InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
|
||||||
|
|
||||||
SourceString.Buffer = NULL;
|
SourceString.Buffer = NULL;
|
||||||
|
|
||||||
if (NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd) != NPFS_NTC_ROOT_DCB)
|
if (NpDecodeFileObject(IoStack->FileObject,
|
||||||
|
NULL,
|
||||||
|
&Ccb,
|
||||||
|
&NamedPipeEnd) != NPFS_NTC_ROOT_DCB)
|
||||||
{
|
{
|
||||||
Status = STATUS_ILLEGAL_FUNCTION;
|
Status = STATUS_ILLEGAL_FUNCTION;
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
|
@ -544,14 +550,17 @@ NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
NameLength = Buffer->NameLength;
|
NameLength = Buffer->NameLength;
|
||||||
if ((NameLength > 0xFFFD) || ((NameLength + sizeof(*Buffer)) > InLength))
|
if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) ||
|
||||||
|
((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength))
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
goto Quickie;
|
goto Quickie;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
|
SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||||
SourceString.Buffer = ExAllocatePoolWithTag(PagedPool, SourceString.Length, NPFS_WRITE_BLOCK_TAG);
|
SourceString.Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
|
SourceString.Length,
|
||||||
|
NPFS_WRITE_BLOCK_TAG);
|
||||||
if (!SourceString.Buffer)
|
if (!SourceString.Buffer)
|
||||||
{
|
{
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -562,6 +571,7 @@ NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
||||||
RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
|
RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
OriginalBuffer = SourceString.Buffer;
|
||||||
//Status = NpTranslateAlias(&SourceString);
|
//Status = NpTranslateAlias(&SourceString);
|
||||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
|
@ -583,7 +593,7 @@ NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
||||||
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
|
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NextEntry == &Fcb->CcbList)
|
if (NextEntry != &Fcb->CcbList)
|
||||||
{
|
{
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -592,7 +602,8 @@ NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
||||||
Status = NpAddWaiter(&NpVcb->WaitQueue,
|
Status = NpAddWaiter(&NpVcb->WaitQueue,
|
||||||
Fcb->Timeout,
|
Fcb->Timeout,
|
||||||
Irp,
|
Irp,
|
||||||
&SourceString);
|
OriginalBuffer == SourceString.Buffer ?
|
||||||
|
NULL : &SourceString);
|
||||||
}
|
}
|
||||||
|
|
||||||
Quickie:
|
Quickie:
|
||||||
|
|
|
@ -62,7 +62,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||||
|
|
||||||
DriverObject->DriverUnload = NULL;
|
DriverObject->DriverUnload = NULL;
|
||||||
|
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe2");
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
|
||||||
Status = IoCreateDevice(DriverObject,
|
Status = IoCreateDevice(DriverObject,
|
||||||
sizeof(NP_VCB),
|
sizeof(NP_VCB),
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
|
|
|
@ -178,7 +178,7 @@ typedef struct _NP_WAIT_QUEUE_ENTRY
|
||||||
KDPC Dpc;
|
KDPC Dpc;
|
||||||
KTIMER Timer;
|
KTIMER Timer;
|
||||||
PNP_WAIT_QUEUE WaitQueue;
|
PNP_WAIT_QUEUE WaitQueue;
|
||||||
UNICODE_STRING String;
|
UNICODE_STRING AliasName;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
|
} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
|
||||||
|
|
||||||
|
@ -590,7 +590,7 @@ NTAPI
|
||||||
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
IN LARGE_INTEGER WaitTime,
|
IN LARGE_INTEGER WaitTime,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN PUNICODE_STRING Name);
|
IN PUNICODE_STRING AliasName);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
|
@ -66,7 +66,6 @@ NpDeleteFcb(IN PNP_FCB Fcb,
|
||||||
IN PLIST_ENTRY ListEntry)
|
IN PLIST_ENTRY ListEntry)
|
||||||
{
|
{
|
||||||
PNP_DCB Dcb;
|
PNP_DCB Dcb;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
Dcb = Fcb->ParentDcb;
|
Dcb = Fcb->ParentDcb;
|
||||||
|
@ -76,7 +75,7 @@ NpDeleteFcb(IN PNP_FCB Fcb,
|
||||||
&Fcb->FullName,
|
&Fcb->FullName,
|
||||||
STATUS_OBJECT_NAME_NOT_FOUND,
|
STATUS_OBJECT_NAME_NOT_FOUND,
|
||||||
ListEntry);
|
ListEntry);
|
||||||
|
|
||||||
RemoveEntryList(&Fcb->DcbEntry);
|
RemoveEntryList(&Fcb->DcbEntry);
|
||||||
|
|
||||||
if (Fcb->SecurityDescriptor)
|
if (Fcb->SecurityDescriptor)
|
||||||
|
|
|
@ -45,7 +45,7 @@ NpCancelWaitQueueIrp(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
if (WaitEntry)
|
if (WaitEntry)
|
||||||
{
|
{
|
||||||
ObfDereferenceObject(WaitEntry->FileObject);
|
ObDereferenceObject(WaitEntry->FileObject);
|
||||||
ExFreePool(WaitEntry);
|
ExFreePool(WaitEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,23 +66,28 @@ NpTimerDispatch(IN PKDPC Dpc,
|
||||||
PNP_WAIT_QUEUE_ENTRY WaitEntry = Context;
|
PNP_WAIT_QUEUE_ENTRY WaitEntry = Context;
|
||||||
|
|
||||||
OldIrql = KfAcquireSpinLock(&WaitEntry->WaitQueue->WaitLock);
|
OldIrql = KfAcquireSpinLock(&WaitEntry->WaitQueue->WaitLock);
|
||||||
|
|
||||||
Irp = WaitEntry->Irp;
|
Irp = WaitEntry->Irp;
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
if (!IoSetCancelRoutine(Irp, NULL))
|
if (!IoSetCancelRoutine(Irp, NULL))
|
||||||
{
|
{
|
||||||
Irp->Tail.Overlay.DriverContext[1] = NULL;
|
Irp->Tail.Overlay.DriverContext[1] = NULL;
|
||||||
Irp = NULL;
|
Irp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KfReleaseSpinLock(&WaitEntry->WaitQueue->WaitLock, OldIrql);
|
KfReleaseSpinLock(&WaitEntry->WaitQueue->WaitLock, OldIrql);
|
||||||
|
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
|
Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
|
||||||
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
|
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
|
||||||
}
|
}
|
||||||
ObfDereferenceObject(WaitEntry->FileObject);
|
|
||||||
|
ObDereferenceObject(WaitEntry->FileObject);
|
||||||
ExFreePool(WaitEntry);
|
ExFreePool(WaitEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +104,22 @@ NTAPI
|
||||||
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
IN PUNICODE_STRING PipeName,
|
IN PUNICODE_STRING PipeName,
|
||||||
IN NTSTATUS Status,
|
IN NTSTATUS Status,
|
||||||
IN PLIST_ENTRY ListEntry)
|
IN PLIST_ENTRY List)
|
||||||
{
|
{
|
||||||
UNICODE_STRING DestinationString;
|
UNICODE_STRING DestinationString;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PWCHAR Buffer;
|
PWCHAR Buffer;
|
||||||
|
PLIST_ENTRY NextEntry;
|
||||||
|
PNP_WAIT_QUEUE_ENTRY WaitEntry, Linkage;
|
||||||
|
PIRP WaitIrp;
|
||||||
|
PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer;
|
||||||
|
ULONG i, NameLength;
|
||||||
|
|
||||||
Buffer = ExAllocatePoolWithTag(NonPagedPool, PipeName->Length, NPFS_WAIT_BLOCK_TAG);
|
Linkage = NULL;
|
||||||
|
|
||||||
|
Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
PipeName->Length,
|
||||||
|
NPFS_WAIT_BLOCK_TAG);
|
||||||
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
|
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
RtlInitEmptyUnicodeString(&DestinationString, Buffer, PipeName->Length);
|
RtlInitEmptyUnicodeString(&DestinationString, Buffer, PipeName->Length);
|
||||||
|
@ -113,10 +127,78 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
|
|
||||||
OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
|
OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
|
||||||
|
|
||||||
ASSERT(IsListEmpty(&WaitQueue->WaitList) == TRUE);
|
for (NextEntry = WaitQueue->WaitList.Flink;
|
||||||
|
NextEntry != &WaitQueue->WaitList;
|
||||||
|
NextEntry = NextEntry->Flink)
|
||||||
|
{
|
||||||
|
WaitIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
WaitEntry = WaitIrp->Tail.Overlay.DriverContext[1];
|
||||||
|
|
||||||
|
if (WaitEntry->AliasName.Length)
|
||||||
|
{
|
||||||
|
ASSERT(FALSE);
|
||||||
|
if (DestinationString.Length == WaitEntry->AliasName.Length)
|
||||||
|
{
|
||||||
|
if (RtlCompareMemory(WaitEntry->AliasName.Buffer,
|
||||||
|
DestinationString.Buffer,
|
||||||
|
DestinationString.Length) ==
|
||||||
|
DestinationString.Length)
|
||||||
|
{
|
||||||
|
CancelWait:
|
||||||
|
RemoveEntryList(&WaitIrp->Tail.Overlay.ListEntry);
|
||||||
|
if (KeCancelTimer(&WaitEntry->Timer))
|
||||||
|
{
|
||||||
|
WaitEntry->WaitQueue = (PNP_WAIT_QUEUE)Linkage;
|
||||||
|
Linkage = WaitEntry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitEntry->Irp = NULL;
|
||||||
|
WaitIrp->Tail.Overlay.DriverContext[1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IoSetCancelRoutine(WaitIrp, NULL))
|
||||||
|
{
|
||||||
|
WaitIrp->IoStatus.Information = 0;
|
||||||
|
WaitIrp->IoStatus.Status = Status;
|
||||||
|
InsertTailList(List, &WaitIrp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitIrp->Tail.Overlay.DriverContext[1] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitBuffer = WaitIrp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
if (WaitBuffer->NameLength + sizeof(WCHAR) == DestinationString.Length)
|
||||||
|
{
|
||||||
|
NameLength = WaitBuffer->NameLength / sizeof(WCHAR);
|
||||||
|
for (i = 0; i < NameLength; i++)
|
||||||
|
{
|
||||||
|
if (WaitBuffer->Name[i] != DestinationString.Buffer[i + 1]) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= NameLength) goto CancelWait;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
|
KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
|
||||||
|
|
||||||
ExFreePool(DestinationString.Buffer);
|
ExFreePool(DestinationString.Buffer);
|
||||||
|
|
||||||
|
while (Linkage)
|
||||||
|
{
|
||||||
|
WaitEntry = Linkage;
|
||||||
|
Linkage = (PNP_WAIT_QUEUE_ENTRY)Linkage->WaitQueue;
|
||||||
|
ObDereferenceObject(WaitEntry->FileObject);
|
||||||
|
ExFreePool(WaitEntry);
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +206,8 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
IN LARGE_INTEGER WaitTime,
|
IN LARGE_INTEGER WaitTime,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN PUNICODE_STRING Name)
|
IN PUNICODE_STRING AliasName)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
@ -137,71 +219,74 @@ NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
WaitEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(*WaitEntry), NPFS_WRITE_BLOCK_TAG);
|
WaitEntry = ExAllocatePoolWithQuotaTag(NonPagedPool,
|
||||||
if (WaitEntry)
|
sizeof(*WaitEntry),
|
||||||
|
NPFS_WRITE_BLOCK_TAG);
|
||||||
|
if (!WaitEntry)
|
||||||
{
|
{
|
||||||
KeInitializeDpc(&WaitEntry->Dpc, NpTimerDispatch, WaitEntry);
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
KeInitializeTimer(&WaitEntry->Timer);
|
}
|
||||||
|
|
||||||
if (Name)
|
KeInitializeDpc(&WaitEntry->Dpc, NpTimerDispatch, WaitEntry);
|
||||||
{
|
KeInitializeTimer(&WaitEntry->Timer);
|
||||||
WaitEntry->String = *Name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WaitEntry->String.Length = 0;
|
|
||||||
WaitEntry->String.Buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitEntry->WaitQueue = WaitQueue;
|
if (AliasName)
|
||||||
WaitEntry->Irp = Irp;
|
{
|
||||||
|
WaitEntry->AliasName = *AliasName;
|
||||||
WaitBuffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
|
|
||||||
if (WaitBuffer->TimeoutSpecified)
|
|
||||||
{
|
|
||||||
DueTime = WaitBuffer->Timeout;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DueTime = WaitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < WaitBuffer->NameLength / sizeof(WCHAR); i++)
|
|
||||||
{
|
|
||||||
WaitBuffer->Name[i] = RtlUpcaseUnicodeChar(WaitBuffer->Name[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->Tail.Overlay.DriverContext[0] = WaitQueue;
|
|
||||||
Irp->Tail.Overlay.DriverContext[1] = WaitEntry;
|
|
||||||
OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
|
|
||||||
|
|
||||||
IoSetCancelRoutine(Irp, NpCancelWaitQueueIrp);
|
|
||||||
|
|
||||||
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
|
||||||
{
|
|
||||||
Status = STATUS_CANCELLED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
InsertTailList(&WaitQueue->WaitList, &Irp->Tail.Overlay.ListEntry);
|
|
||||||
|
|
||||||
IoMarkIrpPending(Irp);
|
|
||||||
Status = STATUS_PENDING;
|
|
||||||
|
|
||||||
WaitEntry->FileObject = IoStack->FileObject;
|
|
||||||
ObfReferenceObject(WaitEntry->FileObject);
|
|
||||||
|
|
||||||
KeSetTimer(&WaitEntry->Timer, DueTime, &WaitEntry->Dpc);
|
|
||||||
WaitEntry = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
|
|
||||||
if (WaitEntry) ExFreePool(WaitEntry);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
WaitEntry->AliasName.Length = 0;
|
||||||
|
WaitEntry->AliasName.Buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WaitEntry->WaitQueue = WaitQueue;
|
||||||
|
WaitEntry->Irp = Irp;
|
||||||
|
|
||||||
|
WaitBuffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
if (WaitBuffer->TimeoutSpecified)
|
||||||
|
{
|
||||||
|
DueTime = WaitBuffer->Timeout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DueTime = WaitTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < WaitBuffer->NameLength / sizeof(WCHAR); i++)
|
||||||
|
{
|
||||||
|
WaitBuffer->Name[i] = RtlUpcaseUnicodeChar(WaitBuffer->Name[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->Tail.Overlay.DriverContext[0] = WaitQueue;
|
||||||
|
Irp->Tail.Overlay.DriverContext[1] = WaitEntry;
|
||||||
|
|
||||||
|
OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
|
||||||
|
|
||||||
|
IoSetCancelRoutine(Irp, NpCancelWaitQueueIrp);
|
||||||
|
|
||||||
|
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
||||||
|
{
|
||||||
|
Status = STATUS_CANCELLED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertTailList(&WaitQueue->WaitList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
Status = STATUS_PENDING;
|
||||||
|
|
||||||
|
WaitEntry->FileObject = IoStack->FileObject;
|
||||||
|
ObReferenceObject(WaitEntry->FileObject);
|
||||||
|
|
||||||
|
KeSetTimer(&WaitEntry->Timer, DueTime, &WaitEntry->Dpc);
|
||||||
|
WaitEntry = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
|
||||||
|
if (WaitEntry) ExFreePool(WaitEntry);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue