Sync to trunk revision 63922.
[reactos.git] / drivers / filesystems / npfs / strucsup.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/strucsup.c
5 * PURPOSE:
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_STRUCSUP)
15
16 /* GLOBALS ********************************************************************/
17
18 PWCHAR NpRootDCBName = L"\\";
19 PNP_VCB NpVcb;
20
21 /* FUNCTIONS ******************************************************************/
22
23 RTL_GENERIC_COMPARE_RESULTS
24 NTAPI
25 NpEventTableCompareRoutine(IN PRTL_GENERIC_TABLE Table,
26 IN PVOID FirstStruct,
27 IN PVOID SecondStruct)
28 {
29 UNIMPLEMENTED;
30 return GenericEqual;
31 }
32
33 PVOID
34 NTAPI
35 NpEventTableAllocate(IN PRTL_GENERIC_TABLE Table,
36 IN CLONG ByteSize)
37 {
38 UNIMPLEMENTED;
39 return NULL;
40 }
41
42 VOID
43 NTAPI
44 NpEventTableDeallocate(IN PRTL_GENERIC_TABLE Table,
45 IN PVOID Buffer)
46 {
47 UNIMPLEMENTED;
48 }
49
50 BOOLEAN
51 NTAPI
52 NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
53 IN PVOID Buffer)
54 {
55 if (!Buffer) return FALSE;
56
57 ObDereferenceObject(((PNP_EVENT_BUFFER)Buffer)->Event);
58 return RtlDeleteElementGenericTable(Table, Buffer);
59 }
60
61 VOID
62 NTAPI
63 NpDeleteFcb(IN PNP_FCB Fcb,
64 IN PLIST_ENTRY ListEntry)
65 {
66 PNP_DCB Dcb;
67 PAGED_CODE();
68
69 Dcb = Fcb->ParentDcb;
70 if (Fcb->CurrentInstances) NpBugCheck(0, 0, 0);
71
72 NpCancelWaiter(&NpVcb->WaitQueue,
73 &Fcb->FullName,
74 STATUS_OBJECT_NAME_NOT_FOUND,
75 ListEntry);
76
77 RemoveEntryList(&Fcb->DcbEntry);
78
79 if (Fcb->SecurityDescriptor)
80 {
81 ObDereferenceSecurityDescriptor(Fcb->SecurityDescriptor, 1);
82 }
83
84 RtlRemoveUnicodePrefix(&NpVcb->PrefixTable, &Fcb->PrefixTableEntry);
85 ExFreePool(Fcb->FullName.Buffer);
86 ExFreePool(Fcb);
87 NpCheckForNotify(Dcb, TRUE, ListEntry);
88 }
89
90 VOID
91 NTAPI
92 NpDeleteCcb(IN PNP_CCB Ccb,
93 IN PLIST_ENTRY ListEntry)
94 {
95 PNP_ROOT_DCB_FCB RootDcbCcb;
96 PAGED_CODE();
97
98 RootDcbCcb = (PNP_ROOT_DCB_FCB)Ccb;
99 if (Ccb->NodeType == NPFS_NTC_CCB)
100 {
101 RemoveEntryList(&Ccb->CcbEntry);
102 --Ccb->Fcb->CurrentInstances;
103
104 NpDeleteEventTableEntry(&NpVcb->EventTable,
105 Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END]);
106 NpDeleteEventTableEntry(&NpVcb->EventTable,
107 Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_SERVER_END]);
108 NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]);
109 NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND]);
110 NpCheckForNotify(Ccb->Fcb->ParentDcb, FALSE, ListEntry);
111 ExDeleteResourceLite(&Ccb->NonPagedCcb->Lock);
112 NpUninitializeSecurity(Ccb);
113 if (Ccb->ClientSession)
114 {
115 ExFreePool(Ccb->ClientSession);
116 Ccb->ClientSession = NULL;
117 }
118 ExFreePool(Ccb->NonPagedCcb);
119 }
120 else if (RootDcbCcb->NodeType == NPFS_NTC_ROOT_DCB_CCB && RootDcbCcb->Unknown)
121 {
122 ExFreePool(RootDcbCcb->Unknown);
123 }
124
125 ExFreePool(Ccb);
126 }
127
128 VOID
129 NTAPI
130 NpInitializeVcb(VOID)
131 {
132 PAGED_CODE();
133
134 RtlZeroMemory(NpVcb, sizeof(*NpVcb));
135
136 NpVcb->NodeType = NPFS_NTC_VCB;
137 RtlInitializeUnicodePrefix(&NpVcb->PrefixTable);
138 ExInitializeResourceLite(&NpVcb->Lock);
139 RtlInitializeGenericTable(&NpVcb->EventTable,
140 NpEventTableCompareRoutine,
141 NpEventTableAllocate,
142 NpEventTableDeallocate,
143 0);
144 NpInitializeWaitQueue(&NpVcb->WaitQueue);
145 }
146
147 NTSTATUS
148 NTAPI
149 NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb)
150 {
151 PNP_ROOT_DCB_FCB RootCcb;
152 PAGED_CODE();
153
154 RootCcb = ExAllocatePoolWithTag(PagedPool, sizeof(*RootCcb), NPFS_ROOT_DCB_CCB_TAG);
155 if (!RootCcb) return STATUS_INSUFFICIENT_RESOURCES;
156
157 RtlZeroMemory(RootCcb, sizeof(*RootCcb));
158 RootCcb->NodeType = NPFS_NTC_ROOT_DCB_CCB;
159 *NewRootCcb = RootCcb;
160 return STATUS_SUCCESS;
161 }
162
163 NTSTATUS
164 NTAPI
165 NpCreateRootDcb(VOID)
166 {
167 PNP_DCB Dcb;
168 PAGED_CODE();
169
170 if (NpVcb->RootDcb)
171 {
172 NpBugCheck(0, 0, 0);
173 }
174
175 NpVcb->RootDcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Dcb), NPFS_DCB_TAG);
176 if (!NpVcb->RootDcb)
177 {
178 return STATUS_INSUFFICIENT_RESOURCES;
179 }
180
181 Dcb = NpVcb->RootDcb;
182 RtlZeroMemory(Dcb, sizeof(*Dcb));
183 Dcb->NodeType = NPFS_NTC_ROOT_DCB;
184
185 InitializeListHead(&Dcb->DcbEntry);
186 InitializeListHead(&Dcb->NotifyList);
187 InitializeListHead(&Dcb->NotifyList2);
188 InitializeListHead(&Dcb->FcbList);
189
190 Dcb->FullName.Buffer = NpRootDCBName;
191 Dcb->FullName.Length = 2;
192 Dcb->FullName.MaximumLength = 4;
193
194 Dcb->ShortName.Length = Dcb->FullName.Length;
195 Dcb->ShortName.MaximumLength = Dcb->FullName.MaximumLength;
196 Dcb->ShortName.Buffer = Dcb->FullName.Buffer;
197
198 if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
199 &Dcb->FullName,
200 &Dcb->PrefixTableEntry))
201 {
202 NpBugCheck(0, 0, 0);
203 }
204
205 return STATUS_SUCCESS;
206 }
207
208 NTSTATUS
209 NTAPI
210 NpCreateFcb(IN PNP_DCB Dcb,
211 IN PUNICODE_STRING PipeName,
212 IN ULONG MaximumInstances,
213 IN LARGE_INTEGER Timeout,
214 IN USHORT NamedPipeConfiguration,
215 IN USHORT NamedPipeType,
216 OUT PNP_FCB *NewFcb)
217 {
218 PNP_FCB Fcb;
219 BOOLEAN RootPipe;
220 PWCHAR NameBuffer;
221 ULONG BufferOffset;
222 USHORT Length, MaximumLength;
223 PAGED_CODE();
224
225 Length = PipeName->Length;
226 MaximumLength = Length + sizeof(UNICODE_NULL);
227
228 if ((Length < sizeof(WCHAR)) || (MaximumLength < Length))
229 {
230 return STATUS_INVALID_PARAMETER;
231 }
232
233 RootPipe = FALSE;
234 if (PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
235 {
236 MaximumLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
237 RootPipe = TRUE;
238 if (MaximumLength < sizeof(WCHAR))
239 {
240 return STATUS_INVALID_PARAMETER;
241 }
242 }
243
244 Fcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Fcb), NPFS_FCB_TAG);
245 if (!Fcb) return STATUS_INSUFFICIENT_RESOURCES;
246
247 RtlZeroMemory(Fcb, sizeof(*Fcb));
248 Fcb->MaximumInstances = MaximumInstances;
249 Fcb->Timeout = Timeout;
250 Fcb->NodeType = NPFS_NTC_FCB;
251 Fcb->ParentDcb = Dcb;
252 InitializeListHead(&Fcb->CcbList);
253
254 NameBuffer = ExAllocatePoolWithTag(PagedPool,
255 MaximumLength,
256 NPFS_NAME_BLOCK_TAG);
257 if (!NameBuffer)
258 {
259 ExFreePool(Fcb);
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262
263 InsertTailList(&Dcb->FcbList, &Fcb->DcbEntry);
264
265 BufferOffset = 0;
266 if (RootPipe)
267 {
268 NameBuffer[0] = OBJ_NAME_PATH_SEPARATOR;
269 BufferOffset = 1;
270 }
271
272 RtlCopyMemory(NameBuffer + BufferOffset, PipeName->Buffer, Length);
273 NameBuffer[BufferOffset + (Length / sizeof(WCHAR))] = UNICODE_NULL;
274
275 Fcb->FullName.Length = Length;
276 Fcb->FullName.MaximumLength = MaximumLength;
277 Fcb->FullName.Buffer = NameBuffer;
278
279 Fcb->ShortName.MaximumLength = Length;
280 Fcb->ShortName.Length = Length - sizeof(OBJ_NAME_PATH_SEPARATOR);
281 Fcb->ShortName.Buffer = NameBuffer + 1;
282
283 if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
284 &Fcb->FullName,
285 &Fcb->PrefixTableEntry))
286 {
287 NpBugCheck(0, 0, 0);
288 }
289
290 Fcb->NamedPipeConfiguration = NamedPipeConfiguration;
291 Fcb->NamedPipeType = NamedPipeType;
292 *NewFcb = Fcb;
293 return STATUS_SUCCESS;
294 }
295
296 NTSTATUS
297 NTAPI
298 NpCreateCcb(IN PNP_FCB Fcb,
299 IN PFILE_OBJECT FileObject,
300 IN UCHAR State,
301 IN UCHAR ReadMode,
302 IN UCHAR CompletionMode,
303 IN ULONG InQuota,
304 IN ULONG OutQuota,
305 OUT PNP_CCB *NewCcb)
306 {
307 PNP_CCB Ccb;
308 PNP_NONPAGED_CCB CcbNonPaged;
309 NTSTATUS Status;
310 PAGED_CODE();
311
312 Ccb = ExAllocatePoolWithTag(PagedPool, sizeof(*Ccb), NPFS_CCB_TAG);
313 if (!Ccb) return STATUS_INSUFFICIENT_RESOURCES;
314
315 CcbNonPaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(*CcbNonPaged), NPFS_CCB_TAG);
316 if (!CcbNonPaged)
317 {
318 ExFreePool(Ccb);
319 return STATUS_INSUFFICIENT_RESOURCES;
320 }
321
322 RtlZeroMemory(CcbNonPaged, sizeof(*CcbNonPaged));
323 CcbNonPaged->NodeType = NPFS_NTC_NONPAGED_CCB;
324
325 RtlZeroMemory(Ccb, sizeof(*Ccb));
326 Ccb->NodeType = NPFS_NTC_CCB;
327 Ccb->NonPagedCcb = CcbNonPaged;
328 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
329 Ccb->Fcb = Fcb;
330 Ccb->NamedPipeState = State;
331 Ccb->ReadMode[FILE_PIPE_SERVER_END] = ReadMode;
332 Ccb->CompletionMode[FILE_PIPE_SERVER_END] = CompletionMode;
333
334 Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND], InQuota);
335 if (!NT_SUCCESS(Status))
336 {
337 ExFreePool(CcbNonPaged);
338 ExFreePool(Ccb);
339 return STATUS_INSUFFICIENT_RESOURCES;
340 }
341
342 Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], OutQuota);
343 if (!NT_SUCCESS(Status))
344 {
345 NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]);
346 ExFreePool(CcbNonPaged);
347 ExFreePool(Ccb);
348 return STATUS_INSUFFICIENT_RESOURCES;
349 }
350
351 InsertTailList(&Fcb->CcbList, &Ccb->CcbEntry);
352
353 Fcb->CurrentInstances++;
354 Fcb->ServerOpenCount++;
355 InitializeListHead(&Ccb->IrpList);
356 ExInitializeResourceLite(&Ccb->NonPagedCcb->Lock);
357 *NewCcb = Ccb;
358 return STATUS_SUCCESS;
359 }
360
361 /* EOF */