xref: /reactos/drivers/sac/driver/chanmgr.c (revision e4930be4)
1 /*
2  * PROJECT:     ReactOS Drivers
3  * LICENSE:     BSD - See COPYING.ARM in the top level directory
4  * FILE:        drivers/sac/driver/chanmgr.c
5  * PURPOSE:     Driver for the Server Administration Console (SAC) for EMS
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "sacdrv.h"
12 
13 /* GLOBALS ********************************************************************/
14 
15 SAC_CHANNEL_LOCK ChannelCreateLock;
16 BOOLEAN ChannelCreateEnabled;
17 PSAC_CHANNEL ChannelArray[SAC_MAX_CHANNELS];
18 LONG ChannelRefCount[SAC_MAX_CHANNELS];
19 LONG ChannelReaped[SAC_MAX_CHANNELS];
20 SAC_CHANNEL_LOCK ChannelSlotLock[SAC_MAX_CHANNELS];
21 
22 /* FUNCTIONS ******************************************************************/
23 
24 #define MAX_REF_COUNT 100
25 
26 #define CHANNEL_SLOT_IS_IN_USE(x)   (ChannelRefCount[(x)] > 0)
27 
28 FORCEINLINE
29 PSAC_CHANNEL
ChannelFromIndex(IN ULONG Index)30 ChannelFromIndex(IN ULONG Index)
31 {
32     return ChannelArray[Index];
33 }
34 
35 FORCEINLINE
36 LONG
ChannelGetReferenceCount(IN LONG Index)37 ChannelGetReferenceCount(IN LONG Index)
38 {
39     return ChannelRefCount[Index];
40 }
41 
42 FORCEINLINE
43 LONG
ChannelReferenceByIndex(IN LONG Index)44 ChannelReferenceByIndex(IN LONG Index)
45 {
46     if (ChannelGetReferenceCount(Index) > 0)
47     {
48         ASSERT(ChannelRefCount[Index] <= MAX_REF_COUNT);
49         ASSERT(ChannelRefCount[Index] >= 1);
50         _InterlockedIncrement(&ChannelRefCount[Index]);
51         ASSERT(ChannelRefCount[Index] <= MAX_REF_COUNT);
52         ASSERT(ChannelRefCount[Index] >= 2);
53     }
54 
55     return ChannelGetReferenceCount(Index);
56 }
57 
58 FORCEINLINE
59 LONG
ChannelReferenceByIndexWithLock(IN LONG Index)60 ChannelReferenceByIndexWithLock(IN LONG Index)
61 {
62     LONG RefCount;
63 
64     ChannelSlotLock(Index);
65     RefCount = ChannelReferenceByIndex(Index);
66     ChannelSlotUnlock(Index);
67     return RefCount;
68 }
69 
70 FORCEINLINE
71 LONG
ChannelDereferenceByIndex(IN LONG Index)72 ChannelDereferenceByIndex(IN LONG Index)
73 {
74     ASSERT(ChannelGetReferenceCount(Index) <= MAX_REF_COUNT);
75     ASSERT(ChannelGetReferenceCount(Index) > 1);
76     _InterlockedDecrement(&ChannelRefCount[Index]);
77     ASSERT(ChannelGetReferenceCount(Index) >= 1);
78     return ChannelGetReferenceCount(Index);
79 }
80 
81 FORCEINLINE
82 VOID
ChannelDereferenceByIndexWithLock(IN LONG Index)83 ChannelDereferenceByIndexWithLock(IN LONG Index)
84 {
85     ChannelSlotLock(Index);
86     ChannelDereferenceByIndex(Index);
87     ChannelSlotUnlock(Index);
88 }
89 
90 FORCEINLINE
91 VOID
ChannelDereferenceToZeroByIndex(IN LONG Index)92 ChannelDereferenceToZeroByIndex(IN LONG Index)
93 {
94     ASSERT(ChannelGetReferenceCount(Index) == 1);
95     ASSERT(ChannelIsActive(ChannelFromIndex(Index)) == FALSE);
96     _InterlockedExchange(&ChannelRefCount[Index], 0);
97 }
98 
99 FORCEINLINE
100 VOID
ChannelReferenceToOneByIndex(IN LONG Index)101 ChannelReferenceToOneByIndex(IN LONG Index)
102 {
103     ASSERT(ChannelGetReferenceCount(Index) == 0);
104     _InterlockedExchange(&ChannelRefCount[Index], 1);
105 }
106 
107 FORCEINLINE
108 VOID
ChannelReferenceToOneByIndexWithLock(IN LONG Index)109 ChannelReferenceToOneByIndexWithLock(IN LONG Index)
110 {
111     ChannelSlotLock(Index);
112     ChannelReferenceToOneByIndex(Index);
113     ChannelSlotUnlock(Index);
114 }
115 
116 NTSTATUS
117 NTAPI
ChanMgrInitialize(VOID)118 ChanMgrInitialize(VOID)
119 {
120     ULONG i;
121 
122     /* Initialize the channel lock */
123     SacInitializeLock(&ChannelCreateLock);
124     ChannelCreateEnabled = TRUE;
125 
126     /* Loop through the channel arrays */
127     for (i = 0; i < SAC_MAX_CHANNELS; i++)
128     {
129         /* Clear and initialize their locks */
130         ChannelArray[i] = NULL;
131         SacInitializeLock(&ChannelSlotLock[i]);
132 
133         /* Clear their statuses and reference counts */
134         _InterlockedExchange(&ChannelRefCount[i], 0);
135         _InterlockedExchange(&ChannelReaped[i], 1);
136     }
137 
138     /* All good */
139     return STATUS_SUCCESS;
140 }
141 
142 NTSTATUS
143 NTAPI
ChanMgrShutdown(VOID)144 ChanMgrShutdown(VOID)
145 {
146     /* FIXME: TODO */
147     return STATUS_NOT_IMPLEMENTED;
148 }
149 
150 NTSTATUS
151 NTAPI
ChanMgrGetChannelByName(IN PWCHAR Name,OUT PSAC_CHANNEL * Channel)152 ChanMgrGetChannelByName(IN PWCHAR Name,
153                         OUT PSAC_CHANNEL* Channel)
154 {
155     NTSTATUS Status, Status1;
156     ULONG i;
157     PSAC_CHANNEL CurrentChannel;
158     PWCHAR ChannelName;
159     BOOLEAN Found;
160     CHECK_PARAMETER1(Name);
161     CHECK_PARAMETER2(Channel);
162 
163     /* Assume failure */
164     *Channel = NULL;
165     Status = STATUS_NOT_FOUND;
166 
167     /* Loop through all channels */
168     for (i = 0; i < SAC_MAX_CHANNELS; i++)
169     {
170         /* Reference this one and check if it's valid */
171         if (ChannelReferenceByIndexWithLock(i) > 0)
172         {
173             /* All good, grab it */
174             CurrentChannel = ChannelFromIndex(i);
175             ASSERT(CurrentChannel != NULL);
176 
177             /* Get its name */
178             Status1 = ChannelGetName(CurrentChannel, &ChannelName);
179             ASSERT(NT_SUCCESS(Status1));
180 
181             /* Check if this is the name that was passed in */
182             Found = _wcsicmp(Name, ChannelName);
183             SacFreePool(ChannelName);
184             if (Found)
185             {
186                 /* We found it, return it (with a reference held) */
187                 *Channel = CurrentChannel;
188                 return STATUS_SUCCESS;
189             }
190 
191             /* Not the one we want, dereference this one and keep going */
192             ChannelDereferenceByIndexWithLock(i);
193         }
194     }
195 
196     /* No channels with this name were found */
197     return Status;
198 }
199 
200 NTSTATUS
201 NTAPI
ChanMgrGetByHandle(IN SAC_CHANNEL_ID ChannelId,OUT PSAC_CHANNEL * TargetChannel)202 ChanMgrGetByHandle(IN SAC_CHANNEL_ID ChannelId,
203                    OUT PSAC_CHANNEL* TargetChannel)
204 {
205     NTSTATUS Status;
206     ULONG i;
207     PSAC_CHANNEL Channel;
208     CHECK_PARAMETER2(TargetChannel);
209 
210     /* Assume failure */
211     *TargetChannel = NULL;
212     Status = STATUS_NOT_FOUND;
213 
214     /* Loop through all channels */
215     for (i = 0; i < SAC_MAX_CHANNELS; i++)
216     {
217         /* Reference this one and check if it's valid */
218         if (ChannelReferenceByIndexWithLock(i) > 0)
219         {
220             /* All good, grab it */
221             Channel = ChannelFromIndex(i);
222             ASSERT(Channel != NULL);
223 
224             /* Check if the channel ID matches */
225             if (ChannelIsEqual(Channel, &ChannelId))
226             {
227                 /* We found it, return it (with a reference held) */
228                 *TargetChannel = Channel;
229                 return STATUS_SUCCESS;
230             }
231 
232             /* Not the one we want, dereference this one and keep going */
233             ChannelDereferenceByIndexWithLock(i);
234         }
235     }
236 
237     /* No channels with this ID were found */
238     return Status;
239 }
240 
241 NTSTATUS
242 NTAPI
ChanMgrReleaseChannel(IN PSAC_CHANNEL Channel)243 ChanMgrReleaseChannel(IN PSAC_CHANNEL Channel)
244 {
245     LONG Index;
246     ULONG RefCount;
247     PSAC_CHANNEL ThisChannel;
248     CHECK_PARAMETER(Channel);
249 
250     /* Get the index of the channel */
251     Index = ChannelGetIndex(Channel);
252 
253     /* Drop a reference -- there should still be at least the keepalive left */
254     ChannelSlotLock(Index);
255     RefCount = ChannelDereferenceByIndex(Index);
256     ASSERT(RefCount > 0);
257 
258     /* Do we only have the keep-alive left, and the channel is dead? */
259     if ((RefCount == 1) && !(ChannelIsActive(Channel)))
260     {
261         /* Check if the ??? flag is set, or if there's no output data */
262         ThisChannel = ChannelFromIndex(Index);
263         if (!(ThisChannel->Flags & 1))
264         {
265             /* Nope, we can wipe the references and get rid of it */
266             ChannelDereferenceToZeroByIndex(Index);
267         }
268         else if (!ThisChannel->ChannelHasNewOBufferData)
269         {
270             /* No data, we can wipe the references and get rid of it */
271             ChannelDereferenceToZeroByIndex(Index);
272         }
273     }
274 
275     /* We're done, we can unlock the slot now */
276     ChannelSlotUnlock(Index);
277     return STATUS_SUCCESS;
278 }
279 
280 BOOLEAN
281 NTAPI
ChanMgrIsUniqueName(IN PWCHAR ChannelName)282 ChanMgrIsUniqueName(IN PWCHAR ChannelName)
283 {
284     NTSTATUS Status;
285     BOOLEAN IsUnique = FALSE;
286     PSAC_CHANNEL Channel;
287 
288     /* Check if a channel with this name already exists */
289     Status = ChanMgrGetChannelByName(ChannelName, &Channel);
290     if (Status == STATUS_NOT_FOUND) IsUnique = TRUE;
291 
292     /* If one did, dereference it, all we wanted was to check uniqueness */
293     if (NT_SUCCESS(Status)) ChanMgrReleaseChannel(Channel);
294 
295     /* Return if one was found or not */
296     return IsUnique;
297 }
298 
299 NTSTATUS
300 NTAPI
ChanMgrReapChannel(IN ULONG ChannelIndex)301 ChanMgrReapChannel(IN ULONG ChannelIndex)
302 {
303     /* FIXME: TODO */
304     return STATUS_NOT_IMPLEMENTED;
305 }
306 
307 NTSTATUS
308 NTAPI
ChanMgrReapChannels(VOID)309 ChanMgrReapChannels(VOID)
310 {
311     ULONG i;
312     NTSTATUS Status = STATUS_SUCCESS;
313 
314     /* Loop all the channels */
315     for (i = 0; i < SAC_MAX_CHANNELS; i++)
316     {
317         /* Lock this index and see if the channel was reaped */
318         ChannelSlotLock(i);
319         if (!ChannelReaped[i])
320         {
321             /* It was not reaped yet, so a channel should still be here */
322             ASSERT(ChannelFromIndex(i) != NULL);
323             if (ChannelGetReferenceCount(i) <= 0)
324             {
325                 /* The channel has no more references, so clear the buffer flags */
326                 _InterlockedExchange(&ChannelArray[i]->ChannelHasNewIBufferData, 0);
327                 _InterlockedExchange(&ChannelArray[i]->ChannelHasNewOBufferData, 0);
328 
329                 /* And reap it */
330                 Status = ChanMgrReapChannel(i);
331             }
332         }
333 
334         /* Release the lock, and move on unless reaping failed */
335         ChannelSlotUnlock(i);
336         if (!NT_SUCCESS(Status)) break;
337     }
338 
339     /* Return reaping status */
340     return Status;
341 }
342 
343 NTSTATUS
344 NTAPI
ChanMgrCreateChannel(OUT PSAC_CHANNEL * Channel,IN PSAC_CHANNEL_ATTRIBUTES Attributes)345 ChanMgrCreateChannel(OUT PSAC_CHANNEL *Channel,
346                      IN PSAC_CHANNEL_ATTRIBUTES Attributes)
347 {
348     NTSTATUS Status;
349     PSAC_CHANNEL NewChannel;
350     SAC_CHANNEL_ID ChanId;
351     ULONG i;
352     CHECK_PARAMETER(Channel);
353     CHECK_PARAMETER2(Attributes);
354 
355     /* No other channel create attempts can happen */
356     ChannelLockCreates();
357 
358     /* Is the channel manager initialized? */
359     if (!ChannelCreateEnabled)
360     {
361         /* Nope, bail out */
362         Status = STATUS_UNSUCCESSFUL;
363         goto ReturnStatus;
364     }
365 
366     /* Reap any zombie channels */
367     Status = ChanMgrReapChannels();
368     if (!NT_SUCCESS(Status))
369     {
370         /* Bail out on error */
371         Status = STATUS_UNSUCCESSFUL;
372         goto ReturnStatus;
373     }
374 
375     /* Check if we already have a channel with this name */
376     if (!ChanMgrIsUniqueName(Attributes->NameBuffer))
377     {
378         /* We do, fail */
379         Status = STATUS_DUPLICATE_NAME;
380         goto ReturnStatus;
381     }
382 
383     /* Allocate this channel */
384     NewChannel = SacAllocatePool(sizeof(SAC_CHANNEL), CHANNEL_BLOCK_TAG);
385     CHECK_PARAMETER_WITH_STATUS(NewChannel, STATUS_NO_MEMORY); // bug
386     RtlZeroMemory(NewChannel, sizeof(SAC_CHANNEL));
387 
388     /* Loop channel slots */
389     for (i = 0; i < SAC_MAX_CHANNELS; i++)
390     {
391         /* Find a free spot for it */
392         if (ChannelReaped[i])
393         {
394             /* Free slot found, attempt to use it */
395             ASSERT(!CHANNEL_SLOT_IS_IN_USE(i));
396             InterlockedCompareExchangePointer((PVOID*)&ChannelArray[i], NewChannel, NULL);
397             if (ChannelArray[i] == NewChannel) break;
398         }
399     }
400 
401     /* Did we not find a single free slot? */
402     if (i == SAC_MAX_CHANNELS)
403     {
404         /* Bail out */
405         goto ReturnStatus;
406     }
407 
408     /* Create an ID for this channel */
409     RtlZeroMemory(&ChanId, sizeof(ChanId));
410     Status = ExUuidCreate(&ChanId.ChannelGuid);
411     if (!NT_SUCCESS(Status))
412     {
413         /* Bail out if we couldn't */
414         SAC_DBG(SAC_DBG_INIT, "SAC Create Channel :: Failed to get GUID\n");
415         goto ReturnStatus;
416     }
417 
418     /* Now create the channel proper */
419     Status = ChannelCreate(NewChannel, Attributes, ChanId);
420     if (NT_SUCCESS(Status))
421     {
422         /* Set the channel index */
423         _InterlockedExchange(&NewChannel->Index, i);
424 
425         /* Add the initial reference to the channel */
426         ChannelReferenceToOneByIndexWithLock(i);
427 
428         /* Return it to the caller */
429         *Channel = NewChannel;
430 
431         /* This slot is now occupied */
432         ASSERT(ChannelReaped[i] == 1);
433         _InterlockedExchange(&ChannelReaped[i], 0);
434     }
435     else
436     {
437         /* We couldn't create it, free the buffer */
438         SacFreePool(NewChannel);
439     }
440 
441 ReturnStatus:
442     /* Return whatever the operation status was */
443     ChannelUnlockCreates();
444     return Status;
445 }
446 
447 NTSTATUS
448 NTAPI
ChanMgrGetByHandleAndFileObject(IN SAC_CHANNEL_ID ChannelId,IN PFILE_OBJECT FileObject,OUT PSAC_CHANNEL * TargetChannel)449 ChanMgrGetByHandleAndFileObject(IN SAC_CHANNEL_ID ChannelId,
450                                 IN PFILE_OBJECT FileObject,
451                                 OUT PSAC_CHANNEL* TargetChannel)
452 {
453     NTSTATUS Status;
454     PSAC_CHANNEL FoundChannel;
455 
456     /* Lookup the channel by ID first */
457     Status = ChanMgrGetByHandle(ChannelId, &FoundChannel);
458     if (NT_SUCCESS(Status))
459     {
460         /* We found it, now check if the file object matches */
461         if (FoundChannel->FileObject == FileObject)
462         {
463             /* Yep, return success */
464             *TargetChannel = FoundChannel;
465         }
466         else
467         {
468             /* Nope, drop the reference on the channel */
469             ChanMgrReleaseChannel(FoundChannel);
470 
471             /* And return failure */
472             *TargetChannel = NULL;
473             Status = STATUS_NOT_FOUND;
474         }
475     }
476 
477     /* Return if we found it or not */
478     return Status;
479 }
480 
481 NTSTATUS
482 NTAPI
ChanMgrGetChannelIndex(IN PSAC_CHANNEL Channel,IN PLONG ChannelIndex)483 ChanMgrGetChannelIndex(IN PSAC_CHANNEL Channel,
484                        IN PLONG ChannelIndex)
485 {
486     CHECK_PARAMETER1(Channel);
487     CHECK_PARAMETER2(ChannelIndex);
488 
489     /* Just return the index of the channel */
490     *ChannelIndex = ChannelGetIndex(Channel);
491     return STATUS_SUCCESS;
492 }
493 
494 NTSTATUS
495 NTAPI
ChanMgrGetByIndex(IN LONG TargetIndex,IN PSAC_CHANNEL * TargetChannel)496 ChanMgrGetByIndex(IN LONG TargetIndex,
497                   IN PSAC_CHANNEL* TargetChannel)
498 {
499     NTSTATUS Status;
500     CHECK_PARAMETER1(TargetIndex < SAC_MAX_CHANNELS);
501     CHECK_PARAMETER2(TargetChannel);
502 
503     /* Assume failure */
504     *TargetChannel = NULL;
505     Status = STATUS_NOT_FOUND;
506 
507     /* Reference this one and check if it's valid */
508     if (ChannelReferenceByIndexWithLock(TargetIndex) > 0)
509     {
510         /* We found it, return it (with a reference held) */
511         *TargetChannel = ChannelFromIndex(TargetIndex);
512         return STATUS_SUCCESS;
513     }
514 
515     /* No channels with this ID were found */
516     return Status;
517 }
518 
519 NTSTATUS
520 NTAPI
ChanMgrGetNextActiveChannel(IN PSAC_CHANNEL CurrentChannel,IN PULONG TargetIndex,OUT PSAC_CHANNEL * TargetChannel)521 ChanMgrGetNextActiveChannel(IN PSAC_CHANNEL CurrentChannel,
522                             IN PULONG TargetIndex,
523                             OUT PSAC_CHANNEL *TargetChannel)
524 {
525     NTSTATUS Status;
526     ULONG i;
527     LONG ChannelIndex, StartIndex;
528     PSAC_CHANNEL FoundChannel;
529     BOOLEAN ChannelFound;
530     CHECK_PARAMETER1(CurrentChannel);
531     CHECK_PARAMETER2(TargetIndex);
532     CHECK_PARAMETER3(TargetChannel);
533 
534     /* Get the current channel index */
535     Status = ChanMgrGetChannelIndex(CurrentChannel, &ChannelIndex);
536     if (!NT_SUCCESS(Status)) return Status;
537 
538     /* Assume failure */
539     ChannelFound = FALSE;
540 
541     /* Loop through all the possible active channels */
542     StartIndex = (ChannelIndex + 1) % SAC_MAX_CHANNELS;
543     for (i = StartIndex; i != StartIndex; i = (i + 1) % SAC_MAX_CHANNELS)
544     {
545         /* Get the channel and see if it exists*/
546         Status = ChanMgrGetByIndex(i, &FoundChannel);
547         if (Status != STATUS_NOT_FOUND)
548         {
549             /* Bail out if we failed for some reason */
550             if (!NT_SUCCESS(Status)) return Status;
551 
552             /* It exists -- is it active? Or, does it have output data? */
553             if ((ChannelIsActive(FoundChannel)) ||
554                 (!(ChannelIsActive(FoundChannel)) &&
555                   (FoundChannel->ChannelHasNewOBufferData)))
556             {
557                 /* It's active or has output data, return with it */
558                 ChannelFound = TRUE;
559                 break;
560             }
561 
562             /* Drop the reference on this channel and try the next one */
563             Status = ChanMgrReleaseChannel(FoundChannel);
564             if (!NT_SUCCESS(Status)) return Status;
565         }
566     }
567 
568     /* Check if we successfully found a channel */
569     if ((NT_SUCCESS(Status)) && (ChannelFound))
570     {
571         /* Return it and its indexed. Remember we still hold the reference */
572         *TargetIndex = i;
573         *TargetChannel = FoundChannel;
574     }
575 
576     /* All done */
577     return Status;
578 }
579 
580 NTSTATUS
581 NTAPI
ChanMgrChannelDestroy(IN PSAC_CHANNEL Channel)582 ChanMgrChannelDestroy(IN PSAC_CHANNEL Channel)
583 {
584     CHECK_PARAMETER1(Channel);
585     CHECK_PARAMETER(ChannelGetReferenceCount(Channel->Index) > 0);
586 
587     /* Destroy the channel */
588     return Channel->ChannelDestroy(Channel);
589 }
590 
591 NTSTATUS
592 NTAPI
ChanMgrCloseChannel(IN PSAC_CHANNEL Channel)593 ChanMgrCloseChannel(IN PSAC_CHANNEL Channel)
594 {
595     NTSTATUS Status;
596     CHECK_PARAMETER(Channel);
597 
598     /* Check if the channel is active */
599     if (ChannelIsActive(Channel))
600     {
601         /* Yep, close it */
602         Status = ChannelClose(Channel);
603     }
604     else
605     {
606         /* Nothing to do */
607         Status = STATUS_ALREADY_DISCONNECTED;
608     }
609 
610     /* Handle the channel close */
611     ConMgrHandleEvent(TRUE, Channel, &Status);
612     return Status;
613 }
614 
615 NTSTATUS
616 NTAPI
ChanMgrGetChannelCount(OUT PULONG ChannelCount)617 ChanMgrGetChannelCount(OUT PULONG ChannelCount)
618 {
619     ULONG i;
620     PSAC_CHANNEL Channel;
621     NTSTATUS Status;
622     CHECK_PARAMETER(ChannelCount);
623 
624     /* Assume no channels */
625     *ChannelCount = 0;
626 
627     /* Loop every channel */
628     for (i = 0; i < SAC_MAX_CHANNELS; i++)
629     {
630         /* See if this one exists */
631         Status = ChanMgrGetByIndex(i, &Channel);
632         if (Status != STATUS_NOT_FOUND)
633         {
634             /* Sanity checks*/
635             ASSERT(NT_SUCCESS(Status));
636             ASSERT(Channel != NULL);
637 
638             /* It exists -- is it active? Or, does it have output data? */
639             if ((ChannelIsActive(Channel)) ||
640                 (!(ChannelIsActive(Channel)) &&
641                  (Channel->ChannelHasNewOBufferData)))
642             {
643                 /* It's active or has output data, increase the count */
644                 ++*ChannelCount;
645                 break;
646             }
647 
648             /* Drop the reference on this channel and try the next one */
649             Status = ChanMgrReleaseChannel(Channel);
650             if (!NT_SUCCESS(Status)) return Status;
651         }
652         else
653         {
654             /* Channel doesn't exist, nothing wrong with that, keep going */
655             Status = STATUS_SUCCESS;
656         }
657     }
658 
659     /* We should always succeed if we get here */
660     ASSERT(NT_SUCCESS(Status));
661     return Status;
662 }
663 
664 NTSTATUS
665 NTAPI
ChanMgrIsFull(OUT PBOOLEAN IsFull)666 ChanMgrIsFull(OUT PBOOLEAN IsFull)
667 {
668     NTSTATUS Status;
669     ULONG Count;
670 
671     /* Count the channels */
672     Status = ChanMgrGetChannelCount(&Count);
673     CHECK_PARAMETER(Status == STATUS_SUCCESS);
674 
675     /* Return if we hit the limit */
676     *IsFull = (Count == SAC_MAX_CHANNELS);
677     return Status;
678 }
679 
680 NTSTATUS
681 NTAPI
ChanMgrCloseChannelsWithFileObject(IN PFILE_OBJECT FileObject)682 ChanMgrCloseChannelsWithFileObject(IN PFILE_OBJECT FileObject)
683 {
684     PSAC_CHANNEL Channel;
685     ULONG i;
686     NTSTATUS Status;
687     CHECK_PARAMETER1(FileObject);
688 
689     /* Loop all channels */
690     for (i = 0; i < SAC_MAX_CHANNELS; i++)
691     {
692         /* Try to get this one */
693         Status = ChanMgrGetByIndex(i, &Channel);
694         if (!NT_SUCCESS(Status)) break;
695 
696         /* Check if the FO matches, if so, close the channel */
697         if (Channel->FileObject == FileObject) ChanMgrCloseChannel(Channel);
698 
699         /* Drop the reference and try the next channel(s) */
700         Status = ChanMgrReleaseChannel(Channel);
701         if (!NT_SUCCESS(Status)) break;
702     }
703 
704     /* All done */
705     return Status;
706 }
707 
708 NTSTATUS
709 NTAPI
ChanMgrGenerateUniqueCmdName(IN PWCHAR ChannelName)710 ChanMgrGenerateUniqueCmdName(IN PWCHAR ChannelName)
711 {
712     return STATUS_NOT_IMPLEMENTED;
713 }
714