[NPFS-NEW]: Multiple code fixes to almost all code paths. Mainly a collection of small bugs, structural errors, logic flaws, off-by-ones, etc. But they were enough to make the driver essentially useless. Now Thomas's kmtests NpfsCreate and NpfsConnect return absolutely zero failures. On to NpfsReadWrite....

svn path=/trunk/; revision=60027
This commit is contained in:
Alex Ionescu 2013-09-11 02:04:17 +00:00
parent f2664a3227
commit a8e4859598
6 changed files with 170 additions and 121 deletions

View file

@ -14,6 +14,7 @@ NpCheckForNotify(IN PNP_DCB Dcb,
ListHead = &Dcb->NotifyList;
for (i = 0; i < 2; i++)
{
ASSERT(IsListEmpty(ListHead));
while (!IsListEmpty(ListHead))
{
NextEntry = RemoveHeadList(ListHead);
@ -47,7 +48,7 @@ NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
++NpVcb->ReferenceCount;
Status.Information = 1;
Status.Information = FILE_OPENED;
Status.Status = STATUS_SUCCESS;
return Status;
}
@ -69,7 +70,7 @@ NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
++Dcb->CurrentInstances;
Status.Information = 1;
Status.Information = FILE_OPENED;
Status.Status = STATUS_SUCCESS;
}
else
@ -130,7 +131,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
if (AccessGranted)
{
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000);
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
}
ObjectTypeName.Buffer = L"NamedPipe";
@ -147,14 +148,14 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
SeUnlockSubjectContext(SubjectSecurityContext);
if (!AccessGranted) return IoStatus;
if (((GrantedAccess & 1) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
((GrantedAccess & 2) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
if (((AccessGranted & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
((AccessGranted & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
if (!(GrantedAccess & 3)) SecurityQos = NULL;
if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL;
ListHead = &Fcb->CcbList;
NextEntry = ListHead->Flink;
@ -185,7 +186,7 @@ NpCreateClientEnd(IN PNP_FCB Fcb,
Ccb->ClientSession = NULL;
Ccb->Process = IoThreadToProcess(Thread);
IoStatus.Information = 1;
IoStatus.Information = FILE_OPENED;
IoStatus.Status = STATUS_SUCCESS;
return IoStatus;
}
@ -205,7 +206,9 @@ NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
PNP_DCB Dcb;
ACCESS_MASK DesiredAccess;
LIST_ENTRY List;
PLIST_ENTRY NextEntry, ThisEntry;
UNICODE_STRING Prefix;
PIRP ListIrp;
InitializeListHead(&List);
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
@ -235,20 +238,22 @@ NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
if (FileName.Length)
{
if ((FileName.Length == sizeof(WCHAR)) &&
if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
!(RelatedFileObject))
{
Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
FileObject,
DesiredAccess,
&List);
FileObject,
DesiredAccess,
&List);
goto Quickie;
}
}
else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
{
Irp->IoStatus = NpOpenNamedPipeFileSystem(FileObject,
DesiredAccess);
goto Quickie;
}
else if (Type == NPFS_NTC_ROOT_DCB)
{
@ -256,77 +261,94 @@ NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
FileObject,
DesiredAccess,
&List);
goto Quickie;
}
// Status = NpTranslateAlias(&FileName);; // ignore this for now
// if (!NT_SUCCESS(Status)) goto Quickie;
if (RelatedFileObject)
{
if (Type == NPFS_NTC_ROOT_DCB)
{
Dcb = (PNP_DCB)Ccb;
Irp->IoStatus.Status = NpFindRelativePrefix(Dcb,
&FileName,
1,
&Prefix,
&Fcb);
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
goto Quickie;
}
}
else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
else
{
Prefix.Length = 0;
}
}
else
{
// Status = NpTranslateAlias(&FileName);; // ignore this for now
// if (!NT_SUCCESS(Status)) goto Quickie;
if (RelatedFileObject)
if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
(FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
if (Type == NPFS_NTC_ROOT_DCB)
{
Dcb = (PNP_DCB)Ccb;
Irp->IoStatus.Status = NpFindRelativePrefix(Dcb,
&FileName,
1,
&Prefix,
&Fcb);
if (!NT_SUCCESS(Irp->IoStatus.Status)) goto Quickie;
}
else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
else
{
Prefix.Length = 0;
}
}
else
{
if ((FileName.Length <= sizeof(WCHAR)) ||
(FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Fcb = NpFindPrefix(&FileName, 1, &Prefix);
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
if (Prefix.Length)
{
Irp->IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
STATUS_OBJECT_NAME_NOT_FOUND :
STATUS_OBJECT_NAME_INVALID;
}
if (!Fcb->CurrentInstances)
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
Irp->IoStatus = NpCreateClientEnd(Fcb,
FileObject,
DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->SecurityQos,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Irp->Tail.Overlay.Thread,
&List);
}
Fcb = NpFindPrefix(&FileName, TRUE, &Prefix);
}
if (Prefix.Length)
{
Irp->IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
STATUS_OBJECT_NAME_NOT_FOUND :
STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
if (Fcb->NodeType != NPFS_NTC_FCB)
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
if (!Fcb->ServerOpenCount)
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Quickie;
}
Irp->IoStatus = NpCreateClientEnd(Fcb,
FileObject,
DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->SecurityQos,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Irp->Tail.Overlay.Thread,
&List);
Quickie:
ExReleaseResourceLite(&NpVcb->Lock);
ASSERT(IsListEmpty(&List) == TRUE);
NextEntry = List.Flink;
while (NextEntry != &List)
{
ThisEntry = NextEntry;
NextEntry = NextEntry->Flink;
ListIrp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(ListIrp, IO_DISK_INCREMENT);
}
FsRtlExitFileSystem();
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@ -582,10 +604,11 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
NpCheckForNotify(Dcb, 1, List);
NpCheckForNotify(Dcb, TRUE, List);
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = 2;
IoStatus->Information = FILE_CREATED;
return STATUS_SUCCESS;
Quickie:
@ -605,11 +628,13 @@ NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
USHORT Disposition, ShareAccess;
PEPROCESS Process;
LIST_ENTRY LocalList;
PLIST_ENTRY NextEntry, ThisEntry;
UNICODE_STRING FileName;
PNP_FCB Fcb;
UNICODE_STRING Prefix;
PNAMED_PIPE_CREATE_PARAMETERS Parameters;
IO_STATUS_BLOCK IoStatus;
PIRP ListIrp;
DPRINT1("NpFsdCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
@ -655,16 +680,21 @@ NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
TRUE,
&Prefix,
&Fcb);
if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
if (!NT_SUCCESS(IoStatus.Status))
{
goto Quickie;
}
}
else
{
if (FileName.Length <= 2u || *FileName.Buffer != '\\')
if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) ||
FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Fcb = NpFindPrefix(&FileName, 1u, &Prefix);
Fcb = NpFindPrefix(&FileName, TRUE, &Prefix);
}
if (Prefix.Length)
@ -683,7 +713,7 @@ NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
Parameters,
Process,
&LocalList,
&Irp->IoStatus);
&IoStatus);
goto Quickie;
}
else
@ -692,30 +722,40 @@ NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
goto Quickie;
}
}
if (Fcb->NodeType != NPFS_NTC_FCB)
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Irp->IoStatus = NpCreateExistingNamedPipe(Fcb,
FileObject,
IoStack->Parameters.CreatePipe.
SecurityContext->DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Disposition,
ShareAccess,
Parameters,
Process,
&LocalList);
IoStatus = NpCreateExistingNamedPipe(Fcb,
FileObject,
IoStack->Parameters.CreatePipe.
SecurityContext->DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Disposition,
ShareAccess,
Parameters,
Process,
&LocalList);
Quickie:
ExReleaseResourceLite(&NpVcb->Lock);
ASSERT(IsListEmpty(&LocalList));
NextEntry = LocalList.Flink;
while (NextEntry != &LocalList)
{
ThisEntry = NextEntry;
NextEntry = NextEntry->Flink;
ListIrp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(ListIrp, IO_DISK_INCREMENT);
}
FsRtlExitFileSystem();

View file

@ -437,7 +437,7 @@ NpAddDataQueueEntry(IN ULONG NamedPipeEnd,
ASSERT(ByteOffset < DataEntry->DataSize);
ASSERT(DataQueue->EntriesInQueue == 1);
}
InsertTailList(&DataQueue->Queue, &DataEntry->QueueEntry);
if (Status == STATUS_PENDING)

View file

@ -327,7 +327,7 @@ NpQueryPipeLocalInfo(IN PNP_FCB Fcb,
{
InfoBuffer->ReadDataAvailable = InQueue->BytesInQueue - InQueue->ByteOffset;
}
InfoBuffer->WriteQuotaAvailable = OutQueue->QuotaUsed;
InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - OutQueue->QuotaUsed;
}
else
{
@ -335,7 +335,7 @@ NpQueryPipeLocalInfo(IN PNP_FCB Fcb,
{
InfoBuffer->ReadDataAvailable = OutQueue->BytesInQueue - OutQueue->ByteOffset;
}
InfoBuffer->WriteQuotaAvailable = InQueue->QuotaUsed;
InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - InQueue->QuotaUsed;
}
return STATUS_SUCCESS;

View file

@ -181,6 +181,7 @@ typedef struct _NP_DCB
LIST_ENTRY NotifyList;
LIST_ENTRY NotifyList2;
LIST_ENTRY FcbList;
ULONG Pad;
//
// Common Footer
@ -213,6 +214,8 @@ typedef struct _NP_FCB
NP_CB_FOOTER;
} NP_FCB, *PNP_FCB;
C_ASSERT(FIELD_OFFSET(NP_FCB, PrefixTableEntry) == FIELD_OFFSET(NP_DCB, PrefixTableEntry));
//
// The nonpaged portion of the CCB
//

View file

@ -96,7 +96,7 @@ NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
break;
case FILE_PIPE_CONNECTED_STATE:
EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END];
while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
@ -121,12 +121,13 @@ NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
Status = STATUS_SUCCESS;
break;
// drop down on purpose... queue will be empty so flush code is nop
ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty);
case FILE_PIPE_CLOSING_STATE:
EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END];
while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
{
Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List);
@ -177,11 +178,11 @@ NpSetListeningPipeState(IN PNP_CCB Ccb,
{
case FILE_PIPE_DISCONNECTED_STATE:
Status = NpCancelWaiter(&NpVcb->WaitQueue,
&Ccb->Fcb->FullName,
STATUS_SUCCESS,
List);
if (!NT_SUCCESS(Status)) return Status;
Status = NpCancelWaiter(&NpVcb->WaitQueue,
&Ccb->Fcb->FullName,
STATUS_SUCCESS,
List);
if (!NT_SUCCESS(Status)) return Status;
//
// Drop down on purpose
@ -203,7 +204,7 @@ NpSetListeningPipeState(IN PNP_CCB Ccb,
Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
IoMarkIrpPending(Irp);
InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
InsertTailList(&Ccb->IrpList, &Irp->Tail.Overlay.ListEntry);
return STATUS_PENDING;
case FILE_PIPE_CONNECTED_STATE:

View file

@ -53,7 +53,7 @@ NpDeleteFcb(IN PNP_FCB Fcb,
PAGED_CODE();
Dcb = Fcb->ParentDcb;
if (!Fcb->CurrentInstances) KeBugCheckEx(NPFS_FILE_SYSTEM, 0x17025F, 0, 0, 0);
if (Fcb->CurrentInstances) KeBugCheckEx(NPFS_FILE_SYSTEM, 0x17025F, 0, 0, 0);
NpCancelWaiter(&NpVcb->WaitQueue,
&Fcb->FullName,
@ -205,23 +205,26 @@ NpCreateFcb(IN PNP_DCB Dcb,
BOOLEAN RootPipe;
PWCHAR NameBuffer;
ULONG BufferOffset;
USHORT PipeNameLength;
USHORT Length, MaximumLength;
PAGED_CODE();
PipeNameLength = PipeName->Length;
Length = PipeName->Length;
MaximumLength = Length + sizeof(UNICODE_NULL);
if ((PipeNameLength < sizeof(WCHAR)) ||
((PipeNameLength + sizeof(WCHAR)) < PipeNameLength) ||
(PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
if ((Length < sizeof(WCHAR)) || (MaximumLength < Length))
{
return STATUS_INVALID_PARAMETER;
}
RootPipe = FALSE;
if (PipeNameLength == sizeof(WCHAR))
if (PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
{
MaximumLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
RootPipe = TRUE;
PipeNameLength += sizeof(WCHAR);
if (MaximumLength < sizeof(WCHAR))
{
return STATUS_INVALID_PARAMETER;
}
}
Fcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Fcb), NPFS_FCB_TAG);
@ -235,7 +238,7 @@ NpCreateFcb(IN PNP_DCB Dcb,
InitializeListHead(&Fcb->CcbList);
NameBuffer = ExAllocatePoolWithTag(PagedPool,
PipeName->Length + (RootPipe ? 4 : 2),
MaximumLength,
NPFS_NAME_BLOCK_TAG);
if (!NameBuffer)
{
@ -248,19 +251,19 @@ NpCreateFcb(IN PNP_DCB Dcb,
BufferOffset = 0;
if (RootPipe)
{
*NameBuffer = OBJ_NAME_PATH_SEPARATOR;
NameBuffer[0] = OBJ_NAME_PATH_SEPARATOR;
BufferOffset = 1;
}
RtlCopyMemory(NameBuffer + BufferOffset, PipeName->Buffer, PipeNameLength);
NameBuffer[BufferOffset + (PipeNameLength / sizeof(WCHAR))] = UNICODE_NULL;
RtlCopyMemory(NameBuffer + BufferOffset, PipeName->Buffer, Length);
NameBuffer[BufferOffset + (Length / sizeof(WCHAR))] = UNICODE_NULL;
Fcb->FullName.Length = PipeNameLength - sizeof(WCHAR);
Fcb->FullName.MaximumLength = PipeNameLength;
Fcb->FullName.Length = Length;
Fcb->FullName.MaximumLength = MaximumLength;
Fcb->FullName.Buffer = NameBuffer;
Fcb->ShortName.MaximumLength = PipeNameLength - sizeof(WCHAR);
Fcb->ShortName.Length = PipeNameLength - 2 * sizeof(WCHAR);
Fcb->ShortName.MaximumLength = Length;
Fcb->ShortName.Length = Length - sizeof(OBJ_NAME_PATH_SEPARATOR);
Fcb->ShortName.Buffer = NameBuffer + 1;
if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
@ -333,6 +336,8 @@ NpCreateCcb(IN PNP_FCB Fcb,
InsertTailList(&Fcb->CcbList, &Ccb->CcbEntry);
Fcb->CurrentInstances++;
Fcb->ServerOpenCount++;
InitializeListHead(&Ccb->IrpList);
ExInitializeResourceLite(&Ccb->NonPagedCcb->Lock);
*NewCcb = Ccb;