2 * PROJECT: ReactOS Drivers
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/sac/driver/channel.c
5 * PURPOSE: Driver for the Server Administration Console (SAC) for EMS
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 /* FUNCTIONS ******************************************************************/
17 ChannelIsValidType(IN SAC_CHANNEL_TYPE ChannelType
)
19 /* Check if the type is valid */
20 return ((ChannelType
>= VtUtf8
) && (ChannelType
<= Raw
));
25 ChannelIsEqual(IN PSAC_CHANNEL Channel
,
26 IN PSAC_CHANNEL_ID ChannelId
)
28 /* Check if the GUIDs match */
29 return IsEqualGUIDAligned(&Channel
->ChannelId
.ChannelGuid
,
30 &ChannelId
->ChannelGuid
);
35 ChannelDereferenceHandles(IN PSAC_CHANNEL Channel
)
37 CHECK_PARAMETER(Channel
);
39 /* Clear the data event */
40 if (Channel
->HasNewDataEvent
)
42 ChannelUninitializeEvent(Channel
,
44 SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT
);
47 /* Clear the close event */
48 if (Channel
->CloseEvent
)
50 ChannelUninitializeEvent(Channel
,
52 SAC_CHANNEL_FLAG_CLOSE_EVENT
);
55 /* Clear the lock event */
56 if (Channel
->LockEvent
)
58 ChannelUninitializeEvent(Channel
,
60 SAC_CHANNEL_FLAG_LOCK_EVENT
);
63 /* Clear the redraw event */
64 if (Channel
->RedrawEvent
)
66 ChannelUninitializeEvent(Channel
,
68 SAC_CHANNEL_FLAG_REDRAW_EVENT
);
72 return STATUS_SUCCESS
;
77 ChannelDestroy(IN PSAC_CHANNEL Channel
)
79 CHECK_PARAMETER(Channel
);
81 /* Same thing as dereferencing all the handles */
82 return ChannelDereferenceHandles(Channel
);
87 ChannelOWrite(IN PSAC_CHANNEL Channel
,
92 CHECK_PARAMETER3(BufferSize
< SAC_OBUFFER_SIZE
);
94 /* While holding the output lock, write to the output buffer */
95 ChannelLockOBuffer(Channel
);
96 Status
= Channel
->ChannelOutputWrite(Channel
, Buffer
, BufferSize
);
97 ChannelUnlockOBuffer(Channel
);
103 ChannelOFlush(IN PSAC_CHANNEL Channel
)
107 /* While holding the output lock, flush to the output buffer */
108 ChannelLockOBuffer(Channel
);
109 Status
= Channel
->ChannelOutputFlush(Channel
);
110 ChannelUnlockOBuffer(Channel
);
116 ChannelIWrite(IN PSAC_CHANNEL Channel
,
122 /* Write into the input buffer while holding the lock */
123 ChannelLockIBuffer(Channel
);
124 Status
= Channel
->ChannelInputWrite(Channel
, Buffer
, BufferSize
);
125 ChannelUnlockIBuffer(Channel
);
131 ChannelIRead(IN PSAC_CHANNEL Channel
,
134 IN OUT PULONG ResultBufferSize
)
138 /* Read the input buffer while holding the lock */
139 ChannelLockIBuffer(Channel
);
140 Status
= Channel
->ChannelInputRead(Channel
,
144 ChannelUnlockIBuffer(Channel
);
150 ChannelIReadLast(IN PSAC_CHANNEL Channel
)
154 /* Read the last character while holding the lock */
155 ChannelLockIBuffer(Channel
);
156 LastChar
= Channel
->ChannelInputReadLast(Channel
);
157 ChannelUnlockIBuffer(Channel
);
163 ChannelIBufferLength(IN PSAC_CHANNEL Channel
)
167 /* Get the input buffer length while holding the lock */
168 ChannelLockOBuffer(Channel
);
169 Length
= Channel
->ChannelInputBufferLength(Channel
);
170 ChannelUnlockOBuffer(Channel
);
176 ChannelSetRedrawEvent(IN PSAC_CHANNEL Channel
)
181 ChannelSetEvent(Channel
, RedrawEvent
);
187 ChannelSetLockEvent(IN PSAC_CHANNEL Channel
)
192 ChannelSetEvent(Channel
, LockEvent
);
198 ChannelClearRedrawEvent(IN PSAC_CHANNEL Channel
)
202 /* Clear the event */
203 ChannelClearEvent(Channel
, RedrawEvent
);
209 ChannelHasRedrawEvent(IN PSAC_CHANNEL Channel
,
210 OUT PBOOLEAN Present
)
212 CHECK_PARAMETER1(Channel
);
213 CHECK_PARAMETER2(Present
);
215 /* Return if the flag is set */
216 *Present
= Channel
->Flags
& SAC_CHANNEL_FLAG_REDRAW_EVENT
;
217 return STATUS_SUCCESS
;
222 ChannelGetStatus(IN PSAC_CHANNEL Channel
,
223 OUT PSAC_CHANNEL_STATUS ChannelStatus
)
225 CHECK_PARAMETER1(Channel
);
227 /* Read the status while holding the attribute lock */
228 ChannelLockAttributes(Channel
);
229 *ChannelStatus
= Channel
->ChannelStatus
;
230 ChannelUnlockAttributes(Channel
);
231 return STATUS_SUCCESS
;
236 ChannelSetStatus(IN PSAC_CHANNEL Channel
,
237 IN SAC_CHANNEL_STATUS ChannelStatus
)
239 CHECK_PARAMETER1(Channel
);
241 /* Read the status while holding the attribute lock */
242 ChannelLockAttributes(Channel
);
243 Channel
->ChannelStatus
= ChannelStatus
;
244 ChannelUnlockAttributes(Channel
);
245 return STATUS_SUCCESS
;
250 ChannelIsActive(IN PSAC_CHANNEL Channel
)
252 SAC_CHANNEL_STATUS ChannelStatus
;
256 if (!NT_SUCCESS(ChannelGetStatus(Channel
, &ChannelStatus
)))
258 /* We couldn't even do that, assume it's inactive */
263 /* Check if the status shows activity */
264 IsActive
= (ChannelStatus
== Active
);
267 /* Return the state */
273 ChannelIsClosed(IN PSAC_CHANNEL Channel
)
275 SAC_CHANNEL_STATUS ChannelStatus
;
279 if (!NT_SUCCESS(ChannelGetStatus(Channel
, &ChannelStatus
)))
281 /* We couldn't even do that, assume it's inactive */
286 /* Check if the status shows activity */
287 IsClosed
= ((ChannelStatus
== Inactive
) &&
288 (Channel
->ChannelHasNewOBufferData
));
291 /* Return the state */
297 ChannelGetName(IN PSAC_CHANNEL Channel
,
300 CHECK_PARAMETER1(Channel
);
301 CHECK_PARAMETER2(Name
);
303 /* Allocate space to hold the name */
304 *Name
= SacAllocatePool(sizeof(Channel
->NameBuffer
), GLOBAL_BLOCK_TAG
);
305 CHECK_ALLOCATION(*Name
);
307 /* Lock the attributes while we copy the name */
308 ChannelLockAttributes(Channel
);
310 /* Copy the name and null-terminate it */
311 ASSERT(((wcslen(Channel
->NameBuffer
) + 1) * sizeof(WCHAR
)) <= ((SAC_CHANNEL_NAME_SIZE
+ 1) * sizeof(WCHAR
)));
312 wcsncpy(*Name
, Channel
->NameBuffer
, RTL_NUMBER_OF(Channel
->NameBuffer
)); // bug
313 (*Name
)[SAC_CHANNEL_NAME_SIZE
] = UNICODE_NULL
;
315 /* Release the lock and return */
316 ChannelUnlockAttributes(Channel
);
317 return STATUS_SUCCESS
;
322 ChannelSetName(IN PSAC_CHANNEL Channel
,
325 CHECK_PARAMETER1(Channel
);
326 CHECK_PARAMETER2(Name
);
328 /* Lock the attributes while we copy the name */
329 ChannelLockAttributes(Channel
);
331 /* Copy the name and null-terminate it */
332 ASSERT(((wcslen(Name
) + 1) * sizeof(WCHAR
)) <= ((SAC_CHANNEL_NAME_SIZE
+ 1) * sizeof(WCHAR
)));
333 wcsncpy(Channel
->NameBuffer
, Name
, RTL_NUMBER_OF(Channel
->NameBuffer
)); // bug
334 Channel
->NameBuffer
[SAC_CHANNEL_NAME_SIZE
] = UNICODE_NULL
;
336 /* Release the lock and return */
337 ChannelUnlockAttributes(Channel
);
338 return STATUS_SUCCESS
;
343 ChannelGetDescription(IN PSAC_CHANNEL Channel
,
344 IN PWCHAR
* Description
)
346 CHECK_PARAMETER1(Channel
);
347 CHECK_PARAMETER2(Description
);
349 /* Allocate space to hold the description */
350 *Description
= SacAllocatePool(sizeof(Channel
->DescriptionBuffer
), GLOBAL_BLOCK_TAG
);
351 CHECK_ALLOCATION(*Description
);
353 /* Lock the attributes while we copy the name */
354 ChannelLockAttributes(Channel
);
356 /* Copy the name and null-terminate it */
357 ASSERT(((wcslen(Channel
->DescriptionBuffer
) + 1) * sizeof(WCHAR
)) <= ((SAC_CHANNEL_DESCRIPTION_SIZE
+ 1) * sizeof(WCHAR
)));
358 wcsncpy(*Description
, Channel
->DescriptionBuffer
, RTL_NUMBER_OF(Channel
->DescriptionBuffer
)); // bug
359 (*Description
)[SAC_CHANNEL_DESCRIPTION_SIZE
] = UNICODE_NULL
;
361 /* Release the lock and return */
362 ChannelUnlockAttributes(Channel
);
363 return STATUS_SUCCESS
;
368 ChannelSetDescription(IN PSAC_CHANNEL Channel
,
369 IN PWCHAR Description
)
371 CHECK_PARAMETER1(Channel
);
372 CHECK_PARAMETER2(Description
);
374 /* Lock the attributes while we copy the name */
375 ChannelLockAttributes(Channel
);
377 /* Copy the name and null-terminate it */
378 ASSERT(((wcslen(Description
) + 1) * sizeof(WCHAR
)) <= ((SAC_CHANNEL_NAME_SIZE
+ 1) * sizeof(WCHAR
)));
379 wcsncpy(Channel
->DescriptionBuffer
, Description
, RTL_NUMBER_OF(Channel
->DescriptionBuffer
)); // bug
380 Channel
->DescriptionBuffer
[SAC_CHANNEL_DESCRIPTION_SIZE
] = UNICODE_NULL
;
382 /* Release the lock and return */
383 ChannelUnlockAttributes(Channel
);
384 return STATUS_SUCCESS
;
389 ChannelGetApplicationType(IN PSAC_CHANNEL Channel
,
390 OUT PGUID ApplicationType
)
392 CHECK_PARAMETER1(Channel
);
394 /* Read the application type GUID */
395 ChannelLockAttributes(Channel
);
396 *ApplicationType
= Channel
->ApplicationType
;
397 ChannelUnlockAttributes(Channel
);
399 /* Always return success */
400 return STATUS_SUCCESS
;
405 ChannelInitializeVTable(IN PSAC_CHANNEL Channel
)
407 /* What kind of channel is this? */
408 switch (Channel
->ChannelType
)
411 /* Setup the calls for a VT-UTF8 channel */
412 Channel
->ChannelCreate
= VTUTF8ChannelCreate
;
413 Channel
->ChannelDestroy
= VTUTF8ChannelDestroy
;
414 Channel
->ChannelOutputFlush
= VTUTF8ChannelOFlush
;
415 Channel
->ChannelOutputEcho
= VTUTF8ChannelOEcho
;
416 Channel
->ChannelOutputWrite
= VTUTF8ChannelOWrite
;
417 Channel
->ChannelOutputRead
= VTUTF8ChannelORead
;
418 Channel
->ChannelInputWrite
= VTUTF8ChannelIWrite
;
419 Channel
->ChannelInputRead
= VTUTF8ChannelIRead
;
420 Channel
->ChannelInputReadLast
= VTUTF8ChannelIReadLast
;
421 Channel
->ChannelInputBufferIsFull
= VTUTF8ChannelIBufferIsFull
;
422 Channel
->ChannelInputBufferLength
= VTUTF8ChannelIBufferLength
;
428 return STATUS_NOT_IMPLEMENTED
;
432 /* Setup the calls for a raw channel */
433 Channel
->ChannelCreate
= RawChannelCreate
;
434 Channel
->ChannelDestroy
= RawChannelDestroy
;
435 Channel
->ChannelOutputFlush
= RawChannelOFlush
;
436 Channel
->ChannelOutputEcho
= RawChannelOEcho
;
437 Channel
->ChannelOutputWrite
= RawChannelOWrite
;
438 Channel
->ChannelOutputRead
= RawChannelORead
;
439 Channel
->ChannelInputWrite
= RawChannelIWrite
;
440 Channel
->ChannelInputRead
= RawChannelIRead
;
441 Channel
->ChannelInputReadLast
= RawChannelIReadLast
;
442 Channel
->ChannelInputBufferIsFull
= RawChannelIBufferIsFull
;
443 Channel
->ChannelInputBufferLength
= RawChannelIBufferLength
;
447 /* Unsupported channel type */
448 return STATUS_INVALID_PARAMETER
;
451 /* If we got here, the channel was supported */
452 return STATUS_SUCCESS
;
457 ChannelCreate(IN PSAC_CHANNEL Channel
,
458 IN PSAC_CHANNEL_ATTRIBUTES Attributes
,
459 IN SAC_CHANNEL_ID ChannelId
)
462 CHECK_PARAMETER1(Channel
);
463 CHECK_PARAMETER2(Attributes
);
465 /* If a close event is being passed in, it must exist, and vice-versa */
466 if (Attributes
->Flag
& SAC_CHANNEL_FLAG_CLOSE_EVENT
)
468 CHECK_PARAMETER(Attributes
->CloseEvent
!= NULL
);
472 CHECK_PARAMETER(Attributes
->CloseEvent
== NULL
);
475 /* If a new data event is being passed in, it must exist, and vice-versa */
476 if (Attributes
->Flag
& SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT
)
478 CHECK_PARAMETER(Attributes
->HasNewDataEvent
!= NULL
);
482 CHECK_PARAMETER(Attributes
->HasNewDataEvent
== NULL
);
485 /* If a lock event is being passed in, it must exist, and vice-versa */
486 if (Attributes
->Flag
& SAC_CHANNEL_FLAG_LOCK_EVENT
)
488 CHECK_PARAMETER(Attributes
->LockEvent
!= NULL
);
492 CHECK_PARAMETER(Attributes
->LockEvent
== NULL
);
495 /* If a redraw event is being passed in, it must exist, and vice-versa */
496 if (Attributes
->Flag
& SAC_CHANNEL_FLAG_REDRAW_EVENT
)
498 CHECK_PARAMETER(Attributes
->RedrawEvent
!= NULL
);
502 CHECK_PARAMETER(Attributes
->RedrawEvent
== NULL
);
505 /* Initialize the channel structure */
506 RtlZeroMemory(Channel
, sizeof(SAC_CHANNEL
));
507 Channel
->ChannelId
= ChannelId
;
508 Channel
->ChannelType
= Attributes
->ChannelType
;
509 Channel
->Flags
= Attributes
->Flag
;
510 if (Attributes
->Flag
& SAC_CHANNEL_FLAG_APPLICATION
)
512 Channel
->ApplicationType
= Attributes
->ChannelId
;
515 /* Initialize all the locks and events */
516 SacInitializeLock(&Channel
->ChannelAttributeLock
);
517 SacInitializeLock(&Channel
->ChannelOBufferLock
);
518 SacInitializeLock(&Channel
->ChannelIBufferLock
);
519 ChannelInitializeEvent(Channel
, Attributes
, CloseEvent
);
520 ChannelInitializeEvent(Channel
, Attributes
, HasNewDataEvent
);
521 ChannelInitializeEvent(Channel
, Attributes
, LockEvent
);
522 ChannelInitializeEvent(Channel
, Attributes
, RedrawEvent
);
524 /* Set the name and description */
525 ChannelSetName(Channel
, Attributes
->NameBuffer
);
526 ChannelSetDescription(Channel
, Attributes
->DescriptionBuffer
);
528 /* Initialize the function table for the type of channel this is */
529 Status
= ChannelInitializeVTable(Channel
);
530 if (!NT_SUCCESS(Status
))
532 /* This is critical */
533 SAC_DBG(SAC_DBG_INIT
, "SAC Create Channel :: Failed to initialize vtable\n");
537 /* Now call the channel specific type constructor */
538 Status
= Channel
->ChannelCreate(Channel
);
539 if (!NT_SUCCESS(Status
))
541 /* This is critical */
542 SAC_DBG(SAC_DBG_INIT
, "SAC Create Channel :: Failed channel specific initialization\n");
546 /* Finally, mark the channel as active */
547 ChannelSetStatus(Channel
, Active
);
548 return STATUS_SUCCESS
;
551 /* Destroy the channel and return the failure code */
552 Channel
->ChannelDestroy(Channel
);
558 ChannelClose(IN PSAC_CHANNEL Channel
)
561 CHECK_PARAMETER(Channel
);
563 /* Set the channel inactive */
564 ChannelSetStatus(Channel
, Inactive
);
566 /* Set the close event */
567 if (Channel
->Flags
& SAC_CHANNEL_FLAG_CLOSE_EVENT
)
569 ChannelSetEvent(Channel
, CloseEvent
);
572 /* Close all the handles */
573 Status
= ChannelDereferenceHandles(Channel
);