diff --git a/reactos/ntoskrnl/lpc/close.c b/reactos/ntoskrnl/lpc/close.c new file mode 100644 index 00000000000..99c81791fde --- /dev/null +++ b/reactos/ntoskrnl/lpc/close.c @@ -0,0 +1,112 @@ +/* $Id: close.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/close.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +VOID +NiClosePort ( + PVOID ObjectBody, + ULONG HandleCount + ) +{ + PEPORT Port = (PEPORT) ObjectBody; + LPC_MESSAGE Message; + +// DPRINT1("NiClosePort(ObjectBody %x, HandleCount %d) RefCount %d\n", +// ObjectBody, HandleCount, ObGetReferenceCount(Port)); + + if ( (HandleCount == 0) + && (Port->State == EPORT_CONNECTED_CLIENT) + && (ObGetReferenceCount(Port) == 2) + ) + { +// DPRINT1("All handles closed to client port\n"); + + Message.MessageSize = sizeof(LPC_MESSAGE); + Message.DataSize = 0; + + EiReplyOrRequestPort ( + Port->OtherPort, + & Message, + LPC_PORT_CLOSED, + Port + ); + KeSetEvent ( + & Port->OtherPort->Event, + IO_NO_INCREMENT, + FALSE + ); + + Port->OtherPort->OtherPort = NULL; + Port->OtherPort->State = EPORT_DISCONNECTED; + ObDereferenceObject (Port); + } + if ( (HandleCount == 0) + && (Port->State == EPORT_CONNECTED_SERVER) + && (ObGetReferenceCount(Port) == 2) + ) + { +// DPRINT("All handles closed to server\n"); + + Port->OtherPort->OtherPort = NULL; + Port->OtherPort->State = EPORT_DISCONNECTED; + ObDereferenceObject(Port->OtherPort); + } +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +VOID +NiDeletePort ( + PVOID ObjectBody + ) +{ +// PEPORT Port = (PEPORT)ObjectBody; + +// DPRINT1("Deleting port %x\n", Port); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/complete.c b/reactos/ntoskrnl/lpc/complete.c new file mode 100644 index 00000000000..43ac0430bb6 --- /dev/null +++ b/reactos/ntoskrnl/lpc/complete.c @@ -0,0 +1,68 @@ +/* $Id: complete.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/complete.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/*********************************************************************** + * NAME EXPORTED + * NtCompleteConnectPort@4 + * + * + */ +EXPORTED +NTSTATUS +STDCALL +NtCompleteConnectPort (HANDLE PortHandle) +{ + NTSTATUS Status; + PEPORT OurPort; + + DPRINT("NtCompleteConnectPort(PortHandle %x)\n", PortHandle); + + Status = ObReferenceObjectByHandle ( + PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID *) & OurPort, + NULL + ); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + + KeSetEvent ( + & OurPort->OtherPort->Event, + IO_NO_INCREMENT, + FALSE + ); + + OurPort->State = EPORT_CONNECTED_SERVER; + + ObDereferenceObject (OurPort); + + return (STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/connect.c b/reactos/ntoskrnl/lpc/connect.c new file mode 100644 index 00000000000..fe525e3492c --- /dev/null +++ b/reactos/ntoskrnl/lpc/connect.c @@ -0,0 +1,303 @@ +/* $Id: connect.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/connect.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME EXPORTED + * NtConnectPort@32 + * + * DESCRIPTION + * Connect to a named port and wait for the other side to + * accept the connection. + * + * ARGUMENTS + * ConnectedPort + * PortName + * Qos + * WriteMap + * ReadMap + * MaxMessageSize + * ConnectInfo + * UserConnectInfoLength + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +NtConnectPort ( + PHANDLE ConnectedPort, + PUNICODE_STRING PortName, + PSECURITY_QUALITY_OF_SERVICE Qos, + PLPC_SECTION_WRITE WriteMap, + PLPC_SECTION_READ ReadMap, + PULONG MaxMessageSize, + PVOID ConnectInfo, + PULONG UserConnectInfoLength + ) +{ + NTSTATUS Status; + PEPORT NamedPort; + PEPORT OurPort; + HANDLE OurPortHandle; + PLPC_MESSAGE Request; + PQUEUEDMESSAGE Reply; + ULONG ConnectInfoLength; + KIRQL oldIrql; + + DPRINT("PortName %x\n", PortName); + DPRINT("NtConnectPort(PortName %S)\n", PortName->Buffer); + + /* + * Copy in user parameters + */ + memcpy ( + & ConnectInfoLength, + UserConnectInfoLength, + sizeof (*UserConnectInfoLength) + ); + /* + * Get access to the port + */ + Status = ObReferenceObjectByName ( + PortName, + 0, + NULL, + PORT_ALL_ACCESS, /* DesiredAccess */ + ExPortType, + UserMode, + NULL, + (PVOID *) & NamedPort + ); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to reference named port (status %x)\n", Status); + return (Status); + } + /* + * Create a port to represent our side of the connection + */ + OurPort = ObCreateObject ( + & OurPortHandle, + PORT_ALL_ACCESS, + NULL, + ExPortType + ); + NiInitializePort(OurPort); + /* + * Create a request message + */ + DPRINT("Creating request message\n"); + + Request = ExAllocatePool ( + NonPagedPool, + (sizeof (LPC_MESSAGE) + ConnectInfoLength) + ); + + Request->DataSize = ConnectInfoLength; + Request->MessageSize = sizeof(LPC_MESSAGE) + ConnectInfoLength; + Request->SharedSectionSize = 0; + if ( (ConnectInfo != NULL) + && (ConnectInfoLength > 0) + ) + { + memcpy ( + (PVOID) (Request + 1), + ConnectInfo, + ConnectInfoLength + ); + } + /* + * Queue the message to the named port + */ + DPRINT("Queuing message\n"); + + EiReplyOrRequestPort ( + NamedPort, + Request, + LPC_CONNECTION_REQUEST, + OurPort + ); + KeSetEvent ( + & NamedPort->Event, + IO_NO_INCREMENT, + FALSE + ); + + DPRINT("Waiting for connection completion\n"); + + /* + * Wait for them to accept our connection + */ + KeWaitForSingleObject ( + & OurPort->Event, + UserRequest, + UserMode, + FALSE, + NULL + ); + + DPRINT("Received connection completion\n"); + KeAcquireSpinLock ( + & OurPort->Lock, + & oldIrql + ); + Reply = EiDequeueMessagePort (OurPort); + KeReleaseSpinLock ( + & OurPort->Lock, + oldIrql + ); + memcpy ( + ConnectInfo, + Reply->MessageData, + Reply->Message.DataSize + ); + *UserConnectInfoLength = Reply->Message.DataSize; + + if (Reply->Message.MessageType == LPC_CONNECTION_REFUSED) + { + ObDereferenceObject (NamedPort); + ObDereferenceObject (OurPort); + ZwClose (OurPortHandle); + ExFreePool (Request); + ExFreePool (Reply); + return (STATUS_UNSUCCESSFUL); + } + + OurPort->State = EPORT_CONNECTED_CLIENT; + *ConnectedPort = OurPortHandle; + ExFreePool (Reply); + ExFreePool (Request); + + DPRINT("Exited successfully\n"); + + return (STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtAcceptConnectPort@24 + * + * DESCRIPTION + * + * ARGUMENTS + * ServerPortHandle + * NamedPortHandle + * LpcMessage + * AcceptIt + * WriteMap + * ReadMap + * + * RETURN VALUE + * + */ +EXPORTED +NTSTATUS +STDCALL +NtAcceptConnectPort ( + PHANDLE ServerPortHandle, + HANDLE NamedPortHandle, + PLPC_MESSAGE LpcMessage, + BOOLEAN AcceptIt, + PLPC_SECTION_WRITE WriteMap, + PLPC_SECTION_READ ReadMap + ) +{ + NTSTATUS Status; + PEPORT NamedPort; + PEPORT OurPort = NULL; + PQUEUEDMESSAGE ConnectionRequest; + KIRQL oldIrql; + + Status = ObReferenceObjectByHandle ( + NamedPortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID *) & NamedPort, + NULL + ); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + /* + * Create a port object for our side of the connection + */ + if (AcceptIt == 1) + { + OurPort = ObCreateObject ( + ServerPortHandle, + PORT_ALL_ACCESS, + NULL, + ExPortType + ); + NiInitializePort(OurPort); + } + /* + * Dequeue the connection request + */ + KeAcquireSpinLock (& NamedPort->Lock, & oldIrql); + ConnectionRequest = EiDequeueConnectMessagePort (NamedPort); + KeReleaseSpinLock (& NamedPort->Lock, oldIrql); + + if (AcceptIt != 1) + { + EiReplyOrRequestPort ( + ConnectionRequest->Sender, + LpcMessage, + LPC_CONNECTION_REFUSED, + NamedPort + ); + KeSetEvent ( + & ConnectionRequest->Sender->Event, + IO_NO_INCREMENT, + FALSE + ); + ObDereferenceObject (ConnectionRequest->Sender); + ExFreePool (ConnectionRequest); + ObDereferenceObject (NamedPort); + return (STATUS_SUCCESS); + } + /* + * Connect the two ports + */ + OurPort->OtherPort = ConnectionRequest->Sender; + OurPort->OtherPort->OtherPort = OurPort; + EiReplyOrRequestPort ( + ConnectionRequest->Sender, + LpcMessage, + LPC_REPLY, + OurPort + ); + ExFreePool (ConnectionRequest); + + ObDereferenceObject (OurPort); + ObDereferenceObject (NamedPort); + + return (STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/create.c b/reactos/ntoskrnl/lpc/create.c new file mode 100644 index 00000000000..230b1893d3e --- /dev/null +++ b/reactos/ntoskrnl/lpc/create.c @@ -0,0 +1,104 @@ +/* $Id: create.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/create.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +NTSTATUS +NiCreatePort ( + PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + NTSTATUS Status; + + if (RemainingPath == NULL) + { + return (STATUS_SUCCESS); + } + + if (wcschr(RemainingPath+1, '\\') != NULL) + { + return (STATUS_UNSUCCESSFUL); + } + + Status = ObReferenceObjectByPointer ( + Parent, + STANDARD_RIGHTS_REQUIRED, + ObDirectoryType, + UserMode + ); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + + ObAddEntryDirectory ( + Parent, + ObjectBody, + (RemainingPath + 1) + ); + ObDereferenceObject (Parent); + + return (STATUS_SUCCESS); +} + + +EXPORTED +NTSTATUS +STDCALL +NtCreatePort ( + PHANDLE PortHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG MaxConnectInfoLength, + ULONG MaxDataLength, + ULONG Reserved + ) +{ + PEPORT Port; + NTSTATUS Status; + + DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer); + + Port = ObCreateObject ( + PortHandle, + PORT_ALL_ACCESS, + ObjectAttributes, + ExPortType + ); + if (Port == NULL) + { + return (STATUS_UNSUCCESSFUL); + } + + Status = NiInitializePort (Port); + Port->MaxConnectInfoLength = 260; + Port->MaxDataLength = 328; + + ObDereferenceObject (Port); + + return (Status); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/listen.c b/reactos/ntoskrnl/lpc/listen.c new file mode 100644 index 00000000000..da11ee223e6 --- /dev/null +++ b/reactos/ntoskrnl/lpc/listen.c @@ -0,0 +1,87 @@ +/* $Id: listen.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/listen.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME EXPORTED + * NtListenPort@8 + * + * DESCRIPTION + * Listen on a named port and wait for a connection attempt. + * + * ARGUMENTS + * PortHandle [IN] LPC port to listen on. + * + * ConnectMsg [IN] User provided storage for a + * possible connection request LPC message. + * + * RETURN VALUE + * STATUS_SUCCESS if a connection request is received + * successfully; otherwise an error code. + * + * The buffer ConnectMessage is filled with the connection + * request message queued by NtConnectPort() in PortHandle. + * + * NOTE + * + */ +EXPORTED +NTSTATUS +STDCALL +NtListenPort ( + IN HANDLE PortHandle, + IN PLPC_MESSAGE ConnectMsg + ) +{ + NTSTATUS Status; + + /* + * Wait forever for a connection request. + */ + for (;;) + { + Status = NtReplyWaitReceivePort ( + PortHandle, + NULL, + NULL, + ConnectMsg + ); + /* + * Accept only LPC_CONNECTION_REQUEST requests. + * Drop any other message. + */ + if ( !NT_SUCCESS(Status) + || (LPC_CONNECTION_REQUEST == ConnectMsg->MessageType) + ) + { + DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST); + break; + } + DPRINT("Got message (type %x)\n", ConnectMsg->MessageType); + } + + return (Status); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/port.c b/reactos/ntoskrnl/lpc/port.c new file mode 100644 index 00000000000..7ad2c1331a3 --- /dev/null +++ b/reactos/ntoskrnl/lpc/port.c @@ -0,0 +1,127 @@ +/* $Id: port.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/port.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + * + * 2000-06-04 (ea) + * ntoskrnl/nt/port.c moved in ntoskrnl/lpc/port.c + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE ExPortType = NULL; +ULONG EiNextLpcMessageId = 0; + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS NiInitPort (VOID) +{ + ExPortType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlInitUnicodeString(&ExPortType->TypeName,L"Port"); + + ExPortType->MaxObjects = ULONG_MAX; + ExPortType->MaxHandles = ULONG_MAX; + ExPortType->TotalObjects = 0; + ExPortType->TotalHandles = 0; + ExPortType->PagedPoolCharge = 0; + ExPortType->NonpagedPoolCharge = sizeof(EPORT); + ExPortType->Dump = NULL; + ExPortType->Open = NULL; + ExPortType->Close = NiClosePort; + ExPortType->Delete = NiDeletePort; + ExPortType->Parse = NULL; + ExPortType->Security = NULL; + ExPortType->QueryName = NULL; + ExPortType->OkayToClose = NULL; + ExPortType->Create = NiCreatePort; + + EiNextLpcMessageId = 0; + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME INTERNAL + * NiInitializePort + * + * DESCRIPTION + * Initialize the EPORT object attributes. The Port + * object enters the inactive state. + * + * ARGUMENTS + * Port Pointer to an EPORT object to initialize. + * + * RETURN VALUE + * STATUS_SUCCESS if initialization succedeed. An error code + * otherwise. + */ +NTSTATUS +STDCALL +NiInitializePort ( + IN OUT PEPORT Port + ) +{ + memset (Port, 0, sizeof(EPORT)); + KeInitializeSpinLock (& Port->Lock); + KeInitializeEvent (& Port->Event, SynchronizationEvent, FALSE); + Port->OtherPort = NULL; + Port->QueueLength = 0; + Port->ConnectQueueLength = 0; + Port->State = EPORT_INACTIVE; + InitializeListHead (& Port->QueueListHead); + InitializeListHead (& Port->ConnectQueueListHead); + + return (STATUS_SUCCESS); +} + + +/* MISCELLANEA SYSTEM SERVICES */ + + +/********************************************************************** + * NAME SYSTEM + * NtImpersonateClientOfPort@8 + * + * DESCRIPTION + * + * ARGUMENTS + * PortHandle, + * ClientMessage + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +NtImpersonateClientOfPort ( + HANDLE PortHandle, + PLPC_MESSAGE ClientMessage + ) +{ + UNIMPLEMENTED; +} + + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/query.c b/reactos/ntoskrnl/lpc/query.c new file mode 100644 index 00000000000..aeeb37f79a7 --- /dev/null +++ b/reactos/ntoskrnl/lpc/query.c @@ -0,0 +1,81 @@ +/* $Id: query.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/query.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME EXPORTED + * NtQueryInformationPort@20 + * + * DESCRIPTION + * + * ARGUMENTS + * PortHandle [IN] + * PortInformationClass [IN] + * PortInformation [OUT] + * PortInformationLength [IN] + * ReturnLength [OUT] + * + * RETURN VALUE + * STATUS_SUCCESS if the call succedeed. An error code + * otherwise. + * + * NOTES + * P. Dabak reports that this system service seems to return + * no information. + */ +EXPORTED +NTSTATUS +STDCALL +NtQueryInformationPort ( + IN HANDLE PortHandle, + IN CINT PortInformationClass, + OUT PVOID PortInformation, + IN ULONG PortInformationLength, + OUT PULONG ReturnLength + ) +{ + NTSTATUS Status; + PEPORT Port; + + Status = ObReferenceObjectByHandle ( + PortHandle, + PORT_ALL_ACCESS, /* AccessRequired */ + ExPortType, + UserMode, + (PVOID *) & Port, + NULL + ); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtQueryInformationPort() = %x\n", Status); + return (Status); + } + /* + * FIXME: NT does nothing here! + */ + ObDereferenceObject (Port); + return STATUS_SUCCESS; +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/queue.c b/reactos/ntoskrnl/lpc/queue.c new file mode 100644 index 00000000000..0f00913ba84 --- /dev/null +++ b/reactos/ntoskrnl/lpc/queue.c @@ -0,0 +1,89 @@ +/* $Id: queue.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/queue.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +VOID +STDCALL +EiEnqueueMessagePort ( + IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message + ) +{ + InsertTailList ( + & Port->QueueListHead, + & Message->QueueListEntry + ); + Port->QueueLength++; +} + + +PQUEUEDMESSAGE +STDCALL +EiDequeueMessagePort ( + IN OUT PEPORT Port + ) +{ + PQUEUEDMESSAGE Message; + PLIST_ENTRY entry; + + entry = RemoveHeadList (& Port->QueueListHead); + Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); + Port->QueueLength--; + + return (Message); +} + + +VOID +STDCALL +EiEnqueueConnectMessagePort ( + IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message + ) +{ + InsertTailList ( + & Port->ConnectQueueListHead, + & Message->QueueListEntry + ); + Port->ConnectQueueLength++; +} + + +PQUEUEDMESSAGE +STDCALL +EiDequeueConnectMessagePort ( + IN OUT PEPORT Port + ) +{ + PQUEUEDMESSAGE Message; + PLIST_ENTRY entry; + + entry = RemoveHeadList (& Port->ConnectQueueListHead); + Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); + Port->ConnectQueueLength--; + + return (Message); +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/receive.c b/reactos/ntoskrnl/lpc/receive.c new file mode 100644 index 00000000000..0abb46e98a8 --- /dev/null +++ b/reactos/ntoskrnl/lpc/receive.c @@ -0,0 +1,50 @@ +/* $Id: receive.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/receive.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME SYSTEM + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +NtReadRequestData ( + HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG Returnlength + ) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/reply.c b/reactos/ntoskrnl/lpc/reply.c new file mode 100644 index 00000000000..3ea03b617d1 --- /dev/null +++ b/reactos/ntoskrnl/lpc/reply.c @@ -0,0 +1,237 @@ +/* $Id: reply.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/reply.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +EiReplyOrRequestPort ( + IN PEPORT Port, + IN PLPC_MESSAGE LpcReply, + IN ULONG MessageType, + IN PEPORT Sender + ) +{ + KIRQL oldIrql; + PQUEUEDMESSAGE MessageReply; + + MessageReply = ExAllocatePool(NonPagedPool, sizeof(QUEUEDMESSAGE)); + MessageReply->Sender = Sender; + + if (LpcReply != NULL) + { + memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize); + } + + MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId(); + MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId(); + MessageReply->Message.MessageType = MessageType; + MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId); + + KeAcquireSpinLock(&Port->Lock, &oldIrql); + EiEnqueueMessagePort(Port, MessageReply); + KeReleaseSpinLock(&Port->Lock, oldIrql); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtReplyPort ( + IN HANDLE PortHandle, + IN PLPC_MESSAGE LpcReply + ) +{ + NTSTATUS Status; + PEPORT Port; + + DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, /* AccessRequired */ + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtReplyPort() = %x\n", Status); + return(Status); + } + + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcReply, + LPC_REPLY, + Port); + KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); + + ObDereferenceObject(Port); + + return(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtReplyWaitReceivePort ( + HANDLE PortHandle, + PULONG PortId, + PLPC_MESSAGE LpcReply, + PLPC_MESSAGE LpcMessage + ) +{ + NTSTATUS Status; + PEPORT Port; + KIRQL oldIrql; + PQUEUEDMESSAGE Request; + + DPRINT("NtReplyWaitReceivePort(PortHandle %x, LpcReply %x, " + "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtReplyWaitReceivePort() = %x\n", Status); + return(Status); + } + + /* + * Send the reply + */ + if (LpcReply != NULL) + { + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcReply, + LPC_REPLY, + Port); + KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Port); + return(Status); + } + } + + /* + * Want for a message to be received + */ + DPRINT("Entering wait for message\n"); + KeWaitForSingleObject(&Port->Event, + UserRequest, + UserMode, + FALSE, + NULL); + DPRINT("Woke from wait for message\n"); + + /* + * Dequeue the message + */ + KeAcquireSpinLock(&Port->Lock, &oldIrql); + Request = EiDequeueMessagePort(Port); + memcpy(LpcMessage, &Request->Message, Request->Message.MessageSize); + if (Request->Message.MessageType == LPC_CONNECTION_REQUEST) + { + EiEnqueueConnectMessagePort(Port, Request); + KeReleaseSpinLock(&Port->Lock, oldIrql); + } + else + { + KeReleaseSpinLock(&Port->Lock, oldIrql); + ExFreePool(Request); + } + + /* + * + */ + ObDereferenceObject(Port); + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtReplyWaitReplyPort ( + HANDLE PortHandle, + PLPC_MESSAGE ReplyMessage + ) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/lpc/send.c b/reactos/ntoskrnl/lpc/send.c new file mode 100644 index 00000000000..c3e053c6b61 --- /dev/null +++ b/reactos/ntoskrnl/lpc/send.c @@ -0,0 +1,267 @@ +/* $Id: send.c,v 1.1 2000/06/04 17:27:39 ea Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/send.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +LpcSendTerminationPort ( + IN PEPORT Port, + IN TIME CreationTime + ) +{ + NTSTATUS Status; + LPC_TERMINATION_MESSAGE Msg; + + Msg.CreationTime = CreationTime; + Status = LpcRequestPort ( + Port, + & Msg.Header + ); + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +LpcSendDebugMessagePort ( + IN PEPORT Port, + IN PLPC_DBG_MESSAGE Message + ) +{ + NTSTATUS Status; + + Status = LpcRequestPort(Port, + &Message->Header); + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +LpcRequestPort ( + IN PEPORT Port, + IN PLPC_MESSAGE LpcMessage + ) +{ + NTSTATUS Status; + + DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage); + + Status = EiReplyOrRequestPort(Port, + LpcMessage, + LPC_DATAGRAM, + Port); + KeSetEvent(&Port->Event, IO_NO_INCREMENT, FALSE); + + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtRequestPort ( + IN HANDLE PortHandle, + IN PLPC_MESSAGE LpcMessage + ) +{ + NTSTATUS Status; + PEPORT Port; + + DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle, + LpcMessage); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtRequestPort() = %x\n", Status); + return(Status); + } + + Status = LpcRequestPort(Port->OtherPort, + LpcMessage); + + ObDereferenceObject(Port); + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtRequestWaitReplyPort ( + IN HANDLE PortHandle, + PLPC_MESSAGE LpcRequest, + PLPC_MESSAGE LpcReply + ) +{ + NTSTATUS Status; + PEPORT Port; + PQUEUEDMESSAGE Message; + KIRQL oldIrql; + + DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, " + "LpcReply %x)\n", PortHandle, LpcRequest, LpcReply); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcRequest, + LPC_REQUEST, + Port); + KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("Enqueue failed\n"); + ObDereferenceObject(Port); + return(Status); + } + + /* + * Wait for a reply + */ + KeWaitForSingleObject(&Port->Event, + UserRequest, + UserMode, + FALSE, + NULL); + + /* + * Dequeue the reply + */ + KeAcquireSpinLock(&Port->Lock, &oldIrql); + Message = EiDequeueMessagePort(Port); + KeReleaseSpinLock(&Port->Lock, oldIrql); + DPRINT("Message->Message.MessageSize %d\n", + Message->Message.MessageSize); + memcpy(LpcReply, &Message->Message, Message->Message.MessageSize); + ExFreePool(Message); + + ObDereferenceObject(Port); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtWriteRequestData ( + HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength + ) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/makefile_rex b/reactos/ntoskrnl/makefile_rex index e12bf716826..7e1594d106a 100644 --- a/reactos/ntoskrnl/makefile_rex +++ b/reactos/ntoskrnl/makefile_rex @@ -1,4 +1,4 @@ -# $Id: makefile_rex,v 1.70 2000/05/07 23:04:43 ekohl Exp $ +# $Id: makefile_rex,v 1.71 2000/06/04 17:27:35 ea Exp $ # # ReactOS Operating System # @@ -31,7 +31,6 @@ OBJECTS_NT = \ nt/ntsem.o \ nt/nttimer.o \ nt/plugplay.o \ - nt/port.o \ nt/profile.o \ nt/zw.o @@ -233,6 +232,20 @@ OBJECTS_LDR = \ ldr/sysdll.o \ ldr/userldr.o +# Local Procedure Call (Lpc) +OBJECTS_LPC = \ + lpc/close.o \ + lpc/complete.o \ + lpc/connect.o \ + lpc/create.o \ + lpc/listen.o \ + lpc/port.o \ + lpc/query.o \ + lpc/queue.o \ + lpc/receive.o \ + lpc/reply.o \ + lpc/send.o + # Nation Language Support Library (Nls) OBJECTS_NLS = nls/nls.o @@ -344,6 +357,12 @@ $(OBJECTS_PATH)/ldr.o: $(OBJECTS_LDR) -o $(OBJECTS_PATH)/ldr.o \ $(OBJECTS_LDR) +$(OBJECTS_PATH)/lpc.o: $(OBJECTS_LPC) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/lpc.o \ + $(OBJECTS_LPC) + $(OBJECTS_PATH)/nls.o: $(OBJECTS_NLS) $(LD) \ -r \ @@ -385,6 +404,7 @@ OBJECTS = \ $(OBJECTS_PATH)/cm.o \ $(OBJECTS_PATH)/dbg.o \ $(OBJECTS_PATH)/ex.o \ + $(OBJECTS_PATH)/lpc.o \ $(OBJECTS_PATH)/fs.o \ $(OBJECTS_PATH)/io.o \ $(OBJECTS_PATH)/kd.o \ @@ -403,13 +423,13 @@ OBJECTS = \ ifeq ($(DOSCLI),yes) CLEAN_FILES = $(OBJECTS_PATH)\*.o cc\*.o cm\*.o dbg\*.o ex\*.o hal\x86\*.o io\*.o \ ke\*.o ldr\*.o mm\*.o nt\*.o ob\*.o ps\*.o rtl\*.o se\*.o \ - ke\i386\*.o mm\i386\*.o fs\*.o po\*.o nls\*.o \ + ke\i386\*.o mm\i386\*.o fs\*.o po\*.o nls\*.o lpc\*.o \ kd\*.o utils\export\export.exe $(TARGETNAME).o $(TARGETNAME).a junk.tmp \ base.tmp temp.exp $(TARGETNAME).exe $(TARGETNAME).sym $(TARGETNAME).coff else CLEAN_FILES = $(OBJECTS_PATH)/*.o cc/*.o cm/*.o dbg/*.o ex/*.o hal/x86/*.o io/*.o \ ke/*.o ldr/*.o mm/*.o nt/*.o ob/*.o ps/*.o rtl/*.o se/*.o \ - ke/i386/*.o mm/i386/*.o fs/*.o po/*.o nls/*.o \ + ke/i386/*.o mm/i386/*.o fs/*.o po/*.o nls/*.o lpc/*.o \ kd/*.o utils/export/export $(TARGETNAME).o $(TARGETNAME).a junk.tmp \ base.tmp temp.exp $(TARGETNAME).exe $(TARGETNAME).sym $(TARGETNAME).coff endif @@ -541,3 +561,4 @@ WIN32_LEAN_AND_MEAN = yes WARNINGS_ARE_ERRORS = yes include ../rules.mak +# EOF diff --git a/reactos/ntoskrnl/nt/port.c b/reactos/ntoskrnl/nt/port.c deleted file mode 100644 index 0f6bc8e4b4a..00000000000 --- a/reactos/ntoskrnl/nt/port.c +++ /dev/null @@ -1,796 +0,0 @@ -/* $Id: port.c,v 1.19 2000/04/07 02:24:02 dwelch Exp $ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/port.c - * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - - -/* TYPES ********************************************************************/ - -#define EPORT_INACTIVE (0) -#define EPORT_WAIT_FOR_CONNECT (1) -#define EPORT_WAIT_FOR_ACCEPT (2) -#define EPORT_WAIT_FOR_COMPLETE_SRV (3) -#define EPORT_WAIT_FOR_COMPLETE_CLT (4) -#define EPORT_CONNECTED_CLIENT (5) -#define EPORT_CONNECTED_SERVER (6) -#define EPORT_DISCONNECTED (7) - -struct _EPORT; - -typedef struct _QUEUEDMESSAGE -{ - struct _EPORT* Sender; - LIST_ENTRY QueueListEntry; - LPC_MESSAGE Message; - UCHAR MessageData[MAX_MESSAGE_DATA]; -} QUEUEDMESSAGE, *PQUEUEDMESSAGE; - -/* GLOBALS *******************************************************************/ - -POBJECT_TYPE ExPortType = NULL; -static ULONG EiNextLpcMessageId; - -/* FUNCTIONS *****************************************************************/ - -VOID EiEnqueueMessagePort(PEPORT Port, PQUEUEDMESSAGE Message) -{ - InsertTailList(&Port->QueueListHead, &Message->QueueListEntry); - Port->QueueLength++; -} - -PQUEUEDMESSAGE EiDequeueMessagePort(PEPORT Port) -{ - PQUEUEDMESSAGE Message; - PLIST_ENTRY entry; - - entry = RemoveHeadList(&Port->QueueListHead); - Message = CONTAINING_RECORD(entry, QUEUEDMESSAGE, QueueListEntry); - Port->QueueLength--; - - return(Message); -} - -VOID EiEnqueueConnectMessagePort(PEPORT Port, PQUEUEDMESSAGE Message) -{ - InsertTailList(&Port->ConnectQueueListHead, &Message->QueueListEntry); - Port->ConnectQueueLength++; -} - -PQUEUEDMESSAGE EiDequeueConnectMessagePort(PEPORT Port) -{ - PQUEUEDMESSAGE Message; - PLIST_ENTRY entry; - - entry = RemoveHeadList(&Port->ConnectQueueListHead); - Message = CONTAINING_RECORD(entry, QUEUEDMESSAGE, QueueListEntry); - Port->ConnectQueueLength--; - - return(Message); -} - -NTSTATUS EiReplyOrRequestPort(PEPORT Port, - PLPC_MESSAGE LpcReply, - ULONG MessageType, - PEPORT Sender) -{ - KIRQL oldIrql; - PQUEUEDMESSAGE MessageReply; - - MessageReply = ExAllocatePool(NonPagedPool, sizeof(QUEUEDMESSAGE)); - MessageReply->Sender = Sender; - - if (LpcReply != NULL) - { - memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize); - } - - MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId(); - MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId(); - MessageReply->Message.MessageType = MessageType; - MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId); - - KeAcquireSpinLock(&Port->Lock, &oldIrql); - EiEnqueueMessagePort(Port, MessageReply); - KeReleaseSpinLock(&Port->Lock, oldIrql); - - return(STATUS_SUCCESS); -} - -VOID NiClosePort(PVOID ObjectBody, - ULONG HandleCount) -{ - PEPORT Port = (PEPORT)ObjectBody; - LPC_MESSAGE Message; - -// DPRINT1("NiClosePort(ObjectBody %x, HandleCount %d) RefCount %d\n", -// ObjectBody, HandleCount, ObGetReferenceCount(Port)); - - if (HandleCount == 0 && - Port->State == EPORT_CONNECTED_CLIENT && - ObGetReferenceCount(Port) == 2) - { -// DPRINT1("All handles closed to client port\n"); - - Message.MessageSize = sizeof(LPC_MESSAGE); - Message.DataSize = 0; - - EiReplyOrRequestPort(Port->OtherPort, - &Message, - LPC_PORT_CLOSED, - Port); - KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); - - Port->OtherPort->OtherPort = NULL; - Port->OtherPort->State = EPORT_DISCONNECTED; - ObDereferenceObject(Port); - } - if (HandleCount == 0 && - Port->State == EPORT_CONNECTED_SERVER && - ObGetReferenceCount(Port) == 2) - { -// DPRINT("All handles closed to server\n"); - - Port->OtherPort->OtherPort = NULL; - Port->OtherPort->State = EPORT_DISCONNECTED; - ObDereferenceObject(Port->OtherPort); - } -} - -VOID NiDeletePort(PVOID ObjectBody) -{ -// PEPORT Port = (PEPORT)ObjectBody; - -// DPRINT1("Deleting port %x\n", Port); -} - -NTSTATUS NiCreatePort(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - NTSTATUS Status; - - if (RemainingPath == NULL) - { - return(STATUS_SUCCESS); - } - - if (wcschr(RemainingPath+1, '\\') != NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - Status = ObReferenceObjectByPointer(Parent, - STANDARD_RIGHTS_REQUIRED, - ObDirectoryType, - UserMode); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1); - ObDereferenceObject(Parent); - - return(STATUS_SUCCESS); -} - -NTSTATUS NiInitPort(VOID) -{ - ExPortType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - RtlInitUnicodeString(&ExPortType->TypeName,L"Port"); - - ExPortType->MaxObjects = ULONG_MAX; - ExPortType->MaxHandles = ULONG_MAX; - ExPortType->TotalObjects = 0; - ExPortType->TotalHandles = 0; - ExPortType->PagedPoolCharge = 0; - ExPortType->NonpagedPoolCharge = sizeof(EPORT); - ExPortType->Dump = NULL; - ExPortType->Open = NULL; - ExPortType->Close = NiClosePort; - ExPortType->Delete = NiDeletePort; - ExPortType->Parse = NULL; - ExPortType->Security = NULL; - ExPortType->QueryName = NULL; - ExPortType->OkayToClose = NULL; - ExPortType->Create = NiCreatePort; - - EiNextLpcMessageId = 0; - - return(STATUS_SUCCESS); -} - -static NTSTATUS NiInitializePort(PEPORT Port) -{ - memset(Port, 0, sizeof(EPORT)); - KeInitializeSpinLock(&Port->Lock); - KeInitializeEvent(&Port->Event, SynchronizationEvent, FALSE); - Port->OtherPort = NULL; - Port->QueueLength = 0; - Port->ConnectQueueLength = 0; - Port->State = EPORT_INACTIVE; - InitializeListHead(&Port->QueueListHead); - InitializeListHead(&Port->ConnectQueueListHead); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtCreatePort(PHANDLE PortHandle, - POBJECT_ATTRIBUTES ObjectAttributes, - ULONG MaxConnectInfoLength, - ULONG MaxDataLength, - ULONG Reserved) -{ - PEPORT Port; - NTSTATUS Status; - - DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer); - - Port = ObCreateObject(PortHandle, - PORT_ALL_ACCESS, - ObjectAttributes, - ExPortType); - if (Port == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - Status = NiInitializePort(Port); - Port->MaxConnectInfoLength = 260; - Port->MaxDataLength = 328; - - ObDereferenceObject(Port); - - return(Status); -} - -NTSTATUS STDCALL NtConnectPort (PHANDLE ConnectedPort, - PUNICODE_STRING PortName, - PSECURITY_QUALITY_OF_SERVICE Qos, - PLPC_SECTION_WRITE WriteMap, - PLPC_SECTION_READ ReadMap, - PULONG MaxMessageSize, - PVOID ConnectInfo, - PULONG UserConnectInfoLength) -/* - * FUNCTION: Connect to a named port and wait for the other side to - * accept the connection - */ -{ - NTSTATUS Status; - PEPORT NamedPort; - PEPORT OurPort; - HANDLE OurPortHandle; - PLPC_MESSAGE Request; - PQUEUEDMESSAGE Reply; - ULONG ConnectInfoLength; - KIRQL oldIrql; - - DPRINT("PortName %x\n", PortName); - DPRINT("NtConnectPort(PortName %S)\n", PortName->Buffer); - - /* - * Copy in user parameters - */ - memcpy(&ConnectInfoLength, - UserConnectInfoLength, - sizeof(*UserConnectInfoLength)); - - /* - * Get access to the port - */ - Status = ObReferenceObjectByName(PortName, - 0, - NULL, - PORT_ALL_ACCESS, /* DesiredAccess */ - ExPortType, - UserMode, - NULL, - (PVOID*)&NamedPort); - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed to reference named port (status %x)\n", Status); - return(Status); - } - - /* - * Create a port to represent our side of the connection - */ - OurPort = ObCreateObject(&OurPortHandle, - PORT_ALL_ACCESS, - NULL, - ExPortType); - NiInitializePort(OurPort); - - /* - * Create a request message - */ - DPRINT("Creating request message\n"); - - Request = ExAllocatePool(NonPagedPool, - sizeof(LPC_MESSAGE) + ConnectInfoLength); - - Request->DataSize = ConnectInfoLength; - Request->MessageSize = sizeof(LPC_MESSAGE) + ConnectInfoLength; - Request->SharedSectionSize = 0; - if (ConnectInfo != NULL && ConnectInfoLength > 0) - { - memcpy((PVOID)(Request + 1), ConnectInfo, ConnectInfoLength); - } - - /* - * Queue the message to the named port - */ - DPRINT("Queuing message\n"); - - EiReplyOrRequestPort(NamedPort, Request, LPC_CONNECTION_REQUEST, OurPort); - KeSetEvent(&NamedPort->Event, IO_NO_INCREMENT, FALSE); - - DPRINT("Waiting for connection completion\n"); - - /* - * Wait for them to accept our connection - */ - KeWaitForSingleObject(&OurPort->Event, - UserRequest, - UserMode, - FALSE, - NULL); - - DPRINT("Received connection completion\n"); - KeAcquireSpinLock(&OurPort->Lock, &oldIrql); - Reply = EiDequeueMessagePort(OurPort); - KeReleaseSpinLock(&OurPort->Lock, oldIrql); - memcpy(ConnectInfo, - Reply->MessageData, - Reply->Message.DataSize); - *UserConnectInfoLength = Reply->Message.DataSize; - - if (Reply->Message.MessageType == LPC_CONNECTION_REFUSED) - { - ObDereferenceObject(NamedPort); - ObDereferenceObject(OurPort); - ZwClose(OurPortHandle); - ExFreePool(Request); - ExFreePool(Reply); - return(STATUS_UNSUCCESSFUL); - } - - OurPort->State = EPORT_CONNECTED_CLIENT; - *ConnectedPort = OurPortHandle; - ExFreePool(Reply); - ExFreePool(Request); - - DPRINT("Exited successfully\n"); - - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE ServerPortHandle, - HANDLE NamedPortHandle, - PLPC_MESSAGE LpcMessage, - BOOLEAN AcceptIt, - PLPC_SECTION_WRITE WriteMap, - PLPC_SECTION_READ ReadMap) -{ - NTSTATUS Status; - PEPORT NamedPort; - PEPORT OurPort = NULL; - PQUEUEDMESSAGE ConnectionRequest; - KIRQL oldIrql; - - Status = ObReferenceObjectByHandle(NamedPortHandle, - PORT_ALL_ACCESS, - ExPortType, - UserMode, - (PVOID*)&NamedPort, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* - * Create a port object for our side of the connection - */ - if (AcceptIt == 1) - { - OurPort = ObCreateObject(ServerPortHandle, - PORT_ALL_ACCESS, - NULL, - ExPortType); - NiInitializePort(OurPort); - } - - /* - * Dequeue the connection request - */ - KeAcquireSpinLock(&NamedPort->Lock, &oldIrql); - ConnectionRequest = EiDequeueConnectMessagePort(NamedPort); - KeReleaseSpinLock(&NamedPort->Lock, oldIrql); - - if (AcceptIt != 1) - { - EiReplyOrRequestPort(ConnectionRequest->Sender, - LpcMessage, - LPC_CONNECTION_REFUSED, - NamedPort); - KeSetEvent(&ConnectionRequest->Sender->Event, IO_NO_INCREMENT, FALSE); - ObDereferenceObject(ConnectionRequest->Sender); - ExFreePool(ConnectionRequest); - ObDereferenceObject(NamedPort); - return(STATUS_SUCCESS); - } - - /* - * Connect the two ports - */ - OurPort->OtherPort = ConnectionRequest->Sender; - OurPort->OtherPort->OtherPort = OurPort; - EiReplyOrRequestPort(ConnectionRequest->Sender, - LpcMessage, - LPC_REPLY, - OurPort); - ExFreePool(ConnectionRequest); - - ObDereferenceObject(OurPort); - ObDereferenceObject(NamedPort); - - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL NtCompleteConnectPort (HANDLE PortHandle) -{ - NTSTATUS Status; - PEPORT OurPort; - - DPRINT("NtCompleteConnectPort(PortHandle %x)\n", PortHandle); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - ExPortType, - UserMode, - (PVOID*)&OurPort, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - KeSetEvent(&OurPort->OtherPort->Event, IO_NO_INCREMENT, FALSE); - - OurPort->State = EPORT_CONNECTED_SERVER; - - ObDereferenceObject(OurPort); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtImpersonateClientOfPort (HANDLE PortHandle, - PLPC_MESSAGE ClientMessage) -{ - UNIMPLEMENTED; -} - - -NTSTATUS STDCALL NtListenPort (IN HANDLE PortHandle, - IN PLPC_MESSAGE ConnectMsg) -/* - * FUNCTION: Listen on a named port and wait for a connection attempt - */ -{ - NTSTATUS Status; - - for(;;) - { - Status = NtReplyWaitReceivePort(PortHandle, - NULL, - NULL, - ConnectMsg); - DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST); - if (!NT_SUCCESS(Status) || - ConnectMsg->MessageType == LPC_CONNECTION_REQUEST) - { - break; - } - } - return(Status); -} - - -NTSTATUS STDCALL NtQueryInformationPort (IN HANDLE PortHandle, - IN CINT PortInformationClass, - OUT PVOID PortInformation, - IN ULONG PortInformationLength, - OUT PULONG ReturnLength) -{ - UNIMPLEMENTED; -} - - -NTSTATUS STDCALL NtReplyPort (IN HANDLE PortHandle, - IN PLPC_MESSAGE LpcReply) -{ - NTSTATUS Status; - PEPORT Port; - - DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, /* AccessRequired */ - ExPortType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtReplyPort() = %x\n", Status); - return(Status); - } - - Status = EiReplyOrRequestPort(Port->OtherPort, - LpcReply, - LPC_REPLY, - Port); - KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); - - ObDereferenceObject(Port); - - return(Status); -} - - -NTSTATUS STDCALL NtReplyWaitReceivePort (HANDLE PortHandle, - PULONG PortId, - PLPC_MESSAGE LpcReply, - PLPC_MESSAGE LpcMessage) -{ - NTSTATUS Status; - PEPORT Port; - KIRQL oldIrql; - PQUEUEDMESSAGE Request; - - DPRINT("NtReplyWaitReceivePort(PortHandle %x, LpcReply %x, " - "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - ExPortType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtReplyWaitReceivePort() = %x\n", Status); - return(Status); - } - - /* - * Send the reply - */ - if (LpcReply != NULL) - { - Status = EiReplyOrRequestPort(Port->OtherPort, - LpcReply, - LPC_REPLY, - Port); - KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); - - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Port); - return(Status); - } - } - - /* - * Want for a message to be received - */ - DPRINT("Entering wait for message\n"); - KeWaitForSingleObject(&Port->Event, - UserRequest, - UserMode, - FALSE, - NULL); - DPRINT("Woke from wait for message\n"); - - /* - * Dequeue the message - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - Request = EiDequeueMessagePort(Port); - memcpy(LpcMessage, &Request->Message, Request->Message.MessageSize); - if (Request->Message.MessageType == LPC_CONNECTION_REQUEST) - { - EiEnqueueConnectMessagePort(Port, Request); - KeReleaseSpinLock(&Port->Lock, oldIrql); - } - else - { - KeReleaseSpinLock(&Port->Lock, oldIrql); - ExFreePool(Request); - } - - /* - * - */ - ObDereferenceObject(Port); - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL LpcSendTerminationPort(PEPORT Port, - TIME CreationTime) -{ - NTSTATUS Status; - LPC_TERMINATION_MESSAGE Msg; - - Msg.CreationTime = CreationTime; - Status = LpcRequestPort(Port, - &Msg.Header); - return(Status); -} - -NTSTATUS STDCALL LpcSendDebugMessagePort(PEPORT Port, - PLPC_DBG_MESSAGE Message) -{ - NTSTATUS Status; - - Status = LpcRequestPort(Port, - &Message->Header); - return(Status); -} - -NTSTATUS STDCALL LpcRequestPort(PEPORT Port, - PLPC_MESSAGE LpcMessage) -{ - NTSTATUS Status; - - DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage); - - Status = EiReplyOrRequestPort(Port, - LpcMessage, - LPC_DATAGRAM, - Port); - KeSetEvent(&Port->Event, IO_NO_INCREMENT, FALSE); - - return(Status); -} - -NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle, - IN PLPC_MESSAGE LpcMessage) -{ - NTSTATUS Status; - PEPORT Port; - - DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle, - LpcMessage); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - ExPortType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtRequestPort() = %x\n", Status); - return(Status); - } - - Status = LpcRequestPort(Port->OtherPort, - LpcMessage); - - ObDereferenceObject(Port); - return(Status); -} - - -NTSTATUS STDCALL NtRequestWaitReplyPort(IN HANDLE PortHandle, - PLPC_MESSAGE LpcRequest, - PLPC_MESSAGE LpcReply) -{ - NTSTATUS Status; - PEPORT Port; - PQUEUEDMESSAGE Message; - KIRQL oldIrql; - - DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, " - "LpcReply %x)\n", PortHandle, LpcRequest, LpcReply); - - Status = ObReferenceObjectByHandle(PortHandle, - PORT_ALL_ACCESS, - ExPortType, - UserMode, - (PVOID*)&Port, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - - Status = EiReplyOrRequestPort(Port->OtherPort, - LpcRequest, - LPC_REQUEST, - Port); - KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE); - - if (!NT_SUCCESS(Status)) - { - DbgPrint("Enqueue failed\n"); - ObDereferenceObject(Port); - return(Status); - } - - /* - * Wait for a reply - */ - KeWaitForSingleObject(&Port->Event, - UserRequest, - UserMode, - FALSE, - NULL); - - /* - * Dequeue the reply - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - Message = EiDequeueMessagePort(Port); - KeReleaseSpinLock(&Port->Lock, oldIrql); - DPRINT("Message->Message.MessageSize %d\n", - Message->Message.MessageSize); - memcpy(LpcReply, &Message->Message, Message->Message.MessageSize); - ExFreePool(Message); - - ObDereferenceObject(Port); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL NtReplyWaitReplyPort(HANDLE PortHandle, - PLPC_MESSAGE ReplyMessage) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtReadRequestData (HANDLE PortHandle, - PLPC_MESSAGE Message, - ULONG Index, - PVOID Buffer, - ULONG BufferLength, - PULONG Returnlength) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle, - PLPC_MESSAGE Message, - ULONG Index, - PVOID Buffer, - ULONG BufferLength, - PULONG ReturnLength) -{ - UNIMPLEMENTED; -} diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 970df075fba..201b3e1561e 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.43 2000/06/03 21:36:32 ekohl Exp $ +/* $Id: process.c,v 1.44 2000/06/04 17:27:39 ea Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -757,16 +757,18 @@ PiSnapshotProcessTable ( ) { KIRQL OldIrql; - PLIST_ENTRY CurrentEntry; - PEPROCESS Current; + PLIST_ENTRY CurrentEntryP; + PEPROCESS CurrentP; + PLIST_ENTRY CurrentEntryT; + PETHREAD CurrentT; ULONG RequiredSize = 0L; BOOLEAN SizeOnly = FALSE; - ULONG SpiSizeLast = 0L; - ULONG SpiSizeCurrent = 0L; + ULONG SpiSize = 0L; PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer; + PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL; PSYSTEM_THREAD_INFO pInfoT = NULL; @@ -782,33 +784,18 @@ PiSnapshotProcessTable ( * list is circular, the guard is false * after the last process. */ - for ( CurrentEntry = PsProcessListHead.Flink; - (CurrentEntry != & PsProcessListHead); - CurrentEntry = CurrentEntry->Flink + for ( CurrentEntryP = PsProcessListHead.Flink; + (CurrentEntryP != & PsProcessListHead); + CurrentEntryP = CurrentEntryP->Flink ) { - /* - * Get a reference to the - * process object we are - * handling. - */ - Current = CONTAINING_RECORD( - CurrentEntry, - EPROCESS, - Pcb.ProcessListEntry - ); - /* FIXME: assert (NULL != Current) */ /* * Compute how much space is * occupied in the snapshot * by adding this process info. + * (at least one thread). */ - SpiSizeCurrent = - sizeof (SYSTEM_PROCESS_INFORMATION) - + ( - (Current->ThreadCount - 1) - * sizeof (SYSTEM_THREAD_INFORMATION) - ); + SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION); RequiredSize += SpiSizeCurrent; /* * Do not write process data in the @@ -824,36 +811,112 @@ PiSnapshotProcessTable ( SizeOnly = TRUE; continue; } + /* + * Get a reference to the + * process descriptor we are + * handling. + */ + CurrentP = CONTAINING_RECORD( + CurrentEntryP, + EPROCESS, + Pcb.ProcessListEntry + ); + /* + * Write process data in the buffer. + */ + RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION)); + /* PROCESS */ + pInfoP->ThreadCount = 0L; + pInfoP->ProcessId = CurrentP->UniqueProcessId; + RtlInitUnicodeString ( + & pInfoP->Name, + CurrentP->ImageFileName + ); + /* THREAD */ + for ( pInfoT = & CurrentP->ThreadSysInfo [0], + CurrentEntryT = CurrentP->Pcb.ThreadListHead.Flink; + + (CurrentEntryT != & CurrentP->Pcb.ThreadListHead); + + pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount], + CurrentEntryT = CurrentEntryT->Flink + ) + { + /* + * Recalculate the size of the + * information block. + */ + if (0 < pInfoP->ThreadCount) + { + RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION); + } + /* + * Do not write thread data in the + * buffer if it is too small. + */ + if (TRUE == SizeOnly) continue; + /* + * Check if the buffer can contain + * the full snapshot. + */ + if (Size < RequiredSize) + { + SizeOnly = TRUE; + continue; + } + /* + * Get a reference to the + * thread descriptor we are + * handling. + */ + CurrentT = CONTAINING_RECORD( + CurrentEntryT, + KTHREAD, + Tcb.ThreadListEntry + ); + /* + * Write thread data. + */ + RtlZeroMemory ( + pInfoT, + sizeof (SYSTEM_THREAD_INFORMATION) + ); + pInfoT->KernelTime = CurrentT-> ; /* TIME */ + pInfoT->UserTime = CurrentT-> ; /* TIME */ + pInfoT->CreateTime = CurrentT-> ; /* TIME */ + pInfoT->TickCount = CurrentT-> ; /* ULONG */ + pInfoT->StartEIP = CurrentT-> ; /* ULONG */ + pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */ + pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */ + pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */ + pInfoT->BasePriority = CurrentT-> ; /* ULONG */ + pInfoT->nSwitches = CurrentT-> ; /* ULONG */ + pInfoT->State = CurrentT-> ; /* DWORD */ + pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */ + /* + * Count the number of threads + * this process has. + */ + ++ pInfoP->ThreadCount; + } + /* + * Save the size of information + * stored in the buffer for the + * current process. + */ + pInfoP->RelativeOffset = SpiSize; + /* + * Save a reference to the last + * valid information block. + */ + pInfoPLast = pInfoP; /* * Compute the offset of the * SYSTEM_PROCESS_INFORMATION * descriptor in the snapshot - * buffer for this process. + * buffer for the next process. */ - if (0L != SpiSizeLast) - { - (ULONG) pInfoP += SpiSizeLast; - /* Save current process SpiSize */ - SpiSizeLast = SpiSizeCurrent; - } - /* - * Write process data in the buffer. - */ - pInfoP->RelativeOffset = SpiSizeCurrent; - /* PROCESS */ - pInfoP->ThreadCount = - pInfoP->ProcessId = Current->UniqueProcessId; - RtlInitUnicodeString ( - & pInfoP->Name, - Current->ImageFileName - ); - /* THREAD */ - for ( ThreadIndex = 0; - (ThreadIndex < Current->ThreadCount); - ThreadIndex ++ - ) - { - } + (ULONG) pInfoP += SpiSize; } /* * Unlock the process list. @@ -868,7 +931,10 @@ PiSnapshotProcessTable ( */ if (TRUE == SizeOnly) { - *pRequiredSize = RequiredSize; + if (NULL != RequiredSize) + { + *pRequiredSize = RequiredSize; + } return STATUS_INFO_LENGTH_MISMATCH; } /*