[NPFS/NPFS_NEW]

* Make npfs_new the one and only npfs. One of the few foo_new modules that actually made it and I hope it won't be the last ;)
CORE-7451

svn path=/trunk/; revision=60611
This commit is contained in:
Amine Khaldi 2013-10-11 15:19:46 +00:00
parent 9f4686524d
commit 429a1c4b23
27 changed files with 1938 additions and 4004 deletions

View file

@ -6,5 +6,5 @@ add_subdirectory(fastfat)
add_subdirectory(fs_rec)
add_subdirectory(msfs)
add_subdirectory(mup)
add_subdirectory(npfs_new)
add_subdirectory(npfs)
add_subdirectory(ntfs)

View file

@ -1,19 +1,29 @@
list(APPEND SOURCE
cleanup.c
close.c
create.c
dirctl.c
finfo.c
datasup.c
fileinfo.c
fileobsup.c
flushbuf.c
fsctrl.c
npfs.c
rw.c
volume.c
npfs.rc)
main.c
prefxsup.c
read.c
readsup.c
secursup.c
seinfo.c
statesup.c
strucsup.c
volinfo.c
waitsup.c
write.c
writesup.c)
add_library(npfs SHARED ${SOURCE})
target_link_libraries(npfs ${PSEH_LIB})
set_module_type(npfs kernelmodedriver)
target_link_libraries(npfs ${PSEH_LIB})
add_importlibs(npfs ntoskrnl hal)
add_pch(npfs npfs.h)
add_cd_file(TARGET npfs DESTINATION reactos/system32/drivers FOR all)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,208 +1,675 @@
#ifndef __DRIVERS_FS_NP_NPFS_H
#define __DRIVERS_FS_NP_NPFS_H
/*
* PROJECT: ReactOS Named Pipe FileSystem
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/filesystems/npfs/npfs.h
* PURPOSE: Named Pipe FileSystem Header
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
//
// System Headers
//
#include <ntifs.h>
#include <ndk/iotypes.h>
#include <ntndk.h>
#include <pseh/pseh2.h>
#define UNIMPLEMENTED
#define DPRINT1 DbgPrint
#define TAG_NPFS_CCB 'cFpN'
#define TAG_NPFS_CCB_DATA 'iFpN' /* correct? */
#define TAG_NPFS_FCB 'FFpN'
#define TAG_NPFS_NAMEBLOCK 'nFpN'
#define TAG_NPFS_THREAD_CONTEXT 'tFpN'
//
// Allow Microsoft Extensions
//
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable:4214)
#pragma warning(disable:4100)
#endif
#define ROUND_DOWN(n, align) \
(((ULONG)n) & ~((align) - 1l))
#define ROUND_UP(n, align) \
ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
/* TYPEDEFS & DEFINES *********************************************************/
typedef enum _FCB_TYPE
//
// Pool Tags for NPFS (from pooltag.txt)
//
// Npf* -npfs.sys - Npfs Allocations
// NpFc - npfs.sys - CCB, client control block
// NpFf - npfs.sys - FCB, file control block
// NpFC - npfs.sys - ROOT_DCB CCB
// NpFD - npfs.sys - DCB, directory block
// NpFg - npfs.sys - Global storage
// NpFi - npfs.sys - NPFS client info buffer.
// NpFn - npfs.sys - Name block
// NpFq - npfs.sys - Query template buffer used for directory query
// NpFr - npfs.sys - DATA_ENTRY records(read / write buffers)
// NpFs - npfs.sys - Client security context
// NpFw - npfs.sys - Write block
// NpFW - npfs.sys - Write block
#define NPFS_CCB_TAG 'NpFc'
#define NPFS_ROOT_DCB_CCB_TAG 'NpFC'
#define NPFS_DCB_TAG 'NpFD'
#define NPFS_FCB_TAG 'NpFf'
#define NPFS_GLOBAL_TAG 'NpFg'
#define NPFS_CLIENT_INFO_TAG 'NpFi'
#define NPFS_NAME_BLOCK_TAG 'NpFn'
#define NPFS_QUERY_TEMPLATE_TAG 'NpFq'
#define NPFS_DATA_ENTRY_TAG 'NpFr'
#define NPFS_CLIENT_SEC_CTX_TAG 'NpFs'
#define NPFS_WAIT_BLOCK_TAG 'NpFt'
#define NPFS_WRITE_BLOCK_TAG 'NpFw'
//
// NPFS bugchecking support
//
// We define the NpBugCheck macro which triggers a NPFS_FILE_SYSTEM bugcheck
// containing the source file ID number and the line where it was emitted, as
// described in the MSDN article "Bug Check 0x25: NPFS_FILE_SYSTEM".
//
// The bugcheck emits 4 ULONGs; the first one is made, in its high word, by
// the current source file ID and in its low word, by the line number; the
// three other ones are user-defined.
//
// In order to avoid redefinition of the same file ID in different source files,
// we gather all of them here, so that you will have to add (or remove) a new
// one as soon as you add (or remove) a source file from the NPFS driver code.
//
// To use the NpBugCheck macro in a source file, define at its beginning
// the constant NPFS_BUGCHECK_FILE_ID with one of the following file IDs,
// then use the bugcheck macro wherever you want.
//
#define NPFS_BUGCHECK_CLEANUP 0x0001
#define NPFS_BUGCHECK_CLOSE 0x0002
#define NPFS_BUGCHECK_CREATE 0x0003
#define NPFS_BUGCHECK_DATASUP 0x0004
#define NPFS_BUGCHECK_FILEINFO 0x0005
#define NPFS_BUGCHECK_FILEOBSUP 0x0006
#define NPFS_BUGCHECK_FLUSHBUF 0x0007
#define NPFS_BUGCHECK_FSCTRL 0x0008
#define NPFS_BUGCHECK_MAIN 0x0009
#define NPFS_BUGCHECK_PREFXSUP 0x000a
#define NPFS_BUGCHECK_READ 0x000b
#define NPFS_BUGCHECK_READSUP 0x000c
#define NPFS_BUGCHECK_SECURSUP 0x000d
#define NPFS_BUGCHECK_SEINFO 0x000e
#define NPFS_BUGCHECK_STATESUP 0x000f
#define NPFS_BUGCHECK_STRUCSUP 0x0010
#define NPFS_BUGCHECK_VOLINFO 0x0011
#define NPFS_BUGCHECK_WAITSUP 0x0012
#define NPFS_BUGCHECK_WRITE 0x0013
#define NPFS_BUGCHECK_WRITESUP 0x0014
#define NpBugCheck(p1, p2, p3) \
KeBugCheckEx(NPFS_FILE_SYSTEM, \
(NPFS_BUGCHECK_FILE_ID << 16) | __LINE__, \
(p1), (p2), (p3))
//
// Node Type Codes for NPFS
//
#define NPFS_NTC_VCB 1
#define NPFS_NTC_ROOT_DCB 2
#define NPFS_NTC_FCB 4
#define NPFS_NTC_CCB 6
#define NPFS_NTC_NONPAGED_CCB 7
#define NPFS_NTC_ROOT_DCB_CCB 8
typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
//
// Data Queue States
//
typedef enum _NP_DATA_QUEUE_STATE
{
FCB_INVALID,
FCB_DEVICE,
FCB_DIRECTORY,
FCB_PIPE
} FCB_TYPE;
ReadEntries = 0,
WriteEntries = 1,
Empty = 2
} NP_DATA_QUEUE_STATE;
typedef enum _CCB_TYPE
//
// Data Queue Entry Types
//
typedef enum _NP_DATA_QUEUE_ENTRY_TYPE
{
CCB_INVALID,
CCB_DEVICE,
CCB_DIRECTORY,
CCB_PIPE
} CCB_TYPE;
Buffered = 0,
Unbuffered
} NP_DATA_QUEUE_ENTRY_TYPE;
/* Volume Control Block (VCB) aka Device Extension */
typedef struct _NPFS_VCB
//
// An Input or Output Data Queue. Each CCB has two of these.
//
typedef struct _NP_DATA_QUEUE
{
LIST_ENTRY PipeListHead;
LIST_ENTRY ThreadListHead;
KMUTEX PipeListLock;
ULONG EmptyWaiterCount;
ULONG MinQuota;
ULONG DefaultQuota;
ULONG MaxQuota;
struct _NPFS_FCB *DeviceFcb;
struct _NPFS_FCB *RootFcb;
} NPFS_VCB, *PNPFS_VCB;
LIST_ENTRY Queue;
ULONG QueueState;
ULONG BytesInQueue;
ULONG EntriesInQueue;
ULONG QuotaUsed;
ULONG ByteOffset;
ULONG Quota;
} NP_DATA_QUEUE, *PNP_DATA_QUEUE;
typedef struct _NPFS_FCB
//
// The Entries that go into the Queue
//
typedef struct _NP_DATA_QUEUE_ENTRY
{
FCB_TYPE Type;
PNPFS_VCB Vcb;
volatile LONG RefCount;
UNICODE_STRING PipeName;
LIST_ENTRY PipeListEntry;
KMUTEX CcbListLock;
LIST_ENTRY ServerCcbListHead;
LIST_ENTRY ClientCcbListHead;
LIST_ENTRY WaiterListHead;
LIST_ENTRY EmptyBufferListHead;
ULONG PipeType;
ULONG ClientReadMode;
ULONG ServerReadMode;
ULONG CompletionMode;
ULONG PipeConfiguration;
ULONG MaximumInstances;
ULONG CurrentInstances;
ULONG InboundQuota;
ULONG OutboundQuota;
LARGE_INTEGER TimeOut;
} NPFS_FCB, *PNPFS_FCB;
LIST_ENTRY QueueEntry;
ULONG DataEntryType;
PIRP Irp;
ULONG QuotaInEntry;
PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
ULONG DataSize;
} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY;
typedef struct _NPFS_CCB_DIRECTORY_DATA
//
// A Wait Queue. Only the VCB has one of these.
//
typedef struct _NP_WAIT_QUEUE
{
UNICODE_STRING SearchPattern;
ULONG FileIndex;
} NPFS_CCB_DIRECTORY_DATA, *PNPFS_CCB_DIRECTORY_DATA;
LIST_ENTRY WaitList;
KSPIN_LOCK WaitLock;
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
typedef struct _NPFS_CCB
//
// The Entries in the Queue above, one for each Waiter.
//
typedef struct _NP_WAIT_QUEUE_ENTRY
{
LIST_ENTRY CcbListEntry;
CCB_TYPE Type;
PNPFS_FCB Fcb;
PIRP Irp;
KDPC Dpc;
KTIMER Timer;
PNP_WAIT_QUEUE WaitQueue;
UNICODE_STRING AliasName;
PFILE_OBJECT FileObject;
} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
struct _NPFS_CCB* OtherSide;
struct ETHREAD *Thread;
KEVENT ConnectEvent;
KEVENT ReadEvent;
KEVENT WriteEvent;
ULONG PipeEnd;
ULONG PipeState;
ULONG ReadDataAvailable;
ULONG WriteQuotaAvailable;
volatile LONG RefCount;
//
// The event buffer in the NonPaged CCB
//
typedef struct _NP_EVENT_BUFFER
{
PKEVENT Event;
} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER;
LIST_ENTRY ReadRequestListHead;
//
// The CCB for the Root DCB
//
typedef struct _NP_ROOT_DCB_CCB
{
NODE_TYPE_CODE NodeType;
PVOID Unknown;
ULONG Unknown2;
} NP_ROOT_DCB_CCB, *PNP_ROOT_DCB_FCB;
PVOID Data;
PVOID ReadPtr;
PVOID WritePtr;
ULONG MaxDataLength;
//
// The header that both FCB and DCB share
//
typedef struct _NP_CB_HEADER
{
NODE_TYPE_CODE NodeType;
LIST_ENTRY DcbEntry;
PVOID ParentDcb;
ULONG CurrentInstances;
ULONG ServerOpenCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} NP_CB_HEADER, *PNP_CB_HEADER;
FAST_MUTEX DataListLock; /* Data queue lock */
//
// The footer that both FCB and DCB share
//
typedef struct _NP_CB_FOOTER
{
UNICODE_STRING FullName;
UNICODE_STRING ShortName;
UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry;
} NP_CB_FOOTER;
union
//
// A Directory Control Block (DCB)
//
typedef struct _NP_DCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// DCB-specific data
//
LIST_ENTRY NotifyList;
LIST_ENTRY NotifyList2;
LIST_ENTRY FcbList;
#ifndef _WIN64
ULONG Pad;
#endif
//
// Common Footer
//
NP_CB_FOOTER;
} NP_DCB, *PNP_DCB;
//
// A File Control BLock (FCB)
//
typedef struct _NP_FCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// FCB-specific fields
//
ULONG MaximumInstances;
USHORT NamedPipeConfiguration;
USHORT NamedPipeType;
LARGE_INTEGER Timeout;
LIST_ENTRY CcbList;
#ifdef _WIN64
PVOID Pad[2];
#endif
//
// Common Footer
//
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
//
typedef struct _NP_NONPAGED_CCB
{
NODE_TYPE_CODE NodeType;
PNP_EVENT_BUFFER EventBuffer[2];
ERESOURCE Lock;
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
//
// A Client Control Block (CCB)
//
typedef struct _NP_CCB
{
NODE_TYPE_CODE NodeType;
UCHAR NamedPipeState;
UCHAR ReadMode[2];
UCHAR CompletionMode[2];
SECURITY_QUALITY_OF_SERVICE ClientQos;
LIST_ENTRY CcbEntry;
PNP_FCB Fcb;
PFILE_OBJECT FileObject[2];
PEPROCESS Process;
PVOID ClientSession;
PNP_NONPAGED_CCB NonPagedCcb;
NP_DATA_QUEUE DataQueue[2];
PSECURITY_CLIENT_CONTEXT ClientContext;
LIST_ENTRY IrpList;
} NP_CCB, *PNP_CCB;
//
// A Volume Control Block (VCB)
//
typedef struct _NP_VCB
{
NODE_TYPE_CODE NodeType;
ULONG ReferenceCount;
PNP_DCB RootDcb;
UNICODE_PREFIX_TABLE PrefixTable;
ERESOURCE Lock;
RTL_GENERIC_TABLE EventTable;
NP_WAIT_QUEUE WaitQueue;
} NP_VCB, *PNP_VCB;
extern PNP_VCB NpVcb;
/* FUNCTIONS ******************************************************************/
//
// Functions to lock/unlock the global VCB lock
//
FORCEINLINE
VOID
NpAcquireSharedVcb(VOID)
{
/* Acquire the lock in shared mode */
ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
}
FORCEINLINE
VOID
NpAcquireExclusiveVcb(VOID)
{
/* Acquire the lock in exclusive mode */
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
}
FORCEINLINE
VOID
NpReleaseVcb(VOID)
{
/* Release the lock */
ExReleaseResourceLite(&NpVcb->Lock);
}
//
// Function to process deferred IRPs outside the VCB lock but still within the
// critical region
//
VOID
FORCEINLINE
NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
{
PLIST_ENTRY ThisEntry, NextEntry;
PIRP Irp;
/* Loop the list */
ThisEntry = DeferredList->Flink;
while (ThisEntry != DeferredList)
{
NPFS_CCB_DIRECTORY_DATA Directory;
} u;
/* Remember the next entry, but don't switch to it yet */
NextEntry = ThisEntry->Flink;
} NPFS_CCB, *PNPFS_CCB;
/* Complete the IRP for this entry */
Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
typedef struct _NPFS_CONTEXT
{
LIST_ENTRY ListEntry;
PKEVENT WaitEvent;
} NPFS_CONTEXT, *PNPFS_CONTEXT;
/* And now switch to the next one */
ThisEntry = NextEntry;
}
}
typedef struct _NPFS_THREAD_CONTEXT
{
ULONG Count;
KEVENT Event;
PNPFS_VCB Vcb;
LIST_ENTRY ListEntry;
PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS];
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
PIRP WaitIrpArray[MAXIMUM_WAIT_OBJECTS];
} NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT;
typedef struct _NPFS_WAITER_ENTRY
{
LIST_ENTRY Entry;
PNPFS_CCB Ccb;
} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY;
extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList;
#define KeLockMutex(x) KeWaitForSingleObject(x, \
UserRequest, \
KernelMode, \
FALSE, \
NULL);
#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE);
#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)x)%PAGE_SIZE) ? ((((ULONG_PTR)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG_PTR)x) )
DRIVER_DISPATCH NpfsCreate;
NTSTATUS NTAPI NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsCreateNamedPipe;
NTSTATUS NTAPI NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsCleanup;
NTSTATUS NTAPI NpfsCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsClose;
NTSTATUS NTAPI NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsDirectoryControl;
NTSTATUS NTAPI NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsRead;
NTSTATUS NTAPI NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsWrite;
NTSTATUS NTAPI NpfsWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsFlushBuffers;
NTSTATUS NTAPI NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsFileSystemControl;
NTSTATUS NTAPI NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsQueryInformation;
NTSTATUS NTAPI NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsSetInformation;
NTSTATUS NTAPI NpfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
DRIVER_DISPATCH NpfsQueryVolumeInformation;
NTSTATUS NTAPI NpfsQueryVolumeInformation (PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
BOOLEAN
NTAPI
NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer);
VOID
NpfsDereferenceFcb(PNPFS_FCB Fcb);
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
PNPFS_FCB
NpfsFindPipe(PNPFS_VCB Vcb,
PUNICODE_STRING PipeName);
FCB_TYPE
NpfsGetFcb(PFILE_OBJECT FileObject,
PNPFS_FCB *Fcb);
NTSTATUS
NTAPI
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
CCB_TYPE
NpfsGetCcb(PFILE_OBJECT FileObject,
PNPFS_CCB *Ccb);
PLIST_ENTRY
NTAPI
NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
#endif /* __DRIVERS_FS_NP_NPFS_H */
PIRP
NTAPI
NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Flag,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpAddDataQueueEntry(IN ULONG NamedPipeEnd,
IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE DataQueue,
IN ULONG Who,
IN ULONG Type,
IN ULONG DataSize,
IN PIRP Irp,
IN PVOID Buffer,
IN ULONG ByteOffset);
VOID
NTAPI
NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN ULONG Quota);
NTSTATUS
NTAPI
NpCreateCcb(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN UCHAR State,
IN UCHAR ReadMode,
IN UCHAR CompletionMode,
IN ULONG InQuota,
IN ULONG OutQuota,
OUT PNP_CCB *NewCcb);
NTSTATUS
NTAPI
NpCreateFcb(IN PNP_DCB Dcb,
IN PUNICODE_STRING PipeName,
IN ULONG MaximumInstances,
IN LARGE_INTEGER Timeout,
IN USHORT NamedPipeConfiguration,
IN USHORT NamedPipeType,
OUT PNP_FCB *NewFcb);
NTSTATUS
NTAPI
NpCreateRootDcb(VOID);
NTSTATUS
NTAPI
NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb);
VOID
NTAPI
NpInitializeVcb(VOID);
VOID
NTAPI
NpDeleteCcb(IN PNP_CCB Ccb,
IN PLIST_ENTRY ListEntry);
VOID
NTAPI
NpDeleteFcb(IN PNP_FCB Fcb,
IN PLIST_ENTRY ListEntry);
NTSTATUS
NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetListeningPipeState(IN PNP_CCB Ccb,
IN PIRP Irp,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetClosingPipeState(IN PNP_CCB Ccb,
IN PIRP Irp,
IN ULONG NamedPipeEnd,
IN PLIST_ENTRY List);
VOID
NTAPI
NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
NTSTATUS
NTAPI
NpImpersonateClientContext(IN PNP_CCB Ccb);
VOID
NTAPI
NpCopyClientContext(IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE_ENTRY DataQueueEntry);
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb);
NTSTATUS
NTAPI
NpInitializeSecurity(IN PNP_CCB Ccb,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PETHREAD Thread);
NTSTATUS
NTAPI
NpGetClientSecurityContext(IN ULONG NamedPipeEnd,
IN PNP_CCB Ccb,
IN PETHREAD Thread,
IN PSECURITY_CLIENT_CONTEXT *Context);
VOID
NTAPI
NpSetFileObject(IN PFILE_OBJECT FileObject,
IN PVOID PrimaryContext,
IN PVOID Ccb,
IN ULONG NamedPipeEnd);
NODE_TYPE_CODE
NTAPI
NpDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVOID *PrimaryContext OPTIONAL,
OUT PNP_CCB *Ccb,
OUT PULONG NamedPipeEnd OPTIONAL);
PNP_FCB
NTAPI
NpFindPrefix(IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix);
NTSTATUS
NTAPI
NpFindRelativePrefix(IN PNP_DCB Dcb,
IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix,
OUT PNP_FCB *FoundFcb);
VOID
NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,
IN BOOLEAN SecondList,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN LARGE_INTEGER WaitTime,
IN PIRP Irp,
IN PUNICODE_STRING AliasName);
NTSTATUS
NTAPI
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN PUNICODE_STRING PipeName,
IN NTSTATUS Status,
IN PLIST_ENTRY ListEntry);
IO_STATUS_BLOCK
NTAPI
NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Peek,
IN BOOLEAN ReadOverflowOperation,
IN PVOID Buffer,
IN ULONG BufferSize,
IN ULONG Mode,
IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
IN ULONG Mode,
IN PVOID OutBuffer,
IN ULONG OutBufferSize,
IN ULONG PipeType,
OUT PULONG BytesWritten,
IN PNP_CCB Ccb,
IN ULONG NamedPipeEnd,
IN PETHREAD Thread,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQuerySecurityInfo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* EOF */

View file

@ -1,29 +0,0 @@
list(APPEND SOURCE
cleanup.c
close.c
create.c
datasup.c
fileinfo.c
fileobsup.c
flushbuf.c
fsctrl.c
main.c
prefxsup.c
read.c
readsup.c
secursup.c
seinfo.c
statesup.c
strucsup.c
volinfo.c
waitsup.c
write.c
writesup.c)
add_library(npfs SHARED ${SOURCE})
set_module_type(npfs kernelmodedriver)
target_link_libraries(npfs ${PSEH_LIB})
add_importlibs(npfs ntoskrnl hal)
add_pch(npfs npfs.h)
add_cd_file(TARGET npfs DESTINATION reactos/system32/drivers FOR all)

View file

@ -1,746 +0,0 @@
/*
* PROJECT: ReactOS Named Pipe FileSystem
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/filesystems/npfs/create.c
* PURPOSE: Pipes Creation
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include "npfs.h"
// File ID number for NPFS bugchecking support
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE)
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,
IN BOOLEAN SecondList,
IN PLIST_ENTRY List)
{
PLIST_ENTRY NextEntry, ListHead;
PIRP Irp;
ULONG i;
PAGED_CODE();
ListHead = &Dcb->NotifyList;
for (i = 0; i < 2; i++)
{
ASSERT(IsListEmpty(ListHead));
while (!IsListEmpty(ListHead))
{
NextEntry = RemoveHeadList(ListHead);
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
if (IoSetCancelRoutine(Irp, NULL))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, NextEntry);
}
else
{
InitializeListHead(NextEntry);
}
}
if (!SecondList) break;
ListHead = &Dcb->NotifyList2;
}
}
IO_STATUS_BLOCK
NTAPI
NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess)
{
IO_STATUS_BLOCK Status;
PAGED_CODE();
NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
++NpVcb->ReferenceCount;
Status.Information = FILE_OPENED;
Status.Status = STATUS_SUCCESS;
return Status;
}
IO_STATUS_BLOCK
NTAPI
NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PLIST_ENTRY List)
{
IO_STATUS_BLOCK IoStatus;
PNP_ROOT_DCB_FCB Ccb;
PAGED_CODE();
IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
if (NT_SUCCESS(IoStatus.Status))
{
NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
++Dcb->CurrentInstances;
IoStatus.Information = FILE_OPENED;
IoStatus.Status = STATUS_SUCCESS;
}
else
{
IoStatus.Information = 0;
}
return IoStatus;
}
IO_STATUS_BLOCK
NTAPI
NpCreateClientEnd(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PACCESS_STATE AccessState,
IN KPROCESSOR_MODE PreviousMode,
IN PETHREAD Thread,
IN PLIST_ENTRY List)
{
PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
BOOLEAN AccessGranted;
ACCESS_MASK GrantedAccess;
PPRIVILEGE_SET Privileges;
UNICODE_STRING ObjectTypeName;
IO_STATUS_BLOCK IoStatus;
USHORT NamedPipeConfiguration;
PLIST_ENTRY NextEntry, ListHead;
PNP_CCB Ccb = NULL;
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 0;
Privileges = NULL;
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(SubjectSecurityContext);
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
SubjectSecurityContext,
TRUE,
DesiredAccess & ~4,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
PreviousMode,
&GrantedAccess,
&IoStatus.Status);
if (Privileges)
{
SeAppendPrivileges(AccessState, Privileges);
SeFreePrivileges(Privileges);
}
if (AccessGranted)
{
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
}
ObjectTypeName.Buffer = L"NamedPipe";
ObjectTypeName.Length = 18;
SeOpenObjectAuditAlarm(&ObjectTypeName,
NULL,
&FileObject->FileName,
Fcb->SecurityDescriptor,
AccessState,
FALSE,
AccessGranted,
PreviousMode,
&AccessState->GenerateOnClose);
SeUnlockSubjectContext(SubjectSecurityContext);
if (!AccessGranted) return IoStatus;
if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL;
ListHead = &Fcb->CcbList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
NextEntry = NextEntry->Flink;
}
if (NextEntry == ListHead)
{
IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
return IoStatus;
}
IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
if (!NT_SUCCESS(IoStatus.Status))
{
NpUninitializeSecurity(Ccb);
return IoStatus;
}
Ccb->ClientSession = NULL;
Ccb->Process = IoThreadToProcess(Thread);
IoStatus.Information = FILE_OPENED;
IoStatus.Status = STATUS_SUCCESS;
return IoStatus;
}
NTSTATUS
NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
UNICODE_STRING FileName;
PFILE_OBJECT FileObject;
PFILE_OBJECT RelatedFileObject;
NODE_TYPE_CODE Type;
PNP_CCB Ccb;
PNP_FCB Fcb;
PNP_DCB Dcb;
ACCESS_MASK DesiredAccess;
LIST_ENTRY DeferredList;
UNICODE_STRING Prefix;
InitializeListHead(&DeferredList);
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
RelatedFileObject = FileObject->RelatedFileObject;
FileName = FileObject->FileName;
DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
FsRtlEnterFileSystem();
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
if (RelatedFileObject)
{
Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
}
else
{
Type = 0;
Fcb = NULL;
Ccb = NULL;
}
if (FileName.Length)
{
if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
!(RelatedFileObject))
{
Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
FileObject,
DesiredAccess,
&DeferredList);
goto Quickie;
}
}
else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
{
Irp->IoStatus = NpOpenNamedPipeFileSystem(FileObject,
DesiredAccess);
goto Quickie;
}
else if (Type == NPFS_NTC_ROOT_DCB)
{
Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
FileObject,
DesiredAccess,
&DeferredList);
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
{
if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
(FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
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,
&DeferredList);
Quickie:
ExReleaseResourceLite(&NpVcb->Lock);
NpCompleteDeferredIrps(&DeferredList);
FsRtlExitFileSystem();
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
IO_STATUS_BLOCK
NTAPI
NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PACCESS_STATE AccessState,
IN KPROCESSOR_MODE PreviousMode,
IN ULONG Disposition,
IN ULONG ShareAccess,
IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
IN PEPROCESS Process,
OUT PLIST_ENTRY List)
{
PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
IO_STATUS_BLOCK IoStatus;
UNICODE_STRING ObjectTypeName;
ACCESS_MASK GrantedAccess;
PNP_CCB Ccb;
PPRIVILEGE_SET Privileges;
USHORT NamedPipeConfiguration, CheckShareAccess;
BOOLEAN AccessGranted;
PAGED_CODE();
Privileges = NULL;
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(SubjectSecurityContext);
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
SubjectSecurityContext,
TRUE,
DesiredAccess | 4,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
PreviousMode,
&GrantedAccess,
&IoStatus.Status);
if (Privileges)
{
SeAppendPrivileges(AccessState, Privileges);
SeFreePrivileges(Privileges);
}
if (AccessGranted)
{
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000);
}
ObjectTypeName.Buffer = L"NamedPipe";
ObjectTypeName.Length = 18;
SeOpenObjectAuditAlarm(&ObjectTypeName,
NULL,
&FileObject->FileName,
Fcb->SecurityDescriptor,
AccessState,
FALSE,
AccessGranted,
PreviousMode,
&AccessState->GenerateOnClose);
SeUnlockSubjectContext(SubjectSecurityContext);
if (!AccessGranted) return IoStatus;
if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
{
IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
return IoStatus;
}
if (Disposition == FILE_CREATE)
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
CheckShareAccess = 0;
if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
{
CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
{
CheckShareAccess = FILE_SHARE_READ;
}
else if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
{
CheckShareAccess = FILE_SHARE_WRITE;
}
if (CheckShareAccess != ShareAccess)
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
IoStatus.Status = NpCreateCcb(Fcb,
FileObject,
FILE_PIPE_LISTENING_STATE,
Parameters->ReadMode & 0xFF,
Parameters->CompletionMode & 0xFF,
Parameters->InboundQuota,
Parameters->OutboundQuota,
&Ccb);
if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue,
&Fcb->FullName,
FALSE,
List);
if (!NT_SUCCESS(IoStatus.Status))
{
--Ccb->Fcb->CurrentInstances;
NpDeleteCcb(Ccb, List);
return IoStatus;
}
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
NpCheckForNotify(Fcb->ParentDcb, 0, List);
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 1;
return IoStatus;
}
NTSTATUS
NTAPI
NpCreateNewNamedPipe(IN PNP_DCB Dcb,
IN PFILE_OBJECT FileObject,
IN UNICODE_STRING PipeName,
IN ACCESS_MASK DesiredAccess,
IN PACCESS_STATE AccessState,
IN USHORT Disposition,
IN USHORT ShareAccess,
IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
IN PEPROCESS Process,
IN PLIST_ENTRY List,
IN PIO_STATUS_BLOCK IoStatus)
{
NTSTATUS Status;
USHORT NamedPipeConfiguration;
PSECURITY_SUBJECT_CONTEXT SecurityContext;
PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor;
PNP_CCB Ccb;
PNP_FCB Fcb;
PAGED_CODE();
if (!(Parameters->TimeoutSpecified) ||
!(Parameters->MaximumInstances) ||
(Parameters->DefaultTimeout.HighPart >= 0))
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
if (Disposition == FILE_OPEN)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Quickie;
}
if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE))
{
NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
}
else if (ShareAccess == FILE_SHARE_READ)
{
NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
}
else if (ShareAccess == FILE_SHARE_WRITE)
{
NamedPipeConfiguration = FILE_PIPE_INBOUND;
}
else
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
if (!Parameters->NamedPipeType && Parameters->ReadMode == 1)
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
Status = NpCreateFcb(Dcb,
&PipeName,
Parameters->MaximumInstances,
Parameters->DefaultTimeout,
NamedPipeConfiguration,
Parameters->NamedPipeType & 0xFFFF,
&Fcb);
if (!NT_SUCCESS(Status)) goto Quickie;
Status = NpCreateCcb(Fcb,
FileObject,
FILE_PIPE_LISTENING_STATE,
Parameters->ReadMode & 0xFF,
Parameters->CompletionMode & 0xFF,
Parameters->InboundQuota,
Parameters->OutboundQuota,
&Ccb);
if (!NT_SUCCESS(Status))
{
NpDeleteFcb(Fcb, List);
goto Quickie;
}
SecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
Status = SeAssignSecurity(0,
AccessState->SecurityDescriptor,
&SecurityDescriptor,
0,
SecurityContext,
IoGetFileObjectGenericMapping(),
PagedPool);
SeUnlockSubjectContext(SecurityContext);
if (!NT_SUCCESS(Status))
{
NpDeleteCcb(Ccb, List);
NpDeleteFcb(Fcb, List);
goto Quickie;
}
Status = ObLogSecurityDescriptor(SecurityDescriptor,
&CachedSecurityDescriptor,
1);
ExFreePool(SecurityDescriptor);
if (!NT_SUCCESS(Status))
{
NpDeleteCcb(Ccb, List);
NpDeleteFcb(Fcb, List);
goto Quickie;
}
Fcb->SecurityDescriptor = CachedSecurityDescriptor;
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
NpCheckForNotify(Dcb, TRUE, List);
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = FILE_CREATED;
return STATUS_SUCCESS;
Quickie:
IoStatus->Information = 0;
IoStatus->Status = Status;
return Status;
}
NTSTATUS
NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PFILE_OBJECT RelatedFileObject;
USHORT Disposition, ShareAccess;
PEPROCESS Process;
LIST_ENTRY DeferredList;
UNICODE_STRING FileName;
PNP_FCB Fcb;
UNICODE_STRING Prefix;
PNAMED_PIPE_CREATE_PARAMETERS Parameters;
IO_STATUS_BLOCK IoStatus;
InitializeListHead(&DeferredList);
Process = IoGetRequestorProcess(Irp);
IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
RelatedFileObject = FileObject->RelatedFileObject;
Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
Parameters = IoStack->Parameters.CreatePipe.Parameters;
FileName.Buffer = FileObject->FileName.Buffer;
FileName.Length = FileObject->FileName.Length;
FileName.MaximumLength = FileObject->FileName.MaximumLength;
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 0;
FsRtlEnterFileSystem();
NpAcquireExclusiveVcb();
if (RelatedFileObject)
{
Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
if (!(Fcb) ||
(Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
(FileName.Length < sizeof(WCHAR)) ||
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
&FileName,
TRUE,
&Prefix,
&Fcb);
if (!NT_SUCCESS(IoStatus.Status))
{
goto Quickie;
}
}
else
{
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, TRUE, &Prefix);
}
if (Prefix.Length)
{
if (Fcb->NodeType == NPFS_NTC_ROOT_DCB)
{
IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
FileObject,
FileName,
IoStack->Parameters.CreatePipe.
SecurityContext->DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
Disposition,
ShareAccess,
Parameters,
Process,
&DeferredList,
&IoStatus);
goto Quickie;
}
else
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
}
if (Fcb->NodeType != NPFS_NTC_FCB)
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
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,
&DeferredList);
Quickie:
NpReleaseVcb();
NpCompleteDeferredIrps(&DeferredList);
FsRtlExitFileSystem();
Irp->IoStatus = IoStatus;
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
return IoStatus.Status;
}
/* EOF */

View file

@ -1,741 +0,0 @@
/*
* PROJECT: ReactOS Named Pipe FileSystem
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/filesystems/npfs/fsctrl.c
* PURPOSE: Named Pipe FileSystem I/O Controls
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include "npfs.h"
// File ID number for NPFS bugchecking support
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FSCTRL)
/* GLOBALS ********************************************************************/
IO_STATUS_BLOCK NpUserIoStatusBlock;
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpInternalRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN BOOLEAN Overflow,
IN PLIST_ENTRY List)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpAssignEvent(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpQueryEvent(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpImpersonate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG NamedPipeEnd;
PNP_CCB Ccb;
NTSTATUS Status;
NODE_TYPE_CODE NodeTypeCode;
PIO_STACK_LOCATION IoStack;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
if (NodeTypeCode == NPFS_NTC_CCB)
{
if (NamedPipeEnd == FILE_PIPE_SERVER_END)
{
Status = NpImpersonateClientContext(Ccb);
}
else
{
Status = STATUS_ILLEGAL_FUNCTION;
}
}
return Status;
}
NTSTATUS
NTAPI
NpDisconnect(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
ULONG NamedPipeEnd;
PNP_CCB Ccb;
NTSTATUS Status;
NODE_TYPE_CODE NodeTypeCode;
PIO_STACK_LOCATION IoStack;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
if (NodeTypeCode == NPFS_NTC_CCB)
{
if (NamedPipeEnd == FILE_PIPE_SERVER_END)
{
ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
Status = NpSetDisconnectedPipeState(Ccb, List);
NpUninitializeSecurity(Ccb);
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
}
else
{
Status = STATUS_ILLEGAL_FUNCTION;
}
}
else
{
Status = STATUS_PIPE_DISCONNECTED;
}
return Status;
}
NTSTATUS
NTAPI
NpListen(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
ULONG NamedPipeEnd;
PNP_CCB Ccb;
NTSTATUS Status;
NODE_TYPE_CODE NodeTypeCode;
PIO_STACK_LOCATION IoStack;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
if (NodeTypeCode == NPFS_NTC_CCB)
{
if (NamedPipeEnd == FILE_PIPE_SERVER_END)
{
ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
Status = NpSetListeningPipeState(Ccb, Irp, List);
NpUninitializeSecurity(Ccb);
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
}
else
{
Status = STATUS_ILLEGAL_FUNCTION;
}
}
else
{
Status = STATUS_ILLEGAL_FUNCTION;
}
return Status;
}
NTSTATUS
NTAPI
NpPeek(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
PIO_STACK_LOCATION IoStack;
NODE_TYPE_CODE Type;
ULONG OutputLength;
ULONG NamedPipeEnd;
PNP_CCB Ccb;
PFILE_PIPE_PEEK_BUFFER PeekBuffer;
PNP_DATA_QUEUE DataQueue;
ULONG_PTR BytesPeeked;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PNP_DATA_QUEUE_ENTRY DataEntry;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
if (!Type)
{
return STATUS_PIPE_DISCONNECTED;
}
if ((Type != NPFS_NTC_CCB) &&
(OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)))
{
return STATUS_INVALID_PARAMETER;
}
PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
{
if (NamedPipeEnd != FILE_PIPE_SERVER_END)
{
NpBugCheck(NamedPipeEnd, 0, 0);
}
DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
}
else
{
DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
}
if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
{
if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE)
{
return STATUS_INVALID_PIPE_STATE;
}
if (DataQueue->QueueState != WriteEntries)
{
return STATUS_PIPE_BROKEN;
}
}
PeekBuffer->NamedPipeState = 0;
PeekBuffer->ReadDataAvailable = 0;
PeekBuffer->NumberOfMessages = 0;
PeekBuffer->MessageLength = 0;
PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data);
if (DataQueue->QueueState == WriteEntries)
{
DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
NP_DATA_QUEUE_ENTRY,
QueueEntry);
ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));
PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
{
PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
}
if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))
{
Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
}
else
{
IoStatus = NpReadDataQueue(DataQueue,
TRUE,
FALSE,
PeekBuffer->Data,
OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data),
Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
Ccb,
List);
Status = IoStatus.Status;
BytesPeeked += IoStatus.Information;
}
}
else
{
Status = STATUS_SUCCESS;
}
Irp->IoStatus.Information = BytesPeeked;
return Status;
}
NTSTATUS
NTAPI
NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PAGED_CODE();
if (Irp->AssociatedIrp.SystemBuffer)
{
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
NpTransceive(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PLIST_ENTRY List)
{
PIO_STACK_LOCATION IoStack;
PVOID InBuffer, OutBuffer;
ULONG InLength, OutLength, BytesWritten;
NODE_TYPE_CODE NodeTypeCode;
PNP_CCB Ccb;
ULONG NamedPipeEnd;
PNP_NONPAGED_CCB NonPagedCcb;
PNP_DATA_QUEUE ReadQueue, WriteQueue;
PNP_EVENT_BUFFER EventBuffer;
NTSTATUS Status;
PIRP NewIrp;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer;
OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
OutBuffer = Irp->UserBuffer;
if (Irp->RequestorMode == UserMode)
{
_SEH2_TRY
{
ProbeForRead(InBuffer, InLength, sizeof(CHAR));
ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
if (NodeTypeCode != NPFS_NTC_CCB)
{
return STATUS_PIPE_DISCONNECTED;
}
NonPagedCcb = Ccb->NonPagedCcb;
ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
{
Status = STATUS_INVALID_PIPE_STATE;
goto Quickie;
}
if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
{
if (NamedPipeEnd != FILE_PIPE_SERVER_END)
{
NpBugCheck(NamedPipeEnd, 0, 0);
}
ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
}
else
{
ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
}
EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX ||
Ccb->ReadMode[NamedPipeEnd] != FILE_PIPE_MESSAGE_MODE)
{
Status = STATUS_INVALID_PIPE_STATE;
goto Quickie;
}
if (ReadQueue->QueueState != Empty)
{
Status = STATUS_PIPE_BUSY;
goto Quickie;
}
Status = NpWriteDataQueue(WriteQueue,
1,
InBuffer,
InLength,
Ccb->Fcb->NamedPipeType,
&BytesWritten,
Ccb,
NamedPipeEnd,
Irp->Tail.Overlay.Thread,
List);
if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
ASSERT(WriteQueue->QueueState != ReadEntries);
NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
if (!NewIrp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE);
if (BytesWritten)
{
NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
BytesWritten,
NPFS_WRITE_BLOCK_TAG);
if (!NewIrp->AssociatedIrp.SystemBuffer)
{
IoFreeIrp(NewIrp);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
_SEH2_TRY
{
RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer,
(PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten),
BytesWritten);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(goto Quickie);
}
_SEH2_END;
}
else
{
NewIrp->AssociatedIrp.SystemBuffer = NULL;
}
IoStack = IoGetNextIrpStackLocation(NewIrp);
IoSetNextIrpStackLocation(NewIrp);
NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
NewIrp->IoStatus.Information = BytesWritten;
IoStack->Parameters.Read.Length = BytesWritten;
IoStack->MajorFunction = IRP_MJ_WRITE;
if (BytesWritten > 0) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
NewIrp->UserIosb = &NpUserIoStatusBlock;
Status = NpAddDataQueueEntry(NamedPipeEnd,
Ccb,
WriteQueue,
WriteEntries,
Unbuffered,
BytesWritten,
NewIrp,
NULL,
0);
if (Status != STATUS_PENDING)
{
NewIrp->IoStatus.Status = Status;
InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry);
}
}
if (!NT_SUCCESS(Status)) goto Quickie;
if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
ASSERT(ReadQueue->QueueState == Empty);
Status = NpAddDataQueueEntry(NamedPipeEnd,
Ccb,
ReadQueue,
ReadEntries,
Buffered,
OutLength,
Irp,
NULL,
0);
if (NT_SUCCESS(Status))
{
if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
}
Quickie:
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
return Status;
}
NTSTATUS
NTAPI
NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
ULONG InLength, NameLength;
UNICODE_STRING SourceString, Prefix;
ULONG NamedPipeEnd;
PNP_CCB Ccb;
PFILE_PIPE_WAIT_FOR_BUFFER Buffer;
NTSTATUS Status;
NODE_TYPE_CODE NodeTypeCode;
PLIST_ENTRY NextEntry;
PNP_FCB Fcb;
PWCHAR OriginalBuffer;
PAGED_CODE();
IoStack = IoGetCurrentIrpStackLocation(Irp);
InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
SourceString.Buffer = NULL;
if (NpDecodeFileObject(IoStack->FileObject,
NULL,
&Ccb,
&NamedPipeEnd) != NPFS_NTC_ROOT_DCB)
{
Status = STATUS_ILLEGAL_FUNCTION;
goto Quickie;
}
Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
if (InLength < sizeof(*Buffer))
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
NameLength = Buffer->NameLength;
if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) ||
((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength))
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
SourceString.Buffer = ExAllocatePoolWithTag(PagedPool,
SourceString.Length,
NPFS_WRITE_BLOCK_TAG);
if (!SourceString.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
Status = STATUS_SUCCESS;
OriginalBuffer = SourceString.Buffer;
//Status = NpTranslateAlias(&SourceString);
if (!NT_SUCCESS(Status)) goto Quickie;
Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix);
Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1);
NodeTypeCode = Fcb ? Fcb->NodeType : 0;
if (NodeTypeCode != NPFS_NTC_FCB)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Quickie;
}
for (NextEntry = Fcb->CcbList.Flink;
NextEntry != &Fcb->CcbList;
NextEntry = NextEntry->Flink)
{
Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
}
if (NextEntry != &Fcb->CcbList)
{
Status = STATUS_SUCCESS;
}
else
{
Status = NpAddWaiter(&NpVcb->WaitQueue,
Fcb->Timeout,
Irp,
OriginalBuffer == SourceString.Buffer ?
NULL : &SourceString);
}
Quickie:
if (SourceString.Buffer) ExFreePool(SourceString.Buffer);
return Status;
}
NTSTATUS
NTAPI
NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG Fsctl;
BOOLEAN Overflow = FALSE;
LIST_ENTRY DeferredList;
NTSTATUS Status;
PAGED_CODE();
InitializeListHead(&DeferredList);
Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode;
switch (Fsctl)
{
case FSCTL_PIPE_PEEK:
NpAcquireExclusiveVcb();
Status = NpPeek(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_INTERNAL_WRITE:
NpAcquireSharedVcb();
Status = NpInternalWrite(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_TRANSCEIVE:
NpAcquireSharedVcb();
Status = NpTransceive(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
NpAcquireSharedVcb();
Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
Overflow = TRUE;
// on purpose
case FSCTL_PIPE_INTERNAL_READ:
NpAcquireSharedVcb();
Status = NpInternalRead(DeviceObject, Irp, Overflow, &DeferredList);
break;
case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
NpAcquireSharedVcb();
Status = NpQueryClientProcess(DeviceObject, Irp);
break;
case FSCTL_PIPE_ASSIGN_EVENT:
NpAcquireExclusiveVcb();
Status = NpAssignEvent(DeviceObject, Irp);
break;
case FSCTL_PIPE_DISCONNECT:
NpAcquireExclusiveVcb();
Status = NpDisconnect(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_LISTEN:
NpAcquireSharedVcb();
Status = NpListen(DeviceObject, Irp, &DeferredList);
break;
case FSCTL_PIPE_QUERY_EVENT:
NpAcquireExclusiveVcb();
Status = NpQueryEvent(DeviceObject, Irp);
break;
case FSCTL_PIPE_WAIT:
NpAcquireExclusiveVcb();
Status = NpWaitForNamedPipe(DeviceObject, Irp);
break;
case FSCTL_PIPE_IMPERSONATE:
NpAcquireExclusiveVcb();
Status = NpImpersonate(DeviceObject, Irp);
break;
case FSCTL_PIPE_SET_CLIENT_PROCESS:
NpAcquireExclusiveVcb();
Status = NpSetClientProcess(DeviceObject, Irp);
break;
default:
return STATUS_NOT_SUPPORTED;
}
NpReleaseVcb();
NpCompleteDeferredIrps(&DeferredList);
return Status;
}
NTSTATUS
NTAPI
NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
PAGED_CODE();
FsRtlEnterFileSystem();
Status = NpCommonFileSystemControl(DeviceObject, Irp);
FsRtlExitFileSystem();
if (Status != STATUS_PENDING)
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
}
return Status;
}
/* EOF */

View file

@ -1,675 +0,0 @@
/*
* PROJECT: ReactOS Named Pipe FileSystem
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/filesystems/npfs/npfs.h
* PURPOSE: Named Pipe FileSystem Header
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
//
// System Headers
//
#include <ntifs.h>
#include <ntndk.h>
#include <pseh/pseh2.h>
#define UNIMPLEMENTED
#define DPRINT1 DbgPrint
//
// Allow Microsoft Extensions
//
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable:4214)
#pragma warning(disable:4100)
#endif
/* TYPEDEFS & DEFINES *********************************************************/
//
// Pool Tags for NPFS (from pooltag.txt)
//
// Npf* -npfs.sys - Npfs Allocations
// NpFc - npfs.sys - CCB, client control block
// NpFf - npfs.sys - FCB, file control block
// NpFC - npfs.sys - ROOT_DCB CCB
// NpFD - npfs.sys - DCB, directory block
// NpFg - npfs.sys - Global storage
// NpFi - npfs.sys - NPFS client info buffer.
// NpFn - npfs.sys - Name block
// NpFq - npfs.sys - Query template buffer used for directory query
// NpFr - npfs.sys - DATA_ENTRY records(read / write buffers)
// NpFs - npfs.sys - Client security context
// NpFw - npfs.sys - Write block
// NpFW - npfs.sys - Write block
#define NPFS_CCB_TAG 'NpFc'
#define NPFS_ROOT_DCB_CCB_TAG 'NpFC'
#define NPFS_DCB_TAG 'NpFD'
#define NPFS_FCB_TAG 'NpFf'
#define NPFS_GLOBAL_TAG 'NpFg'
#define NPFS_CLIENT_INFO_TAG 'NpFi'
#define NPFS_NAME_BLOCK_TAG 'NpFn'
#define NPFS_QUERY_TEMPLATE_TAG 'NpFq'
#define NPFS_DATA_ENTRY_TAG 'NpFr'
#define NPFS_CLIENT_SEC_CTX_TAG 'NpFs'
#define NPFS_WAIT_BLOCK_TAG 'NpFt'
#define NPFS_WRITE_BLOCK_TAG 'NpFw'
//
// NPFS bugchecking support
//
// We define the NpBugCheck macro which triggers a NPFS_FILE_SYSTEM bugcheck
// containing the source file ID number and the line where it was emitted, as
// described in the MSDN article "Bug Check 0x25: NPFS_FILE_SYSTEM".
//
// The bugcheck emits 4 ULONGs; the first one is made, in its high word, by
// the current source file ID and in its low word, by the line number; the
// three other ones are user-defined.
//
// In order to avoid redefinition of the same file ID in different source files,
// we gather all of them here, so that you will have to add (or remove) a new
// one as soon as you add (or remove) a source file from the NPFS driver code.
//
// To use the NpBugCheck macro in a source file, define at its beginning
// the constant NPFS_BUGCHECK_FILE_ID with one of the following file IDs,
// then use the bugcheck macro wherever you want.
//
#define NPFS_BUGCHECK_CLEANUP 0x0001
#define NPFS_BUGCHECK_CLOSE 0x0002
#define NPFS_BUGCHECK_CREATE 0x0003
#define NPFS_BUGCHECK_DATASUP 0x0004
#define NPFS_BUGCHECK_FILEINFO 0x0005
#define NPFS_BUGCHECK_FILEOBSUP 0x0006
#define NPFS_BUGCHECK_FLUSHBUF 0x0007
#define NPFS_BUGCHECK_FSCTRL 0x0008
#define NPFS_BUGCHECK_MAIN 0x0009
#define NPFS_BUGCHECK_PREFXSUP 0x000a
#define NPFS_BUGCHECK_READ 0x000b
#define NPFS_BUGCHECK_READSUP 0x000c
#define NPFS_BUGCHECK_SECURSUP 0x000d
#define NPFS_BUGCHECK_SEINFO 0x000e
#define NPFS_BUGCHECK_STATESUP 0x000f
#define NPFS_BUGCHECK_STRUCSUP 0x0010
#define NPFS_BUGCHECK_VOLINFO 0x0011
#define NPFS_BUGCHECK_WAITSUP 0x0012
#define NPFS_BUGCHECK_WRITE 0x0013
#define NPFS_BUGCHECK_WRITESUP 0x0014
#define NpBugCheck(p1, p2, p3) \
KeBugCheckEx(NPFS_FILE_SYSTEM, \
(NPFS_BUGCHECK_FILE_ID << 16) | __LINE__, \
(p1), (p2), (p3))
//
// Node Type Codes for NPFS
//
#define NPFS_NTC_VCB 1
#define NPFS_NTC_ROOT_DCB 2
#define NPFS_NTC_FCB 4
#define NPFS_NTC_CCB 6
#define NPFS_NTC_NONPAGED_CCB 7
#define NPFS_NTC_ROOT_DCB_CCB 8
typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
//
// Data Queue States
//
typedef enum _NP_DATA_QUEUE_STATE
{
ReadEntries = 0,
WriteEntries = 1,
Empty = 2
} NP_DATA_QUEUE_STATE;
//
// Data Queue Entry Types
//
typedef enum _NP_DATA_QUEUE_ENTRY_TYPE
{
Buffered = 0,
Unbuffered
} NP_DATA_QUEUE_ENTRY_TYPE;
//
// An Input or Output Data Queue. Each CCB has two of these.
//
typedef struct _NP_DATA_QUEUE
{
LIST_ENTRY Queue;
ULONG QueueState;
ULONG BytesInQueue;
ULONG EntriesInQueue;
ULONG QuotaUsed;
ULONG ByteOffset;
ULONG Quota;
} NP_DATA_QUEUE, *PNP_DATA_QUEUE;
//
// The Entries that go into the Queue
//
typedef struct _NP_DATA_QUEUE_ENTRY
{
LIST_ENTRY QueueEntry;
ULONG DataEntryType;
PIRP Irp;
ULONG QuotaInEntry;
PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
ULONG DataSize;
} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY;
//
// A Wait Queue. Only the VCB has one of these.
//
typedef struct _NP_WAIT_QUEUE
{
LIST_ENTRY WaitList;
KSPIN_LOCK WaitLock;
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
//
// The Entries in the Queue above, one for each Waiter.
//
typedef struct _NP_WAIT_QUEUE_ENTRY
{
PIRP Irp;
KDPC Dpc;
KTIMER Timer;
PNP_WAIT_QUEUE WaitQueue;
UNICODE_STRING AliasName;
PFILE_OBJECT FileObject;
} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
//
// The event buffer in the NonPaged CCB
//
typedef struct _NP_EVENT_BUFFER
{
PKEVENT Event;
} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER;
//
// The CCB for the Root DCB
//
typedef struct _NP_ROOT_DCB_CCB
{
NODE_TYPE_CODE NodeType;
PVOID Unknown;
ULONG Unknown2;
} NP_ROOT_DCB_CCB, *PNP_ROOT_DCB_FCB;
//
// The header that both FCB and DCB share
//
typedef struct _NP_CB_HEADER
{
NODE_TYPE_CODE NodeType;
LIST_ENTRY DcbEntry;
PVOID ParentDcb;
ULONG CurrentInstances;
ULONG ServerOpenCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} NP_CB_HEADER, *PNP_CB_HEADER;
//
// The footer that both FCB and DCB share
//
typedef struct _NP_CB_FOOTER
{
UNICODE_STRING FullName;
UNICODE_STRING ShortName;
UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry;
} NP_CB_FOOTER;
//
// A Directory Control Block (DCB)
//
typedef struct _NP_DCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// DCB-specific data
//
LIST_ENTRY NotifyList;
LIST_ENTRY NotifyList2;
LIST_ENTRY FcbList;
#ifndef _WIN64
ULONG Pad;
#endif
//
// Common Footer
//
NP_CB_FOOTER;
} NP_DCB, *PNP_DCB;
//
// A File Control BLock (FCB)
//
typedef struct _NP_FCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// FCB-specific fields
//
ULONG MaximumInstances;
USHORT NamedPipeConfiguration;
USHORT NamedPipeType;
LARGE_INTEGER Timeout;
LIST_ENTRY CcbList;
#ifdef _WIN64
PVOID Pad[2];
#endif
//
// Common Footer
//
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
//
typedef struct _NP_NONPAGED_CCB
{
NODE_TYPE_CODE NodeType;
PNP_EVENT_BUFFER EventBuffer[2];
ERESOURCE Lock;
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
//
// A Client Control Block (CCB)
//
typedef struct _NP_CCB
{
NODE_TYPE_CODE NodeType;
UCHAR NamedPipeState;
UCHAR ReadMode[2];
UCHAR CompletionMode[2];
SECURITY_QUALITY_OF_SERVICE ClientQos;
LIST_ENTRY CcbEntry;
PNP_FCB Fcb;
PFILE_OBJECT FileObject[2];
PEPROCESS Process;
PVOID ClientSession;
PNP_NONPAGED_CCB NonPagedCcb;
NP_DATA_QUEUE DataQueue[2];
PSECURITY_CLIENT_CONTEXT ClientContext;
LIST_ENTRY IrpList;
} NP_CCB, *PNP_CCB;
//
// A Volume Control Block (VCB)
//
typedef struct _NP_VCB
{
NODE_TYPE_CODE NodeType;
ULONG ReferenceCount;
PNP_DCB RootDcb;
UNICODE_PREFIX_TABLE PrefixTable;
ERESOURCE Lock;
RTL_GENERIC_TABLE EventTable;
NP_WAIT_QUEUE WaitQueue;
} NP_VCB, *PNP_VCB;
extern PNP_VCB NpVcb;
/* FUNCTIONS ******************************************************************/
//
// Functions to lock/unlock the global VCB lock
//
FORCEINLINE
VOID
NpAcquireSharedVcb(VOID)
{
/* Acquire the lock in shared mode */
ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
}
FORCEINLINE
VOID
NpAcquireExclusiveVcb(VOID)
{
/* Acquire the lock in exclusive mode */
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
}
FORCEINLINE
VOID
NpReleaseVcb(VOID)
{
/* Release the lock */
ExReleaseResourceLite(&NpVcb->Lock);
}
//
// Function to process deferred IRPs outside the VCB lock but still within the
// critical region
//
VOID
FORCEINLINE
NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
{
PLIST_ENTRY ThisEntry, NextEntry;
PIRP Irp;
/* Loop the list */
ThisEntry = DeferredList->Flink;
while (ThisEntry != DeferredList)
{
/* Remember the next entry, but don't switch to it yet */
NextEntry = ThisEntry->Flink;
/* Complete the IRP for this entry */
Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
/* And now switch to the next one */
ThisEntry = NextEntry;
}
}
BOOLEAN
NTAPI
NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer);
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
NTSTATUS
NTAPI
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
PLIST_ENTRY
NTAPI
NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
PIRP
NTAPI
NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Flag,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpAddDataQueueEntry(IN ULONG NamedPipeEnd,
IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE DataQueue,
IN ULONG Who,
IN ULONG Type,
IN ULONG DataSize,
IN PIRP Irp,
IN PVOID Buffer,
IN ULONG ByteOffset);
VOID
NTAPI
NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN ULONG Quota);
NTSTATUS
NTAPI
NpCreateCcb(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN UCHAR State,
IN UCHAR ReadMode,
IN UCHAR CompletionMode,
IN ULONG InQuota,
IN ULONG OutQuota,
OUT PNP_CCB *NewCcb);
NTSTATUS
NTAPI
NpCreateFcb(IN PNP_DCB Dcb,
IN PUNICODE_STRING PipeName,
IN ULONG MaximumInstances,
IN LARGE_INTEGER Timeout,
IN USHORT NamedPipeConfiguration,
IN USHORT NamedPipeType,
OUT PNP_FCB *NewFcb);
NTSTATUS
NTAPI
NpCreateRootDcb(VOID);
NTSTATUS
NTAPI
NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb);
VOID
NTAPI
NpInitializeVcb(VOID);
VOID
NTAPI
NpDeleteCcb(IN PNP_CCB Ccb,
IN PLIST_ENTRY ListEntry);
VOID
NTAPI
NpDeleteFcb(IN PNP_FCB Fcb,
IN PLIST_ENTRY ListEntry);
NTSTATUS
NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetListeningPipeState(IN PNP_CCB Ccb,
IN PIRP Irp,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpSetClosingPipeState(IN PNP_CCB Ccb,
IN PIRP Irp,
IN ULONG NamedPipeEnd,
IN PLIST_ENTRY List);
VOID
NTAPI
NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
NTSTATUS
NTAPI
NpImpersonateClientContext(IN PNP_CCB Ccb);
VOID
NTAPI
NpCopyClientContext(IN PNP_CCB Ccb,
IN PNP_DATA_QUEUE_ENTRY DataQueueEntry);
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb);
NTSTATUS
NTAPI
NpInitializeSecurity(IN PNP_CCB Ccb,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PETHREAD Thread);
NTSTATUS
NTAPI
NpGetClientSecurityContext(IN ULONG NamedPipeEnd,
IN PNP_CCB Ccb,
IN PETHREAD Thread,
IN PSECURITY_CLIENT_CONTEXT *Context);
VOID
NTAPI
NpSetFileObject(IN PFILE_OBJECT FileObject,
IN PVOID PrimaryContext,
IN PVOID Ccb,
IN ULONG NamedPipeEnd);
NODE_TYPE_CODE
NTAPI
NpDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVOID *PrimaryContext OPTIONAL,
OUT PNP_CCB *Ccb,
OUT PULONG NamedPipeEnd OPTIONAL);
PNP_FCB
NTAPI
NpFindPrefix(IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix);
NTSTATUS
NTAPI
NpFindRelativePrefix(IN PNP_DCB Dcb,
IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix,
OUT PNP_FCB *FoundFcb);
VOID
NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,
IN BOOLEAN SecondList,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN LARGE_INTEGER WaitTime,
IN PIRP Irp,
IN PUNICODE_STRING AliasName);
NTSTATUS
NTAPI
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN PUNICODE_STRING PipeName,
IN NTSTATUS Status,
IN PLIST_ENTRY ListEntry);
IO_STATUS_BLOCK
NTAPI
NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN BOOLEAN Peek,
IN BOOLEAN ReadOverflowOperation,
IN PVOID Buffer,
IN ULONG BufferSize,
IN ULONG Mode,
IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
IN ULONG Mode,
IN PVOID OutBuffer,
IN ULONG OutBufferSize,
IN ULONG PipeType,
OUT PULONG BytesWritten,
IN PNP_CCB Ccb,
IN ULONG NamedPipeEnd,
IN PETHREAD Thread,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQuerySecurityInfo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* EOF */