* Sync up to trunk head (r65095).
[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 USHORT Length, MaximumLength;
222 PAGED_CODE();
223
224 Length = PipeName->Length;
225 MaximumLength = Length + sizeof(UNICODE_NULL);
226
227 if ((Length < sizeof(WCHAR)) || (MaximumLength < Length))
228 {
229 return STATUS_INVALID_PARAMETER;
230 }
231
232 RootPipe = FALSE;
233 if (PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
234 {
235 Length += sizeof(OBJ_NAME_PATH_SEPARATOR);
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 if (RootPipe)
266 {
267 NameBuffer[0] = OBJ_NAME_PATH_SEPARATOR;
268 RtlCopyMemory(NameBuffer + 1,
269 PipeName->Buffer,
270 PipeName->Length);
271 }
272 else
273 {
274 RtlCopyMemory(NameBuffer,
275 PipeName->Buffer,
276 PipeName->Length);
277 }
278
279 NameBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
280
281 Fcb->FullName.Length = Length;
282 Fcb->FullName.MaximumLength = MaximumLength;
283 Fcb->FullName.Buffer = NameBuffer;
284
285 Fcb->ShortName.MaximumLength = Length;
286 Fcb->ShortName.Length = Length - sizeof(OBJ_NAME_PATH_SEPARATOR);
287 Fcb->ShortName.Buffer = NameBuffer + 1;
288
289 if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
290 &Fcb->FullName,
291 &Fcb->PrefixTableEntry))
292 {
293 NpBugCheck(0, 0, 0);
294 }
295
296 Fcb->NamedPipeConfiguration = NamedPipeConfiguration;
297 Fcb->NamedPipeType = NamedPipeType;
298 *NewFcb = Fcb;
299 return STATUS_SUCCESS;
300 }
301
302 NTSTATUS
303 NTAPI
304 NpCreateCcb(IN PNP_FCB Fcb,
305 IN PFILE_OBJECT FileObject,
306 IN UCHAR State,
307 IN UCHAR ReadMode,
308 IN UCHAR CompletionMode,
309 IN ULONG InQuota,
310 IN ULONG OutQuota,
311 OUT PNP_CCB *NewCcb)
312 {
313 PNP_CCB Ccb;
314 PNP_NONPAGED_CCB CcbNonPaged;
315 NTSTATUS Status;
316 PAGED_CODE();
317
318 Ccb = ExAllocatePoolWithTag(PagedPool, sizeof(*Ccb), NPFS_CCB_TAG);
319 if (!Ccb) return STATUS_INSUFFICIENT_RESOURCES;
320
321 CcbNonPaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(*CcbNonPaged), NPFS_CCB_TAG);
322 if (!CcbNonPaged)
323 {
324 ExFreePool(Ccb);
325 return STATUS_INSUFFICIENT_RESOURCES;
326 }
327
328 RtlZeroMemory(CcbNonPaged, sizeof(*CcbNonPaged));
329 CcbNonPaged->NodeType = NPFS_NTC_NONPAGED_CCB;
330
331 RtlZeroMemory(Ccb, sizeof(*Ccb));
332 Ccb->NodeType = NPFS_NTC_CCB;
333 Ccb->NonPagedCcb = CcbNonPaged;
334 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
335 Ccb->Fcb = Fcb;
336 Ccb->NamedPipeState = State;
337 Ccb->ReadMode[FILE_PIPE_SERVER_END] = ReadMode;
338 Ccb->CompletionMode[FILE_PIPE_SERVER_END] = CompletionMode;
339
340 Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND], InQuota);
341 if (!NT_SUCCESS(Status))
342 {
343 ExFreePool(CcbNonPaged);
344 ExFreePool(Ccb);
345 return STATUS_INSUFFICIENT_RESOURCES;
346 }
347
348 Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], OutQuota);
349 if (!NT_SUCCESS(Status))
350 {
351 NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]);
352 ExFreePool(CcbNonPaged);
353 ExFreePool(Ccb);
354 return STATUS_INSUFFICIENT_RESOURCES;
355 }
356
357 InsertTailList(&Fcb->CcbList, &Ccb->CcbEntry);
358
359 Fcb->CurrentInstances++;
360 Fcb->ServerOpenCount++;
361 InitializeListHead(&Ccb->IrpList);
362 ExInitializeResourceLite(&Ccb->NonPagedCcb->Lock);
363 *NewCcb = Ccb;
364 return STATUS_SUCCESS;
365 }
366
367 /* EOF */