You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1151 lines
26 KiB
1151 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sacapi.c
|
|
|
|
Abstract:
|
|
|
|
This is the C library used to interface to SAC driver.
|
|
|
|
Author:
|
|
|
|
Brian Guarraci (briangu)
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "sacapip.h"
|
|
|
|
#include <sacapi.h>
|
|
#include <ntddsac.h>
|
|
|
|
#if DBG
|
|
//
|
|
// Counter to keep track of how many driver handles have been
|
|
// requested and released.
|
|
//
|
|
static ULONG DriverHandleRefCount = 0;
|
|
#endif
|
|
|
|
//
|
|
// Memory management routine aliases
|
|
//
|
|
#define SAC_API_ALLOCATE_MEMORY(s) LocalAlloc(LPTR, (s))
|
|
#define SAC_API_FREE_MEMORY(p) LocalFree(p)
|
|
|
|
//
|
|
// enhanced assertion:
|
|
//
|
|
// First assert the condition,
|
|
// if ASSERTs are turned off,
|
|
// we bail out of the function with a status
|
|
//
|
|
#define SAC_API_ASSERT(c,s) \
|
|
ASSERT(c); \
|
|
if (!(c)) { \
|
|
Status = s; \
|
|
__leave; \
|
|
}
|
|
|
|
typedef GUID* PGUID;
|
|
|
|
BOOL
|
|
SacHandleOpen(
|
|
OUT HANDLE* SacHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a handle to the SAC driver
|
|
|
|
Arguments:
|
|
|
|
SacHandle - A pointer to the SAC Handle
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> SacHandle is valid
|
|
|
|
--*/
|
|
{
|
|
BOOL Status;
|
|
|
|
Status = TRUE;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacHandle, FALSE);
|
|
|
|
//
|
|
// Open the SAC
|
|
//
|
|
// SECURITY:
|
|
//
|
|
// this handle cannot be inherited
|
|
//
|
|
*SacHandle = CreateFile(
|
|
L"\\\\.\\SAC",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if (*SacHandle == INVALID_HANDLE_VALUE) {
|
|
|
|
Status = FALSE;
|
|
|
|
}
|
|
#if DBG
|
|
else {
|
|
InterlockedIncrement((volatile long *)&DriverHandleRefCount);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
ASSERT(0);
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacHandleClose(
|
|
IN OUT HANDLE* SacHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Close the handle to the SAC driver
|
|
|
|
Arguments:
|
|
|
|
SacHandle - A handle to the SAC driver
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> SacHandle is now invalid (NULL)
|
|
|
|
--*/
|
|
{
|
|
BOOL Status;
|
|
|
|
//
|
|
// default: we succeeded to close the handle
|
|
//
|
|
Status = TRUE;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacHandle, FALSE);
|
|
SAC_API_ASSERT(*SacHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// close the handle to the SAC driver
|
|
//
|
|
Status = CloseHandle(*SacHandle);
|
|
|
|
if (Status == TRUE) {
|
|
|
|
//
|
|
// NULL the SAC driver handle
|
|
//
|
|
*SacHandle = INVALID_HANDLE_VALUE;
|
|
|
|
#if DBG
|
|
InterlockedDecrement((volatile long *)&DriverHandleRefCount);
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
ASSERT(0);
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacChannelOpen(
|
|
OUT PSAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PSAC_CHANNEL_OPEN_ATTRIBUTES SacChannelAttributes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open a SAC channel of the specified name
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - The handle to the newly created channel
|
|
SacChannelAttributes - The attributes describing the new channel
|
|
|
|
Note: The SacChannelDescription parameter is optional.
|
|
|
|
If SacChannelDescription != NULL,
|
|
then the Channel description will be assigned the Unicode string pointed to
|
|
by SacChannelDescription.
|
|
If SacChannelDescription == NULL,
|
|
then the Channel description will be null upon creation.
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> pHandle is valid
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
ULONG OpenChannelCmdSize;
|
|
PSAC_CMD_OPEN_CHANNEL OpenChannelCmd;
|
|
SAC_RSP_OPEN_CHANNEL OpenChannelRsp;
|
|
DWORD Feedback;
|
|
HANDLE DriverHandle;
|
|
|
|
//
|
|
// default
|
|
//
|
|
Status = FALSE;
|
|
OpenChannelCmdSize = 0;
|
|
OpenChannelCmd = NULL;
|
|
DriverHandle = INVALID_HANDLE_VALUE;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacChannelHandle, FALSE);
|
|
SAC_API_ASSERT(SacChannelAttributes, FALSE);
|
|
|
|
//
|
|
// Get a handle to the driver and store it in the
|
|
// Channel handle. This way, the api user doesn't have
|
|
// explicitly open/close the driver handle.
|
|
//
|
|
Status = SacHandleOpen(&DriverHandle);
|
|
|
|
if ((Status != TRUE) ||
|
|
(DriverHandle == INVALID_HANDLE_VALUE)) {
|
|
Status = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
SAC_API_ASSERT(Status == TRUE, FALSE);
|
|
SAC_API_ASSERT(DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// Verify that if the user wants to use the CLOSE_EVENT, we received one to use
|
|
//
|
|
SAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
|
&& SacChannelAttributes->CloseEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
|
&& !SacChannelAttributes->CloseEvent),
|
|
FALSE
|
|
);
|
|
|
|
//
|
|
// Verify that if the user wants to use the HAS_NEW_DATA_EVENT, we received one to use
|
|
//
|
|
SAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
|
&& SacChannelAttributes->HasNewDataEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
|
&& !SacChannelAttributes->HasNewDataEvent),
|
|
FALSE
|
|
);
|
|
|
|
#if ENABLE_CHANNEL_LOCKING
|
|
//
|
|
// Verify that if the user wants to use the LOCK_EVENT, we received one to use
|
|
//
|
|
SAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT)
|
|
&& SacChannelAttributes->LockEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT)
|
|
&& !SacChannelAttributes->LockEvent),
|
|
FALSE
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Verify that if the user wants to use the REDRAW_EVENT, we received one to use
|
|
//
|
|
SAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)
|
|
&& SacChannelAttributes->RedrawEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)
|
|
&& !SacChannelAttributes->RedrawEvent),
|
|
FALSE
|
|
);
|
|
|
|
//
|
|
// If the channel type isn't cmd,
|
|
// then make sure they sent us a name.
|
|
//
|
|
if (SacChannelAttributes->Type != ChannelTypeCmd) {
|
|
|
|
SAC_API_ASSERT(SacChannelAttributes->Name, FALSE);
|
|
|
|
}
|
|
|
|
__try {
|
|
|
|
//
|
|
// create and initialize the Open Channel message structure
|
|
//
|
|
OpenChannelCmdSize = sizeof(SAC_CMD_OPEN_CHANNEL);
|
|
OpenChannelCmd = (PSAC_CMD_OPEN_CHANNEL)SAC_API_ALLOCATE_MEMORY(OpenChannelCmdSize);
|
|
SAC_API_ASSERT(OpenChannelCmd, FALSE);
|
|
|
|
//
|
|
// Populate the new channel attributes
|
|
//
|
|
OpenChannelCmd->Attributes = *SacChannelAttributes;
|
|
|
|
//
|
|
// If the channel type isn't cmd,
|
|
// then make sure they sent us a name.
|
|
//
|
|
if (SacChannelAttributes->Type == ChannelTypeCmd) {
|
|
|
|
//
|
|
// force the name and description to be empty
|
|
//
|
|
OpenChannelCmd->Attributes.Name[0] = UNICODE_NULL;
|
|
OpenChannelCmd->Attributes.Description[0] = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// Send down an IOCTL for opening a channel
|
|
//
|
|
Status = DeviceIoControl(
|
|
DriverHandle,
|
|
IOCTL_SAC_OPEN_CHANNEL,
|
|
OpenChannelCmd,
|
|
OpenChannelCmdSize,
|
|
&OpenChannelRsp,
|
|
sizeof(SAC_RSP_OPEN_CHANNEL),
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
//
|
|
// if the channel was not successfully created, NULL
|
|
// the channel handle
|
|
//
|
|
if (Status == FALSE) {
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
//
|
|
// the new channel was created, so pass back the handle to it
|
|
//
|
|
SacChannelHandle->DriverHandle = DriverHandle;
|
|
SacChannelHandle->ChannelHandle = OpenChannelRsp.Handle.ChannelHandle;
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
Status = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
__finally {
|
|
|
|
if (OpenChannelCmd) {
|
|
|
|
//
|
|
// free the Open Channel message structure
|
|
//
|
|
SAC_API_FREE_MEMORY(OpenChannelCmd);
|
|
|
|
}
|
|
|
|
if (Status == FALSE) {
|
|
|
|
if (DriverHandle != INVALID_HANDLE_VALUE) {
|
|
|
|
//
|
|
// Release the driver handle
|
|
//
|
|
SacHandleClose(&DriverHandle);
|
|
|
|
//
|
|
// NULL the sac channel handle
|
|
//
|
|
RtlZeroMemory(SacChannelHandle, sizeof(SAC_CHANNEL_HANDLE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacChannelClose(
|
|
IN OUT PSAC_CHANNEL_HANDLE SacChannelHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Close the specified SAC channel
|
|
|
|
NOTE: the channel pointer is made NULL under all conditions
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - Channel to be closed
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the channel was closed
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
SAC_CMD_CLOSE_CHANNEL CloseChannelCmd;
|
|
DWORD Feedback;
|
|
|
|
__try {
|
|
|
|
if (!SacChannelHandle ||
|
|
(SacChannelHandle == INVALID_HANDLE_VALUE) ||
|
|
(SacChannelHandle->DriverHandle == INVALID_HANDLE_VALUE) ||
|
|
!SacChannelHandle->DriverHandle) {
|
|
Status = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
SAC_API_ASSERT(SacChannelHandle, FALSE);
|
|
SAC_API_ASSERT(SacChannelHandle->DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// initialize the Close Channel message
|
|
//
|
|
RtlZeroMemory(&CloseChannelCmd, sizeof(SAC_CMD_CLOSE_CHANNEL));
|
|
|
|
CloseChannelCmd.Handle.ChannelHandle = SacChannelHandle->ChannelHandle;
|
|
|
|
//
|
|
// Send down the IOCTL for closing the channel
|
|
//
|
|
Status = DeviceIoControl(
|
|
SacChannelHandle->DriverHandle,
|
|
IOCTL_SAC_CLOSE_CHANNEL,
|
|
&CloseChannelCmd,
|
|
sizeof(SAC_CMD_CLOSE_CHANNEL),
|
|
NULL,
|
|
0,
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Close the handle to the driver
|
|
//
|
|
SacHandleClose(&SacChannelHandle->DriverHandle);
|
|
|
|
//
|
|
// The channel handle is no longer valid, so NULL it
|
|
//
|
|
RtlZeroMemory(&SacChannelHandle->ChannelHandle, sizeof(GUID));
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacChannelWrite(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PCBYTE Buffer,
|
|
IN ULONG BufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the given buffer to the specified SAC Channel
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - The channel to write the buffer to
|
|
Buffer - data buffer
|
|
BufferSize - size of the buffer
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was sent
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
ULONG WriteChannelCmdSize;
|
|
PSAC_CMD_WRITE_CHANNEL WriteChannelCmd;
|
|
DWORD Feedback;
|
|
|
|
//
|
|
// Default
|
|
//
|
|
Status = FALSE;
|
|
WriteChannelCmdSize = 0;
|
|
WriteChannelCmd = NULL;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle, FALSE);
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
SAC_API_ASSERT(Buffer, FALSE);
|
|
SAC_API_ASSERT(BufferSize > 0, FALSE);
|
|
|
|
//
|
|
// create and initialize the Open Channel message structure
|
|
//
|
|
WriteChannelCmdSize = sizeof(SAC_CMD_WRITE_CHANNEL) + BufferSize;
|
|
WriteChannelCmd = (PSAC_CMD_WRITE_CHANNEL)SAC_API_ALLOCATE_MEMORY(WriteChannelCmdSize);
|
|
SAC_API_ASSERT(WriteChannelCmd, FALSE);
|
|
|
|
__try {
|
|
|
|
//
|
|
// Indicate which channel this command is for
|
|
//
|
|
WriteChannelCmd->Handle.ChannelHandle = SacChannelHandle.ChannelHandle;
|
|
|
|
//
|
|
// Set the length of the string to send
|
|
//
|
|
// Note: Size does not include the terminating NULL,
|
|
// becase we don't want to send that.
|
|
//
|
|
WriteChannelCmd->Size = BufferSize;
|
|
|
|
//
|
|
// Set the buffer to be written
|
|
//
|
|
RtlCopyMemory(
|
|
&(WriteChannelCmd->Buffer),
|
|
Buffer,
|
|
BufferSize
|
|
);
|
|
|
|
//
|
|
// Send down the IOCTL for writing the message
|
|
//
|
|
Status = DeviceIoControl(
|
|
SacChannelHandle.DriverHandle,
|
|
IOCTL_SAC_WRITE_CHANNEL,
|
|
WriteChannelCmd,
|
|
WriteChannelCmdSize,
|
|
NULL,
|
|
0,
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
}
|
|
__finally {
|
|
|
|
//
|
|
// if the cmd memory was allocated,
|
|
// then release it
|
|
//
|
|
if (WriteChannelCmd) {
|
|
SAC_API_FREE_MEMORY(WriteChannelCmd);
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacChannelRawWrite(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PCBYTE Buffer,
|
|
IN ULONG BufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write the given buffer to the specified SAC Channel
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - The channel to write the buffer to
|
|
Buffer - data buffer
|
|
BufferSize - size of the buffer
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was sent
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// relay the write to the actual write routine
|
|
//
|
|
|
|
return SacChannelWrite(
|
|
SacChannelHandle,
|
|
Buffer,
|
|
BufferSize
|
|
);
|
|
|
|
}
|
|
|
|
BOOL
|
|
SacChannelVTUTF8WriteString(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PCWSTR String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine writes a null-terminated Unicode String to the specified Channel.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - The channel to write the buffer to
|
|
String - A null-terminated Unicode string
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was sent
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
ULONG BufferSize;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Treating the String as a data buffer, we calculate it's size
|
|
// not including the null termination
|
|
//
|
|
|
|
BufferSize = (ULONG)(wcslen(String) * sizeof(WCHAR));
|
|
|
|
SAC_API_ASSERT(BufferSize > 0, FALSE);
|
|
|
|
//
|
|
// Write the data to the channel
|
|
//
|
|
|
|
Status = SacChannelWrite(
|
|
SacChannelHandle,
|
|
(PCBYTE)String,
|
|
BufferSize
|
|
);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SacChannelVTUTF8Write(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PCWCHAR Buffer,
|
|
IN ULONG BufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routines writes an array of WCHAR to the VTUTF8 channel specified.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - The channel to write the buffer to
|
|
Buffer - data buffer
|
|
BufferSize - size of the buffer
|
|
|
|
Note: Buffer is not null-terminated
|
|
BufferSize should not count a null-termination.
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was sent
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// relay the write to the actual write routine
|
|
//
|
|
|
|
return SacChannelWrite(
|
|
SacChannelHandle,
|
|
(PCBYTE)Buffer,
|
|
BufferSize
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
SacChannelHasNewData(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
OUT PBOOL InputWaiting
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks to see if there is any waiting input for
|
|
the channel specified by the handle
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - the channel to write the string to
|
|
InputWaiting - the input buffer status
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer status was retrieved
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
SAC_CMD_POLL_CHANNEL PollChannelCmd;
|
|
SAC_RSP_POLL_CHANNEL PollChannelRsp;
|
|
DWORD Feedback;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle, FALSE);
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// Initialize and populate the poll command structure
|
|
//
|
|
RtlZeroMemory(&PollChannelCmd, sizeof(SAC_CMD_POLL_CHANNEL));
|
|
|
|
PollChannelCmd.Handle.ChannelHandle = SacChannelHandle.ChannelHandle;
|
|
|
|
//
|
|
// Send down the IOCTL to poll for new input
|
|
//
|
|
Status = DeviceIoControl(
|
|
SacChannelHandle.DriverHandle,
|
|
IOCTL_SAC_POLL_CHANNEL,
|
|
&PollChannelCmd,
|
|
sizeof(SAC_CMD_POLL_CHANNEL),
|
|
&PollChannelRsp,
|
|
sizeof(SAC_RSP_POLL_CHANNEL),
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
if (Status) {
|
|
*InputWaiting = PollChannelRsp.InputWaiting;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
BOOL
|
|
SacChannelRead(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
OUT PBYTE Buffer,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG ByteCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads data from the channel specified.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - the channel to read from
|
|
Buffer - destination buffer
|
|
BufferSize - size of the destination buffer (bytes)
|
|
ByteCount - the actual # of byte read
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was read
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
SAC_CMD_READ_CHANNEL ReadChannelCmd;
|
|
PSAC_RSP_READ_CHANNEL ReadChannelRsp;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle, FALSE);
|
|
SAC_API_ASSERT(SacChannelHandle.DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
SAC_API_ASSERT(Buffer, FALSE);
|
|
SAC_API_ASSERT(ByteCount, FALSE);
|
|
|
|
//
|
|
// Populate the read channel cmd
|
|
//
|
|
RtlZeroMemory(&ReadChannelCmd, sizeof(SAC_CMD_READ_CHANNEL));
|
|
|
|
ReadChannelCmd.Handle.ChannelHandle = SacChannelHandle.ChannelHandle;
|
|
ReadChannelRsp = (PSAC_RSP_READ_CHANNEL)Buffer;
|
|
|
|
//
|
|
// Send down the IOCTL to read input
|
|
//
|
|
Status = DeviceIoControl(
|
|
SacChannelHandle.DriverHandle,
|
|
IOCTL_SAC_READ_CHANNEL,
|
|
&ReadChannelCmd,
|
|
sizeof(SAC_CMD_READ_CHANNEL),
|
|
ReadChannelRsp,
|
|
BufferSize,
|
|
ByteCount,
|
|
0
|
|
);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
BOOL
|
|
SacChannelVTUTF8Read(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
OUT PWSTR Buffer,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG ByteCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads data from the channel specified.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - the channel to read from
|
|
Buffer - destination buffer
|
|
BufferSize - size of the destination buffer (bytes)
|
|
ByteCount - the actual # of byte read
|
|
|
|
Note: the Buffer upon return is NOT null terminated
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was read
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return SacChannelRead(
|
|
SacChannelHandle,
|
|
(PBYTE)Buffer,
|
|
BufferSize,
|
|
ByteCount
|
|
);
|
|
|
|
}
|
|
|
|
BOOL
|
|
SacChannelRawRead(
|
|
IN SAC_CHANNEL_HANDLE SacChannelHandle,
|
|
OUT PBYTE Buffer,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG ByteCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads data from the channel specified.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - the channel to read from
|
|
Buffer - destination buffer
|
|
BufferSize - size of the destination buffer (bytes)
|
|
ByteCount - the actual # of byte read
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the buffer was read
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return SacChannelRead(
|
|
SacChannelHandle,
|
|
Buffer,
|
|
BufferSize,
|
|
ByteCount
|
|
);
|
|
|
|
}
|
|
|
|
BOOL
|
|
SacRegisterCmdEvent(
|
|
OUT HANDLE *pDriverHandle,
|
|
IN HANDLE RequestSacCmdEvent,
|
|
IN HANDLE RequestSacCmdSuccessEvent,
|
|
IN HANDLE RequestSacCmdFailureEvent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine configures the SAC driver with the event handlers
|
|
and needed to implement the ability to launch cmd consoles via
|
|
a user-mode service app.
|
|
|
|
Note: Only one registration can exist at a time in the SAC driver.
|
|
|
|
Arguments:
|
|
|
|
pDriverHandle - on success, contains the driver handle used to register
|
|
RequestSacCmdEvent - the event triggered when the SAC wants to launch a cmd console
|
|
RequestSacCmdSuccessEvent - the event triggered when the cmd console has successfully launched
|
|
RequestSacCmdFailureEvent - the event triggered when the cmd console has failed to launch
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the cmd event was registered with the SAC driver
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
DWORD Feedback;
|
|
SAC_CMD_SETUP_CMD_EVENT SacCmdEvent;
|
|
HANDLE DriverHandle;
|
|
|
|
//
|
|
// default
|
|
//
|
|
*pDriverHandle = INVALID_HANDLE_VALUE;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(pDriverHandle != NULL, FALSE);
|
|
SAC_API_ASSERT(RequestSacCmdEvent, FALSE);
|
|
SAC_API_ASSERT(RequestSacCmdSuccessEvent, FALSE);
|
|
SAC_API_ASSERT(RequestSacCmdFailureEvent, FALSE);
|
|
|
|
//
|
|
// Get a handle to the driver. This way, the api user doesn't have
|
|
// explicitly open/close the driver handle.
|
|
//
|
|
Status = SacHandleOpen(&DriverHandle);
|
|
|
|
if ((Status != TRUE) ||
|
|
(DriverHandle == INVALID_HANDLE_VALUE)) {
|
|
Status = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
SAC_API_ASSERT(Status == TRUE, FALSE);
|
|
SAC_API_ASSERT(DriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// Initialize the our SAC Cmd Info
|
|
//
|
|
SacCmdEvent.RequestSacCmdEvent = RequestSacCmdEvent;
|
|
SacCmdEvent.RequestSacCmdSuccessEvent = RequestSacCmdSuccessEvent;
|
|
SacCmdEvent.RequestSacCmdFailureEvent = RequestSacCmdFailureEvent;
|
|
|
|
//
|
|
// Send down the IOCTL for setting up the SAC Cmd launch event
|
|
//
|
|
Status = DeviceIoControl(
|
|
DriverHandle,
|
|
IOCTL_SAC_REGISTER_CMD_EVENT,
|
|
&SacCmdEvent,
|
|
sizeof(SAC_CMD_SETUP_CMD_EVENT),
|
|
NULL,
|
|
0,
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
|
|
//
|
|
// if we were successful,
|
|
// then keep the driver handle
|
|
//
|
|
if (Status) {
|
|
|
|
*pDriverHandle = DriverHandle;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Close the driver handle
|
|
//
|
|
SacHandleClose(&DriverHandle);
|
|
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOL
|
|
SacUnRegisterCmdEvent(
|
|
IN OUT HANDLE *pDriverHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine unregisters the event information required
|
|
to launch cmd consoles via a user-mode service app.
|
|
|
|
Arguments:
|
|
|
|
pDriverHandle - on entry, contains the driver handle that was used to
|
|
register the cmd event info
|
|
on success, contains INVALID_HANDLE_VALUE
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
TRUE --> the cmd event was unregistered with the SAC driver
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL Status;
|
|
DWORD Feedback;
|
|
|
|
//
|
|
// default
|
|
//
|
|
Status = FALSE;
|
|
|
|
__try {
|
|
|
|
SAC_API_ASSERT(*pDriverHandle != INVALID_HANDLE_VALUE, FALSE);
|
|
|
|
//
|
|
// Send down the IOCTL for unregistering the SAC Cmd launch event
|
|
//
|
|
Status = DeviceIoControl(
|
|
*pDriverHandle,
|
|
IOCTL_SAC_UNREGISTER_CMD_EVENT,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&Feedback,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Close the driver handle
|
|
//
|
|
SacHandleClose(pDriverHandle);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|