[CMAKE]
[reactos.git] / ntoskrnl / lpc / create.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/lpc/create.c
5 * PURPOSE: Local Procedure Call: Port/Queue/Message Creation
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 NTSTATUS
18 NTAPI
19 LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port)
20 {
21 PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
22 PAGED_CODE();
23
24 /* Allocate the queue */
25 MessageQueue = ExAllocatePoolWithTag(NonPagedPool,
26 sizeof(LPCP_NONPAGED_PORT_QUEUE),
27 'troP');
28 if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES;
29
30 /* Set it up */
31 KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG);
32 MessageQueue->BackPointer = Port;
33
34 /* And link it with the Paged Pool part */
35 Port->MsgQueue.Semaphore = &MessageQueue->Semaphore;
36 InitializeListHead(&Port->MsgQueue.ReceiveHead);
37 return STATUS_SUCCESS;
38 }
39
40 NTSTATUS
41 NTAPI
42 LpcpCreatePort(OUT PHANDLE PortHandle,
43 IN POBJECT_ATTRIBUTES ObjectAttributes,
44 IN ULONG MaxConnectionInfoLength,
45 IN ULONG MaxMessageLength,
46 IN ULONG MaxPoolUsage,
47 IN BOOLEAN Waitable)
48 {
49 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
50 NTSTATUS Status;
51 PLPCP_PORT_OBJECT Port;
52 PAGED_CODE();
53 LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName);
54
55 /* Create the Object */
56 Status = ObCreateObject(PreviousMode,
57 LpcPortObjectType,
58 ObjectAttributes,
59 PreviousMode,
60 NULL,
61 sizeof(LPCP_PORT_OBJECT),
62 0,
63 0,
64 (PVOID*)&Port);
65 if (!NT_SUCCESS(Status)) return Status;
66
67 /* Set up the Object */
68 RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT));
69 Port->ConnectionPort = Port;
70 Port->Creator = PsGetCurrentThread()->Cid;
71 InitializeListHead(&Port->LpcDataInfoChainHead);
72 InitializeListHead(&Port->LpcReplyChainHead);
73
74 /* Check if we don't have a name */
75 if (!ObjectAttributes->ObjectName->Buffer)
76 {
77 /* Set up for an unconnected port */
78 Port->Flags = LPCP_UNCONNECTED_PORT;
79 Port->ConnectedPort = Port;
80 Port->ServerProcess = NULL;
81 }
82 else
83 {
84 /* Set up for a named connection port */
85 Port->Flags = LPCP_CONNECTION_PORT;
86 Port->ServerProcess = PsGetCurrentProcess();
87
88 /* Don't let the process die on us */
89 ObReferenceObject(Port->ServerProcess);
90 }
91
92 /* Check if this is a waitable port */
93 if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT;
94
95 /* Setup the port queue */
96 Status = LpcpInitializePortQueue(Port);
97 if (!NT_SUCCESS(Status))
98 {
99 /* Fail */
100 ObDereferenceObject(Port);
101 return Status;
102 }
103
104 /* Check if this is a waitable port */
105 if (Port->Flags & LPCP_WAITABLE_PORT)
106 {
107 /* Setup the wait event */
108 KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE);
109 }
110
111 /* Set the maximum message size allowed */
112 Port->MaxMessageLength = LpcpMaxMessageSize -
113 FIELD_OFFSET(LPCP_MESSAGE, Request);
114
115 /* Now subtract the actual message structures and get the data size */
116 Port->MaxConnectionInfoLength = Port->MaxMessageLength -
117 sizeof(PORT_MESSAGE) -
118 sizeof(LPCP_CONNECTION_MESSAGE);
119
120 /* Validate the sizes */
121 if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength)
122 {
123 /* Not enough space for your request */
124 ObDereferenceObject(Port);
125 return STATUS_INVALID_PARAMETER_3;
126 }
127 else if (Port->MaxMessageLength < MaxMessageLength)
128 {
129 /* Not enough space for your request */
130 ObDereferenceObject(Port);
131 return STATUS_INVALID_PARAMETER_4;
132 }
133
134 /* Now set the custom setting */
135 Port->MaxMessageLength = MaxMessageLength;
136
137 /* Insert it now */
138 Status = ObInsertObject((PVOID)Port,
139 NULL,
140 PORT_ALL_ACCESS,
141 0,
142 NULL,
143 PortHandle);
144
145 /* Return success or the error */
146 LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %lx\n", Port, *PortHandle);
147 return Status;
148 }
149
150 /* PUBLIC FUNCTIONS **********************************************************/
151
152 /*
153 * @implemented
154 */
155 NTSTATUS
156 NTAPI
157 NtCreatePort(OUT PHANDLE PortHandle,
158 IN POBJECT_ATTRIBUTES ObjectAttributes,
159 IN ULONG MaxConnectInfoLength,
160 IN ULONG MaxDataLength,
161 IN ULONG MaxPoolUsage)
162 {
163 PAGED_CODE();
164
165 /* Call the internal API */
166 return LpcpCreatePort(PortHandle,
167 ObjectAttributes,
168 MaxConnectInfoLength,
169 MaxDataLength,
170 MaxPoolUsage,
171 FALSE);
172 }
173
174 /*
175 * @implemented
176 */
177 NTSTATUS
178 NTAPI
179 NtCreateWaitablePort(OUT PHANDLE PortHandle,
180 IN POBJECT_ATTRIBUTES ObjectAttributes,
181 IN ULONG MaxConnectInfoLength,
182 IN ULONG MaxDataLength,
183 IN ULONG MaxPoolUsage)
184 {
185 PAGED_CODE();
186
187 /* Call the internal API */
188 return LpcpCreatePort(PortHandle,
189 ObjectAttributes,
190 MaxConnectInfoLength,
191 MaxDataLength,
192 MaxPoolUsage,
193 TRUE);
194 }
195
196 /* EOF */