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.
985 lines
23 KiB
985 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ksacapi.c
|
|
|
|
Abstract:
|
|
|
|
Kernel mode SAC api
|
|
|
|
Author:
|
|
|
|
Brian Guarraci (briangu), 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ksacapip.h"
|
|
|
|
#include <ksacapi.h>
|
|
#include <ntddsac.h>
|
|
|
|
//
|
|
// Machine Information table and routines.
|
|
//
|
|
#define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
|
|
\
|
|
RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
|
|
\
|
|
InitializeObjectAttributes( \
|
|
(Obja), \
|
|
(UnicodeString), \
|
|
OBJ_CASE_INSENSITIVE, \
|
|
NULL, \
|
|
NULL \
|
|
)
|
|
|
|
//
|
|
// Memory management routine aliases
|
|
//
|
|
#define KSAC_API_ALLOCATE_MEMORY(_s)
|
|
#define KSAC_API_FREE_MEMORY(_p)
|
|
|
|
#define KSAC_API_ASSERT(c,s)\
|
|
ASSERT(c);\
|
|
if (!(c)) {\
|
|
return s;\
|
|
}
|
|
|
|
#define KSAC_VALIDATE_CHANNEL_HANDLE(_h)\
|
|
KSAC_API_ASSERT( \
|
|
_h->ChannelHandle->DriverHandle, \
|
|
STATUS_INVALID_PARAMETER_1 \
|
|
); \
|
|
KSAC_API_ASSERT( \
|
|
_h->ChannelHandle->DriverHandle != INVALID_HANDLE_VALUE, \
|
|
STATUS_INVALID_PARAMETER_1 \
|
|
); \
|
|
KSAC_API_ASSERT( \
|
|
_h->SacEventHandle != INVALID_HANDLE_VALUE, \
|
|
STATUS_INVALID_PARAMETER_1 \
|
|
); \
|
|
KSAC_API_ASSERT( \
|
|
_h->SacEvent != NULL, \
|
|
STATUS_INVALID_PARAMETER_1 \
|
|
);
|
|
|
|
|
|
|
|
NTSTATUS
|
|
KSacHandleOpen(
|
|
OUT HANDLE* SacHandle,
|
|
OUT HANDLE* SacEventHandle,
|
|
OUT PKEVENT* SacEvent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens a handle to the SAC driver and
|
|
creates and initializes an associated syncrhonization event.
|
|
|
|
Arguments:
|
|
|
|
SacHandle - the driver handle
|
|
SacEventHandle - the event handle
|
|
SacEvent - the sac event
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
UNICODE_STRING UnicodeString;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
KSAC_API_ASSERT(SacHandle == NULL, STATUS_INVALID_PARAMETER_1);
|
|
KSAC_API_ASSERT(SacEventHandle == NULL, STATUS_INVALID_PARAMETER_2);
|
|
KSAC_API_ASSERT(SacEvent == NULL, STATUS_INVALID_PARAMETER_3);
|
|
|
|
//
|
|
// Open the SAC driver
|
|
//
|
|
INIT_OBJA(&ObjAttr, &UnicodeString, L"\\Device\\SAC");
|
|
|
|
Status = ZwCreateFile(
|
|
*SacHandle,
|
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
&ObjAttr,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
0,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Initialize the SAC Kernel event
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString, L"\\SetupDDSacEvent");
|
|
|
|
*SacEvent = IoCreateSynchronizationEvent(
|
|
&UnicodeString,
|
|
SacEventHandle
|
|
);
|
|
|
|
if (*SacEvent == NULL) {
|
|
ZwClose(*SacHandle);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacHandleClose(
|
|
IN OUT HANDLE* SacHandle,
|
|
IN OUT HANDLE* SacEventHandle,
|
|
IN OUT PKEVENT* SacEvent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine closes a handle to the SAC driver and
|
|
closes the associated syncrhonization event.
|
|
|
|
Arguments:
|
|
|
|
SacHandle - the driver handle
|
|
SacEventHandle - the event handle
|
|
SacEvent - the sac event
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
KSAC_API_ASSERT(*SacHandle != NULL, STATUS_INVALID_PARAMETER_1);
|
|
KSAC_API_ASSERT(*SacEventHandle != NULL, STATUS_INVALID_PARAMETER_2);
|
|
|
|
UNREFERENCED_PARAMETER(SacEvent);
|
|
|
|
ZwClose(*SacHandle);
|
|
ZwClose(*SacEventHandle);
|
|
|
|
//
|
|
// Null the handles
|
|
//
|
|
*SacEventHandle = NULL;
|
|
*SacHandle = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
KSacChannelOpen(
|
|
OUT PKSAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PSAC_CHANNEL_OPEN_ATTRIBUTES SacChannelAttributes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens a SAC channel with the specified attributes.
|
|
|
|
Arguments:
|
|
|
|
SacChannelHandle - on success, contains the handle to the new channel
|
|
SacChannelAttributes - the attributes of the new channel
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
UNICODE_STRING UnicodeString;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
ULONG OpenChannelCmdSize;
|
|
PSAC_CMD_OPEN_CHANNEL OpenChannelCmd;
|
|
SAC_RSP_OPEN_CHANNEL OpenChannelRsp;
|
|
HANDLE DriverHandle;
|
|
HANDLE SacEventHandle;
|
|
PKEVENT SacEvent;
|
|
|
|
KSAC_API_ASSERT(SacChannelHandle != NULL, STATUS_INVALID_PARAMETER_1);
|
|
KSAC_API_ASSERT(SacChannelAttributes != NULL, STATUS_INVALID_PARAMETER_2);
|
|
|
|
//
|
|
// default: we didn't get a valid handle
|
|
//
|
|
RtlZeroMemory(SacChannelHandle, sizeof(KSAC_CHANNEL_HANDLE));
|
|
|
|
//
|
|
// Verify that if the user wants to use the CLOSE_EVENT, we received one to use
|
|
//
|
|
KSAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
|
&& SacChannelAttributes->CloseEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT)
|
|
&& !SacChannelAttributes->CloseEvent),
|
|
STATUS_INVALID_PARAMETER_2
|
|
);
|
|
|
|
//
|
|
// Verify that if the user wants to use the HAS_NEW_DATA_EVENT, we received one to use
|
|
//
|
|
KSAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
|
&& SacChannelAttributes->HasNewDataEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT)
|
|
&& !SacChannelAttributes->HasNewDataEvent),
|
|
STATUS_INVALID_PARAMETER_2
|
|
);
|
|
|
|
#if ENABLE_CHANNEL_LOCKING
|
|
//
|
|
// Verify that if the user wants to use the LOCK_EVENT, we received one to use
|
|
//
|
|
KSAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT)
|
|
&& SacChannelAttributes->LockEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT)
|
|
&& !SacChannelAttributes->LockEvent),
|
|
STATUS_INVALID_PARAMETER_2
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Verify that if the user wants to use the REDRAW_EVENT, we received one to use
|
|
//
|
|
KSAC_API_ASSERT(
|
|
((SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)
|
|
&& SacChannelAttributes->RedrawEvent) ||
|
|
(!(SacChannelAttributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT)
|
|
&& !SacChannelAttributes->RedrawEvent),
|
|
STATUS_INVALID_PARAMETER_2
|
|
);
|
|
|
|
//
|
|
// If the channel type isn't cmd,
|
|
// then make sure they sent us a name.
|
|
//
|
|
if (SacChannelAttributes->Type != ChannelTypeCmd) {
|
|
|
|
KSAC_API_ASSERT(SacChannelAttributes->Name, STATUS_INVALID_PARAMETER_2);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Make sure they didn't pass us a name or description.
|
|
//
|
|
KSAC_API_ASSERT(SacChannelAttributes->Name == NULL, STATUS_INVALID_PARAMETER_2);
|
|
KSAC_API_ASSERT(SacChannelAttributes->Description == NULL, STATUS_INVALID_PARAMETER_2);
|
|
|
|
}
|
|
|
|
//
|
|
// create the Open Channel message structure
|
|
//
|
|
OpenChannelCmdSize = sizeof(SAC_CMD_OPEN_CHANNEL);
|
|
OpenChannelCmd = (PSAC_CMD_OPEN_CHANNEL)KSAC_API_ALLOCATE_MEMORY(OpenChannelCmdSize);
|
|
|
|
ASSERT(OpenChannelCmd);
|
|
if (!OpenChannelCmd) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
RtlZeroMemory(OpenChannelCmd, OpenChannelCmdSize);
|
|
|
|
//
|
|
// default: we failed
|
|
//
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
//
|
|
// Attempt to open the new channel
|
|
//
|
|
do {
|
|
|
|
//
|
|
// initialize the Open Channel message structure
|
|
//
|
|
OpenChannelCmd->Attributes = SacChannelAttributes;
|
|
|
|
//
|
|
// Get a handle to the SAC driver
|
|
//
|
|
Status = KSacHandleOpen(
|
|
&DriverHandle,
|
|
&SacEventHandle,
|
|
&SacEvent
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Send down an IOCTL for opening a channel
|
|
//
|
|
Status = ZwDeviceIoControlFile(
|
|
DriverHandle,
|
|
SacEventHandle,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_SAC_OPEN_CHANNEL,
|
|
OpenChannelCmd,
|
|
OpenChannelCmdSize,
|
|
&OpenChannelRsp,
|
|
sizeof(OpenChannelRsp)
|
|
);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TimeOut.QuadPart = Int32x32To64((LONG)90000, -1000);
|
|
|
|
Status = KeWaitForSingleObject(
|
|
SacEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&TimeOut
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
KSacClose(
|
|
&DriverHandle,
|
|
&SacEventHandle,
|
|
&SacEvent
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// the new channel was created, so pass back the handle to it
|
|
//
|
|
SacChannelHandle->ChannelHandle->DriverHandle = DriverHandle;
|
|
SacChannelHandle->ChannelHandle->ChannelHandle = OpenChannelRsp.Handle;
|
|
SacChannelHandle->SacEventHandle = SacEventHandle;
|
|
SacChannelHandle->SacEvent = SacEvent;
|
|
|
|
} while ( FALSE );
|
|
|
|
//
|
|
// we are done with the cmd structure
|
|
//
|
|
FREE_POOL(OpenChannelCmd);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelClose(
|
|
IN OUT PKSAC_CHANNEL_HANDLE SacChannelHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
SAC_CMD_CLOSE_CHANNEL CloseChannelCmd;
|
|
|
|
KSAC_VALIDATE_CHANNEL_HANDLE(SacChannelHandle);
|
|
|
|
//
|
|
// Get the channel handle
|
|
//
|
|
CloseChannelCmd.Handle.ChannelHandle = SacChannelHandle->ChannelHandle->ChannelHandle;
|
|
|
|
//
|
|
// Send down an IOCTL for closing a channel
|
|
//
|
|
Status = ZwDeviceIoControlFile(
|
|
SacChannelHandle->ChannelHandle->DriverHandle,
|
|
SacChannelHandle->SacEventHandle,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_SAC_CLOSE_CHANNEL,
|
|
&CloseChannelCmd,
|
|
sizeof(CloseChannelCmd),
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TimeOut.QuadPart = Int32x32To64((LONG)90000, -1000);
|
|
|
|
Status = KeWaitForSingleObject(
|
|
SacChannelHandle->SacEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&TimeOut
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Close the driver handle
|
|
//
|
|
KSacHandleClose(
|
|
&SacChannelHandle->ChannelHandle->DriverHandle,
|
|
&SacChannelHandle->SacEventHandle,
|
|
&SacChannelHandle->SacEvent
|
|
);
|
|
|
|
//
|
|
// Null the channel handle since it is no longer valid
|
|
//
|
|
RtlZeroMemory(SacChannelHandle, sizeof(KSAC_CHANNEL_HANDLE));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelWrite(
|
|
IN PKSAC_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
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
ULONG WriteChannelCmdSize;
|
|
PSAC_CMD_WRITE_CHANNEL WriteChannelCmd;
|
|
|
|
KSAC_VALIDATE_CHANNEL_HANDLE(SacChannelHandle);
|
|
KSAC_API_ASSERT(Buffer, STATUS_INVALID_PARAMETER_2);
|
|
|
|
//
|
|
// initialize the Write To Channel message structure
|
|
//
|
|
WriteChannelCmdSize = sizeof(SAC_CMD_WRITE_CHANNEL) + (BufferSize * sizeof(UCHAR));
|
|
WriteChannelCmd = (PSAC_CMD_WRITE_CHANNEL)KSAC_API_ALLOCATE_MEMORY(WriteChannelCmdSize);
|
|
KSAC_API_ASSERT(WriteChannelCmd, FALSE);
|
|
|
|
//
|
|
// Zero the command structure
|
|
//
|
|
RtlZeroMemory(WriteChannelCmd, WriteChannelCmdSize);
|
|
|
|
//
|
|
// 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
|
|
//
|
|
WriteChannelCmd->Buffer = Buffer;
|
|
|
|
//
|
|
// Indicate which channel this command is for
|
|
//
|
|
WriteChannelCmd->Handle.ChannelHandle = SacChannelHandle->ChannelHandle->ChannelHandle;
|
|
|
|
//
|
|
// Send the string to the channel
|
|
//
|
|
Status = ZwDeviceIoControlFile(
|
|
SacChannelHandle->ChannelHandle->DriverHandle,
|
|
SacChannelHandle->SacEventHandle,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_SAC_WRITE_CHANNEL,
|
|
WriteChannelCmd,
|
|
WriteChannelCmdSize,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TimeOut.QuadPart = Int32x32To64((LONG)90000, -1000);
|
|
|
|
Status = KeWaitForSingleObject(
|
|
SacChannelHandle->SacEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&TimeOut
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelRawWrite(
|
|
IN KSAC_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
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// relay the write to the actual write routine
|
|
//
|
|
|
|
return KSacChannelWrite(
|
|
SacChannelHandle,
|
|
Buffer,
|
|
BufferSize
|
|
);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelVTUTF8WriteString(
|
|
IN KSAC_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;
|
|
|
|
//
|
|
// Treating the String as a data buffer, we calculate it's size
|
|
// not including the null termination
|
|
//
|
|
|
|
BufferSize = wcslen(String) * sizeof(WCHAR);
|
|
|
|
KSAC_API_ASSERT(BufferSize > 0, FALSE);
|
|
|
|
//
|
|
// Write the data to the channel
|
|
//
|
|
|
|
Status = SacChannelWrite(
|
|
SacChannelHandle,
|
|
(PCBYTE)String,
|
|
BufferSize
|
|
);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelVTUTF8Write(
|
|
IN KSAC_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
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// relay the write to the actual write routine
|
|
//
|
|
|
|
return KSacChannelWrite(
|
|
SacChannelHandle,
|
|
(PCBYTE)Buffer,
|
|
BufferSize
|
|
);
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelHasNewData(
|
|
IN PKSAC_CHANNEL_HANDLE SacChannelHandle,
|
|
OUT PBOOLEAN 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
|
|
|
|
--*/
|
|
|
|
{
|
|
HEADLESS_RSP_POLL Response;
|
|
NTSTATUS Status;
|
|
SIZE_T Length;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
SAC_CMD_POLL_CHANNEL PollChannelCmd;
|
|
SAC_RSP_POLL_CHANNEL PollChannelRsp;
|
|
|
|
KSAC_VALIDATE_KSAC_CHANNEL_HANDLE(SacChannelHandle);
|
|
|
|
//
|
|
// Initialize the Poll command
|
|
//
|
|
RtlZeroMemory(&PollChannelCmd, sizeof(SAC_RSP_POLL_CHANNEL));
|
|
|
|
PollChannelCmd.Handle.ChannelHandle = SacChannelHandle->ChannelHandle->ChannelHandle;
|
|
|
|
//
|
|
// Send down an IOCTL for polling a channel
|
|
//
|
|
Status = ZwDeviceIoControlFile(
|
|
SacChannelHandle->ChannelHandle->DriverHandle,
|
|
SacChannelHandle->SacEventHandle,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_SAC_POLL_CHANNEL,
|
|
&PollChannelCmd,
|
|
sizeof(PollChannelCmd),
|
|
&PollChannelRsp,
|
|
sizeof(PollChannelRsp)
|
|
);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TimeOut.QuadPart = Int32x32To64((LONG)90000, -1000);
|
|
|
|
Status = KeWaitForSingleObject(
|
|
SacChannelHandle->SacEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&TimeOut
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Return the status to the user
|
|
//
|
|
if (NT_SUCCESS(Status)) {
|
|
*InputWaiting = PollChannelRsp.InputWaiting;
|
|
} else {
|
|
*InputWaiting = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelRead(
|
|
IN PKSAC_CHANNEL_HANDLE SacChannelHandle,
|
|
IN PCBYTE 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
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR Byte;
|
|
BOOLEAN Success;
|
|
TIME_FIELDS StartTime;
|
|
TIME_FIELDS EndTime;
|
|
HEADLESS_RSP_GET_BYTE Response;
|
|
SIZE_T Length;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
SAC_CMD_READ_CHANNEL ReadChannelCmd;
|
|
ULONG ReadChannelRspSize;
|
|
PSAC_RSP_READ_CHANNEL ReadChannelRsp;
|
|
|
|
KSAC_VALIDATE_KSAC_CHANNEL_HANDLE(SacChannelHandle);
|
|
KSAC_API_ASSERT(Buffer, STATUS_INVALID_PARAMETER_2);
|
|
KSAC_API_ASSERT(BufferSize > 0, STATUS_INVALID_PARAMETER_2);
|
|
|
|
//
|
|
// Initialize the IOCTL command
|
|
//
|
|
ReadChannelCmd.Handle.ChannelHandle = SacChannelHandle->ChannelHandle->ChannelHandle;
|
|
|
|
//
|
|
// Initialize the IOCTL response
|
|
//
|
|
ReadChannelRsp = (PSAC_RSP_READ_CHANNEL)Buffer;
|
|
|
|
//
|
|
// Send down an IOCTL for reading a channel
|
|
//
|
|
Status = ZwDeviceIoControlFile(
|
|
SacChannelHandle->ChannelHandle->DriverHandle,
|
|
SacChannelHandle->SacEventHandle,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_SAC_READ_CHANNEL,
|
|
&ReadChannelCmd,
|
|
sizeof(ReadChannelCmd),
|
|
ReadChannelRsp,
|
|
ReadChannelRspSize
|
|
);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TimeOut.QuadPart = Int32x32To64((LONG)90000, -1000);
|
|
|
|
Status = KeWaitForSingleObject(
|
|
SacChannelHandle->SacEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&TimeOut
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelVTUTF8Read(
|
|
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
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return KSacChannelRead(
|
|
SacChannelHandle,
|
|
(PBYTE)Buffer,
|
|
BufferSize,
|
|
ByteCount
|
|
);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
KSacChannelRawRead(
|
|
IN KSAC_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
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return KSacChannelRead(
|
|
SacChannelHandle,
|
|
Buffer,
|
|
BufferSize,
|
|
ByteCount
|
|
);
|
|
|
|
}
|
|
|