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.
2634 lines
67 KiB
2634 lines
67 KiB
/*++
|
|
|
|
Copyright (c) 1998-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
w32drprt
|
|
|
|
Abstract:
|
|
|
|
This module defines the parent for the Win32 client-side RDP
|
|
Port Redirection "device" class hierarchy, W32DrPRT.
|
|
|
|
Author:
|
|
|
|
Tad Brockway 4/21/99
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precom.h>
|
|
|
|
#define TRC_FILE "W32DrPRT"
|
|
|
|
#include "w32drprt.h"
|
|
#include "proc.h"
|
|
#include "drdbg.h"
|
|
#include "utl.h"
|
|
|
|
#ifdef OS_WINCE
|
|
#include "wceinc.h"
|
|
#endif
|
|
|
|
#if DBG
|
|
#include "tracecom.h"
|
|
#endif
|
|
|
|
//
|
|
// COM port initialization default values.
|
|
//
|
|
// These value are copied from
|
|
// \\muroc\slm\proj\win\src\CORE\SPOOL32\SPOOLSS\newdll\localmon.c
|
|
//
|
|
#define WRITE_TOTAL_TIMEOUT 60000 // 60 seconds localmon.c uses 3 seconds, but
|
|
// this doesn't work in 9x. An application that
|
|
// is aware that it is opening a serial device
|
|
// will override this, so it only really applies
|
|
// to serial printer redirection.
|
|
#define READ_TOTAL_TIMEOUT 5000 // 5 seconds
|
|
#define READ_INTERVAL_TIMEOUT 200 // 0.2 second
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
//
|
|
// W32DrPRT Members
|
|
//
|
|
// Subclass off of the async parent device in CE because
|
|
// overlapped IO is not supported. Non-overlapped IO doesn't
|
|
// work right with the NT serial driver, so we need to use
|
|
// overlapped IO in this case.
|
|
//
|
|
|
|
W32DrPRT::W32DrPRT(ProcObj *processObject, const DRSTRING portName,
|
|
ULONG deviceID, const TCHAR *devicePath) :
|
|
#ifdef OS_WINCE
|
|
W32DrDeviceAsync(processObject, deviceID, devicePath),
|
|
#else
|
|
W32DrDeviceOverlapped(processObject, deviceID, devicePath),
|
|
#endif
|
|
DrPRT(portName, processObject)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor
|
|
|
|
Arguments:
|
|
|
|
processObject - Associated Process Object
|
|
portName - Name of the port.
|
|
deviceID - Device ID for the port.
|
|
devicePath - Path that can be opened via CreateFile for port.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::W32DrPRT");
|
|
|
|
//
|
|
// Do nothing for now.
|
|
//
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
W32DrPRT::~W32DrPRT()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor
|
|
|
|
Arguments:
|
|
|
|
NA
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::~W32DrPRT");
|
|
|
|
//
|
|
// Do nothing for now.
|
|
//
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
DRPORTHANDLE W32DrPRT::GetPortHandle(ULONG FileId)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get Port's Open Handle
|
|
|
|
Arguments:
|
|
|
|
File Id from server
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
|
|
{
|
|
DrFile *pFile;
|
|
|
|
pFile = _FileMgr->GetObject(FileId);
|
|
|
|
if (pFile) {
|
|
return pFile->GetFileHandle();
|
|
}
|
|
else {
|
|
return INVALID_TSPORTHANDLE;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
W32DrPRT::MsgIrpDeviceControl(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
|
|
IN UINT32 packetLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handles Port IOCTL's
|
|
|
|
Arguments:
|
|
|
|
pIoRequestPacket - Request packet received from server.
|
|
packetLen - Length of teh packet
|
|
|
|
Return Value:
|
|
|
|
The size (in bytes) of a device announce packet for this device.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::MsgIrpDeviceControl");
|
|
|
|
//
|
|
// Give the parent DrPRT class a shot at decoding the IOCTL
|
|
// into the correct COMM function.
|
|
//
|
|
if (MsgIrpDeviceControlTranslate(pIoRequestPacket)) {
|
|
TRC_DBG((TB, _T("Successfully decoded IOCTL.")));
|
|
}
|
|
//
|
|
// Otherwise, we will just pass it on to the driver.
|
|
//
|
|
else {
|
|
DispatchIOCTLDirectlyToDriver(pIoRequestPacket);
|
|
}
|
|
DC_END_FN();
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
HANDLE
|
|
W32DrPRT::StartWaitOnMaskFunc(
|
|
IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
|
|
OUT DWORD *status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Asynchronously handle a "wait on mask" function.
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
status - Return status for IO request in the form of a windows
|
|
error code.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
ULONG replyPacketSize = 0;
|
|
LPDWORD serverEventMask;
|
|
PBYTE outputBuf;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::StartWaitOnMaskFunc");
|
|
|
|
*status = ERROR_SUCCESS;
|
|
|
|
// Assert the integrity of the IO context
|
|
ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = ¶ms->pIoRequestPacket->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
replyPacketSize = DR_IOCTL_REPLYBUFSIZE(pIoRequest);
|
|
pReplyPacket = DrUTL_AllocIOCompletePacket(
|
|
params->pIoRequestPacket,
|
|
replyPacketSize
|
|
);
|
|
if (pReplyPacket == NULL) {
|
|
*status = ERROR_NOT_ENOUGH_MEMORY;
|
|
TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Save the reply packet info to the context for this IO operation.
|
|
//
|
|
params->pIoReplyPacket = pReplyPacket;
|
|
params->IoReplyPacketSize = replyPacketSize;
|
|
|
|
//
|
|
// Create an event for the overlapped IO.
|
|
//
|
|
memset(¶ms->overlapped, 0, sizeof(params->overlapped));
|
|
params->overlapped.hEvent = CreateEvent(
|
|
NULL, // no attribute.
|
|
TRUE, // manual reset.
|
|
FALSE, // initially not signalled.
|
|
NULL // no name.
|
|
);
|
|
if (params->overlapped.hEvent == NULL) {
|
|
TRC_ERR((TB, _T("Failed to create event")));
|
|
*status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the output buffer and server's event mask.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverEventMask = (LPDWORD)outputBuf;
|
|
|
|
//
|
|
// Use WaitCommEvent to handle the request.
|
|
//
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
if (!WaitCommEvent(FileHandle, serverEventMask, ¶ms->overlapped)) {
|
|
//
|
|
// If IO is pending.
|
|
//
|
|
*status = GetLastError();
|
|
if (*status == ERROR_IO_PENDING) {
|
|
TRC_NRM((TB, _T("Pending IO.")));
|
|
}
|
|
else {
|
|
TRC_ERR((TB, _T("Error %ld."), *status));
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Completed synchronously.")));
|
|
*status = ERROR_SUCCESS;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// If IO is pending, return the handle to the pending IO.
|
|
//
|
|
if (*status == ERROR_IO_PENDING) {
|
|
DC_END_FN();
|
|
return params->overlapped.hEvent;
|
|
}
|
|
//
|
|
// Otherwise, return NULL so that the CompleteIOFunc can be called
|
|
// to send the results to the server.
|
|
//
|
|
else {
|
|
if (params->overlapped.hEvent != NULL) {
|
|
CloseHandle(params->overlapped.hEvent);
|
|
params->overlapped.hEvent = NULL;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return NULL;
|
|
}
|
|
}
|
|
HANDLE
|
|
W32DrPRT::_StartWaitOnMaskFunc(
|
|
IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
|
|
OUT DWORD *status
|
|
)
|
|
{
|
|
return ((W32DrPRT*)params->pObject)->StartWaitOnMaskFunc(params, status);
|
|
}
|
|
|
|
#else // Windows CE
|
|
|
|
HANDLE
|
|
W32DrPRT::StartWaitOnMaskFunc(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params,
|
|
OUT DWORD *status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Asynchronously handle a "wait on mask" function. Can't use overlapped
|
|
IO in CE, so we will use a pooled thread.
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
status - Return status for IO request in the form of a windows
|
|
error code.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
ULONG replyPacketSize = 0;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::_StartWaitOnMaskFunc");
|
|
|
|
*status = ERROR_SUCCESS;
|
|
|
|
// Assert the integrity of the IO context
|
|
ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = ¶ms->pIoRequestPacket->IoRequest;
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
replyPacketSize = DR_IOCTL_REPLYBUFSIZE(pIoRequest);
|
|
pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
|
|
replyPacketSize) ;
|
|
if (pReplyPacket == NULL) {
|
|
*status = ERROR_NOT_ENOUGH_MEMORY;
|
|
TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Save the reply packet info to the context for this IO operation.
|
|
//
|
|
params->pIoReplyPacket = pReplyPacket;
|
|
params->IoReplyPacketSize = replyPacketSize;
|
|
|
|
//
|
|
// Hand a read request off to the thread pool.
|
|
//
|
|
params->completionEvent = CreateEvent(
|
|
NULL, // no attribute.
|
|
TRUE, // manual reset.
|
|
FALSE, // initially not signalled.
|
|
NULL // no name.
|
|
);
|
|
if (params->completionEvent == NULL) {
|
|
*status = GetLastError();
|
|
TRC_ERR((TB, _T("Error in CreateEvent: %08X."), *status));
|
|
}
|
|
else {
|
|
params->thrPoolReq = _threadPool->SubmitRequest(
|
|
_AsyncWaitOnMaskFunc, params,
|
|
params->completionEvent
|
|
);
|
|
|
|
if (params->thrPoolReq == INVALID_THREADPOOLREQUEST) {
|
|
*status = ERROR_SERVICE_NO_THREAD;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// If IO is pending, return the handle to the pending IO.
|
|
//
|
|
if (params->thrPoolReq != INVALID_THREADPOOLREQUEST) {
|
|
*status = ERROR_IO_PENDING;
|
|
DC_END_FN();
|
|
return params->completionEvent;
|
|
}
|
|
//
|
|
// Otherwise, clean up the event handle and return NULL so that the
|
|
// CompleteIOFunc can be called to send the results to the server.
|
|
//
|
|
else {
|
|
|
|
if (params->completionEvent != NULL) {
|
|
CloseHandle(params->completionEvent);
|
|
params->completionEvent = NULL;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return NULL;
|
|
}
|
|
}
|
|
HANDLE
|
|
W32DrPRT::_StartWaitOnMaskFunc(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params,
|
|
OUT DWORD *status
|
|
)
|
|
{
|
|
return ((W32DrPRT*)params->pObject)->StartWaitOnMaskFunc(params, status);
|
|
}
|
|
|
|
DWORD
|
|
W32DrPRT::AsyncWaitOnMaskFunc(
|
|
IN W32DRDEV_ASYNCIO_PARAMS *params
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Start an asynchronous "wait on mask operation." Can't use
|
|
overlapped IO for this function, so we run it in a pooled thread.
|
|
|
|
Arguments:
|
|
|
|
params - Context for the IO request.
|
|
|
|
Return Value:
|
|
|
|
Returns a handle the pending IO object if the operation did not
|
|
complete. Otherwise, NULL is returned.
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
|
|
LPDWORD serverEventMask;
|
|
PBYTE outputBuf;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::AsyncWaitOnMaskFunc");
|
|
|
|
//
|
|
// Assert the integrity of the IO context
|
|
//
|
|
ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = ¶ms->pIoRequestPacket->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
|
|
//
|
|
// Get a pointer to the output buffer and server's event mask.
|
|
//
|
|
pReplyPacket = params->pIoReplyPacket;
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverEventMask = (LPDWORD)outputBuf;
|
|
|
|
//
|
|
// Use WaitCommEvent to handle the request.
|
|
//
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
if (!WaitCommEvent(FileHandle, serverEventMask, NULL)) {
|
|
status = GetLastError();
|
|
TRC_ERR((TB, _T("Error %ld."), status));
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Completed successfully.")));
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return status;
|
|
}
|
|
DWORD
|
|
W32DrPRT::_AsyncWaitOnMaskFunc(
|
|
IN PVOID params,
|
|
IN HANDLE cancelEvent
|
|
)
|
|
{
|
|
return ((W32DrPRT*)(((W32DRDEV_ASYNCIO_PARAMS *)params)->pObject))->AsyncWaitOnMaskFunc(
|
|
(W32DRDEV_ASYNCIO_PARAMS *)params);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
W32DrPRT::SerialSetTimeouts(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Set Timeouts Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
COMMTIMEOUTS commTimeouts;
|
|
PSERIAL_TIMEOUTS newTimeouts;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialSetTimeouts");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_TIMEOUTS));
|
|
|
|
//
|
|
// Get a pointer to the input buffer.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
|
|
//
|
|
// Error check the timeout settings.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
newTimeouts = (PSERIAL_TIMEOUTS)inputBuf;
|
|
if ((newTimeouts->ReadIntervalTimeout == MAXULONG) &&
|
|
(newTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
|
|
(newTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
|
|
TRC_ERR((TB, _T("Invalid timeout parameters.")));
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the new timeouts.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
commTimeouts.ReadIntervalTimeout = newTimeouts->ReadIntervalTimeout;
|
|
commTimeouts.ReadTotalTimeoutMultiplier = newTimeouts->ReadTotalTimeoutMultiplier;
|
|
commTimeouts.ReadTotalTimeoutConstant = newTimeouts->ReadTotalTimeoutConstant;
|
|
commTimeouts.WriteTotalTimeoutMultiplier = newTimeouts->WriteTotalTimeoutMultiplier;
|
|
commTimeouts.WriteTotalTimeoutConstant = newTimeouts->WriteTotalTimeoutConstant;
|
|
|
|
if (!SetCommTimeouts(FileHandle, &commTimeouts)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("SetCommTimeouts failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetTimeouts(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Timeouts Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
PSERIAL_TIMEOUTS st;
|
|
COMMTIMEOUTS ct;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetTimeouts");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_TIMEOUTS));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current timeout values.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer and the server timeout values.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
st = (PSERIAL_TIMEOUTS)outputBuf;
|
|
|
|
//
|
|
// Get the client timeout values.
|
|
//
|
|
if (GetCommTimeouts(FileHandle, &ct)) {
|
|
|
|
st->ReadIntervalTimeout = ct.ReadIntervalTimeout;
|
|
st->ReadTotalTimeoutMultiplier = ct.ReadTotalTimeoutMultiplier;
|
|
st->ReadTotalTimeoutConstant = ct.ReadTotalTimeoutConstant;
|
|
st->WriteTotalTimeoutMultiplier = ct.WriteTotalTimeoutMultiplier;
|
|
st->WriteTotalTimeoutConstant = ct.WriteTotalTimeoutConstant;
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(SERIAL_TIMEOUTS);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommTimeouts failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialSetChars(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Set Chars Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DCB dcb;
|
|
PSERIAL_CHARS serverChars;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialSetChars");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_CHARS));
|
|
|
|
//
|
|
// Get a pointer to the input buffer and the server serial characters
|
|
// buffer.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
serverChars = (PSERIAL_CHARS)inputBuf;
|
|
|
|
//
|
|
// Get the current DCB.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (!GetCommState(FileHandle, &dcb)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the comm chars and update the DCB.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
dcb.XonChar = serverChars->XonChar;
|
|
dcb.XoffChar = serverChars->XoffChar;
|
|
dcb.ErrorChar = serverChars->ErrorChar;
|
|
dcb.ErrorChar = serverChars->BreakChar;
|
|
dcb.EofChar = serverChars->EofChar;
|
|
dcb.EvtChar = serverChars->EventChar;
|
|
|
|
if (!SetCommState(FileHandle, &dcb)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("SetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetChars(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Chars Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DCB dcb;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
PSERIAL_CHARS serverChars;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetChars");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_CHARS));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current DCB and grab the control character params.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer and control charcter params.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverChars = (PSERIAL_CHARS)outputBuf;
|
|
|
|
if (GetCommState(FileHandle, &dcb)) {
|
|
|
|
serverChars->XonChar = dcb.XonChar;
|
|
serverChars->XoffChar = dcb.XoffChar;
|
|
serverChars->ErrorChar = dcb.ErrorChar;
|
|
serverChars->BreakChar = dcb.ErrorChar;
|
|
serverChars->EofChar = dcb.EofChar;
|
|
serverChars->EventChar = dcb.EvtChar;
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(SERIAL_CHARS);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
void
|
|
W32DrPRT::SerialResetDevice(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Reset Device Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::SerialResetDevice");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Send the escape code to the serial port.
|
|
//
|
|
SerialHandleEscapeCode(pIoReq, RESETDEV);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialSetQueueSize(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Set Queue Size Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSERIAL_QUEUE_SIZE serverQueueSize;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialSetQueueSize");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_QUEUE_SIZE));
|
|
|
|
//
|
|
// Get a pointer to the input buffer and the server serial characters
|
|
// buffer.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
serverQueueSize = (PSERIAL_QUEUE_SIZE)inputBuf;
|
|
|
|
//
|
|
// Set the queue size.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
if (!SetupComm(FileHandle, serverQueueSize->InSize,
|
|
serverQueueSize->OutSize)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("SetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetWaitMask(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Handle Serial Port Get Wait Mask Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
ULONG *serverWaitMask;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetWaitMask");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(ULONG));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current wait mask.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's wait mask.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverWaitMask = (ULONG *)outputBuf;
|
|
|
|
if (GetCommMask(FileHandle, serverWaitMask)) {
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(ULONG);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommMask failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialSetWaitMask(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Set Wait Mask Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG *serverWaitMask;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialSetWaitMask");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(ULONG));
|
|
|
|
//
|
|
// Get a pointer to the input buffer server's wait mask.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
serverWaitMask = (ULONG *)inputBuf;
|
|
|
|
//
|
|
// Set the mask.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (!SetCommMask(FileHandle, *serverWaitMask)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("SetCommMask failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialWaitOnMask(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Wait on Mask Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
#ifdef OS_WINCE
|
|
W32DRDEV_ASYNCIO_PARAMS *params = NULL;
|
|
#else
|
|
W32DRDEV_OVERLAPPEDIO_PARAMS *params = NULL;
|
|
#endif
|
|
|
|
DWORD ntStatus;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialWaitOnMask");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(DWORD));
|
|
|
|
//
|
|
// Allocate and dispatch an asynchronous IO request.
|
|
//
|
|
if (status == ERROR_SUCCESS) {
|
|
#ifdef OS_WINCE
|
|
params = new W32DRDEV_ASYNCIO_PARAMS(this, pIoReq);
|
|
#else
|
|
params = new W32DRDEV_OVERLAPPEDIO_PARAMS(this, pIoReq);
|
|
#endif
|
|
if (params != NULL ) {
|
|
status = ProcessObject()->DispatchAsyncIORequest(
|
|
(RDPAsyncFunc_StartIO)
|
|
W32DrPRT::_StartWaitOnMaskFunc,
|
|
(RDPAsyncFunc_IOComplete)_CompleteIOFunc,
|
|
(RDPAsyncFunc_IOCancel)_CancelIOFunc,
|
|
params
|
|
);
|
|
}
|
|
else {
|
|
TRC_ERR((TB, _T("Memory alloc failed.")));
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Translate to a Windows error status.
|
|
//
|
|
ntStatus = TranslateWinError(status);
|
|
|
|
//
|
|
// Clean up on error.
|
|
//
|
|
if (status != ERROR_SUCCESS) {
|
|
if (params != NULL) {
|
|
delete params;
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
DefaultIORequestMsgHandle(pIoReq, ntStatus);
|
|
}
|
|
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, ntStatus);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialPurge(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Serial Purge Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DWORD *purgeFlags;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialPurge");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(DWORD));
|
|
|
|
//
|
|
// Get a pointer to the input buffer and purge flags.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
purgeFlags = (DWORD *)inputBuf;
|
|
|
|
//
|
|
// Purge.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (!PurgeComm(FileHandle, *purgeFlags)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("PurgeComm failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetHandflow(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Handflow Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DCB dcb;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
PSERIAL_HANDFLOW handFlow;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetHandflow");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_HANDFLOW));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current DCB.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's serial hand flow struct.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
handFlow = (PSERIAL_HANDFLOW)outputBuf;
|
|
|
|
if (GetCommState(FileHandle, &dcb)) {
|
|
//
|
|
// Set the hand flow fields based on the current value of fields
|
|
// in the DCB.
|
|
//
|
|
|
|
memset(handFlow, 0, sizeof(SERIAL_HANDFLOW));
|
|
|
|
//
|
|
// RTS Settings
|
|
//
|
|
handFlow->FlowReplace &= ~SERIAL_RTS_MASK;
|
|
switch (dcb.fRtsControl) {
|
|
case RTS_CONTROL_DISABLE:
|
|
break;
|
|
case RTS_CONTROL_ENABLE:
|
|
handFlow->FlowReplace |= SERIAL_RTS_CONTROL;
|
|
break;
|
|
case RTS_CONTROL_HANDSHAKE:
|
|
handFlow->FlowReplace |= SERIAL_RTS_HANDSHAKE;
|
|
break;
|
|
case RTS_CONTROL_TOGGLE:
|
|
handFlow->FlowReplace |= SERIAL_TRANSMIT_TOGGLE;
|
|
break;
|
|
default:
|
|
// Don't think this should ever happen?
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
//
|
|
// DTR Settings
|
|
//
|
|
handFlow->ControlHandShake &= ~SERIAL_DTR_MASK;
|
|
switch (dcb.fDtrControl) {
|
|
case DTR_CONTROL_DISABLE:
|
|
break;
|
|
case DTR_CONTROL_ENABLE:
|
|
handFlow->ControlHandShake |= SERIAL_DTR_CONTROL;
|
|
break;
|
|
case DTR_CONTROL_HANDSHAKE:
|
|
handFlow->ControlHandShake |= SERIAL_DTR_HANDSHAKE;
|
|
break;
|
|
default:
|
|
// Don't think this should ever happen?
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (dcb.fDsrSensitivity) {
|
|
handFlow->ControlHandShake |= SERIAL_DSR_SENSITIVITY;
|
|
}
|
|
|
|
if (dcb.fOutxCtsFlow) {
|
|
handFlow->ControlHandShake |= SERIAL_CTS_HANDSHAKE;
|
|
}
|
|
|
|
if (dcb.fOutxDsrFlow) {
|
|
handFlow->ControlHandShake |= SERIAL_DSR_HANDSHAKE;
|
|
}
|
|
|
|
if (dcb.fOutX) {
|
|
handFlow->FlowReplace |= SERIAL_AUTO_TRANSMIT;
|
|
}
|
|
|
|
if (dcb.fInX) {
|
|
handFlow->FlowReplace |= SERIAL_AUTO_RECEIVE;
|
|
}
|
|
|
|
if (dcb.fNull) {
|
|
handFlow->FlowReplace |= SERIAL_NULL_STRIPPING;
|
|
}
|
|
|
|
if (dcb.fErrorChar) {
|
|
handFlow->FlowReplace |= SERIAL_ERROR_CHAR;
|
|
}
|
|
|
|
if (dcb.fTXContinueOnXoff) {
|
|
handFlow->FlowReplace |= SERIAL_XOFF_CONTINUE;
|
|
}
|
|
|
|
if (dcb.fAbortOnError) {
|
|
handFlow->ControlHandShake |= SERIAL_ERROR_ABORT;
|
|
}
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(SERIAL_HANDFLOW);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialSetHandflow(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Set Handflow Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PBYTE inputBuf;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DCB dcb;
|
|
PSERIAL_HANDFLOW handFlow;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialSetHandflow");
|
|
|
|
//
|
|
// Check the size of the incoming request.
|
|
//
|
|
status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_HANDFLOW));
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Get a pointer to the input buffer and the server serial characters
|
|
// buffer.
|
|
//
|
|
inputBuf = (PBYTE)(pIoReq + 1);
|
|
handFlow = (PSERIAL_HANDFLOW)inputBuf;
|
|
|
|
//
|
|
// Get the current DCB.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (!GetCommState(FileHandle, &dcb)) {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update the DCB based on the new server-side handflow values.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (handFlow->ControlHandShake & SERIAL_CTS_HANDSHAKE) {
|
|
dcb.fOutxCtsFlow = TRUE;
|
|
}
|
|
|
|
if (handFlow->ControlHandShake & SERIAL_DSR_HANDSHAKE) {
|
|
dcb.fOutxDsrFlow = TRUE;
|
|
}
|
|
|
|
if (handFlow->FlowReplace & SERIAL_AUTO_TRANSMIT) {
|
|
dcb.fOutX = TRUE;
|
|
}
|
|
|
|
if (handFlow->FlowReplace & SERIAL_AUTO_RECEIVE) {
|
|
dcb.fInX = TRUE;
|
|
}
|
|
|
|
if (handFlow->FlowReplace & SERIAL_NULL_STRIPPING) {
|
|
dcb.fNull = TRUE;
|
|
}
|
|
|
|
if (handFlow->FlowReplace & SERIAL_ERROR_CHAR) {
|
|
dcb.fErrorChar = TRUE;
|
|
}
|
|
|
|
if (handFlow->FlowReplace & SERIAL_XOFF_CONTINUE) {
|
|
dcb.fTXContinueOnXoff = TRUE;
|
|
}
|
|
|
|
if (handFlow->ControlHandShake & SERIAL_ERROR_ABORT) {
|
|
dcb.fAbortOnError = TRUE;
|
|
}
|
|
|
|
switch (handFlow->FlowReplace & SERIAL_RTS_MASK) {
|
|
case 0:
|
|
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
|
break;
|
|
case SERIAL_RTS_CONTROL:
|
|
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
|
break;
|
|
case SERIAL_RTS_HANDSHAKE:
|
|
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
|
break;
|
|
case SERIAL_TRANSMIT_TOGGLE:
|
|
dcb.fRtsControl = RTS_CONTROL_TOGGLE;
|
|
break;
|
|
}
|
|
|
|
switch (handFlow->ControlHandShake & SERIAL_DTR_MASK) {
|
|
case 0:
|
|
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
|
break;
|
|
case SERIAL_DTR_CONTROL:
|
|
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
|
break;
|
|
case SERIAL_DTR_HANDSHAKE:
|
|
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
|
break;
|
|
}
|
|
|
|
dcb.fDsrSensitivity =
|
|
(handFlow->ControlHandShake & SERIAL_DSR_SENSITIVITY)?(TRUE):(FALSE);
|
|
dcb.XonLim = (WORD)handFlow->XonLimit;
|
|
dcb.XoffLim = (WORD)handFlow->XoffLimit;
|
|
}
|
|
|
|
//
|
|
// Update the DCB.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
if (!SetCommState(FileHandle, &dcb)) {
|
|
DWORD err = GetLastError();
|
|
TRC_NRM((TB, _T("SetCommState failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetModemStatus(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Modem Status Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
LPDWORD modemStatus;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetModemStatus");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(DWORD));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current modem status.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's modem status.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
modemStatus = (LPDWORD)outputBuf;
|
|
|
|
if (GetCommModemStatus(FileHandle, modemStatus)) {
|
|
TRC_NRM((TB, _T("GetCommModemStatus result: 0x%08x"), *modemStatus));
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(DWORD);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ERR((TB, _T("GetCommModemStatus failed with 0x%08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetDTRRTS(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get DTRRRTS Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// This IOCTL is not supported by Win32 COMM functions. What
|
|
// else can we do, but pass it directly to the driver. We should ASSERT
|
|
// to find out under which circumstances this happens, however.
|
|
//
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetDTRRTS");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
ASSERT(FALSE);
|
|
DispatchIOCTLDirectlyToDriver(pIoReq);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetCommStatus(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Comm Status Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
PSERIAL_STATUS serverCommStatus;
|
|
COMSTAT localStatus;
|
|
DWORD errors;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetCommStatus");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_STATUS));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current communications status (via the ClearCommError API).
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's modem status.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverCommStatus = (PSERIAL_STATUS)outputBuf;
|
|
|
|
if (ClearCommError(FileHandle, &errors, &localStatus)) {
|
|
//
|
|
// Convert to server-representation of communication status.
|
|
//
|
|
|
|
serverCommStatus->HoldReasons = 0;
|
|
if (localStatus.fCtsHold) {
|
|
serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
|
|
}
|
|
|
|
if (localStatus.fDsrHold) {
|
|
serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR;
|
|
}
|
|
|
|
if (localStatus.fRlsdHold) {
|
|
serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD;
|
|
}
|
|
|
|
if (localStatus.fXoffHold) {
|
|
serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
|
|
}
|
|
|
|
if (localStatus.fXoffSent) {
|
|
serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
|
|
}
|
|
|
|
serverCommStatus->EofReceived = (BOOLEAN)localStatus.fEof;
|
|
serverCommStatus->WaitForImmediate = (BOOLEAN)localStatus.fTxim;
|
|
serverCommStatus->AmountInInQueue = localStatus.cbInQue;
|
|
serverCommStatus->AmountInOutQueue = localStatus.cbOutQue;
|
|
|
|
serverCommStatus->Errors = 0;
|
|
if (errors & CE_BREAK) {
|
|
serverCommStatus->Errors |= SERIAL_ERROR_BREAK;
|
|
}
|
|
|
|
if (errors & CE_FRAME) {
|
|
serverCommStatus->Errors |= SERIAL_ERROR_FRAMING;
|
|
}
|
|
|
|
if (errors & CE_OVERRUN) {
|
|
serverCommStatus->Errors |= SERIAL_ERROR_OVERRUN;
|
|
}
|
|
|
|
if (errors & CE_RXOVER) {
|
|
serverCommStatus->Errors |= SERIAL_ERROR_QUEUEOVERRUN;
|
|
}
|
|
|
|
if (errors & CE_RXPARITY) {
|
|
serverCommStatus->Errors |= SERIAL_ERROR_PARITY;
|
|
}
|
|
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(SERIAL_STATUS);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("ClearCommError failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetProperties(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Properties Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
PSERIAL_COMMPROP serverProperties;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetProperties");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Make sure that the windows defines and the NT defines are
|
|
// still in sync.
|
|
//
|
|
// Asserts are broken up because if the assert msg string is
|
|
// too long it causes a compile error
|
|
ASSERT((SERIAL_PCF_DTRDSR == PCF_DTRDSR) &&
|
|
(SERIAL_PCF_RTSCTS == PCF_RTSCTS) &&
|
|
(SERIAL_PCF_CD == PCF_RLSD) &&
|
|
(SERIAL_PCF_PARITY_CHECK == PCF_PARITY_CHECK) &&
|
|
(SERIAL_PCF_XONXOFF == PCF_XONXOFF) &&
|
|
(SERIAL_PCF_SETXCHAR == PCF_SETXCHAR) &&
|
|
(SERIAL_PCF_TOTALTIMEOUTS == PCF_TOTALTIMEOUTS) &&
|
|
(SERIAL_PCF_INTTIMEOUTS == PCF_INTTIMEOUTS) &&
|
|
(SERIAL_PCF_SPECIALCHARS == PCF_SPECIALCHARS) &&
|
|
(SERIAL_PCF_16BITMODE == PCF_16BITMODE) &&
|
|
(SERIAL_SP_PARITY == SP_PARITY) &&
|
|
(SERIAL_SP_BAUD == SP_BAUD) &&
|
|
(SERIAL_SP_DATABITS == SP_DATABITS) &&
|
|
(SERIAL_SP_STOPBITS == SP_STOPBITS) &&
|
|
(SERIAL_SP_HANDSHAKING == SP_HANDSHAKING) &&
|
|
(SERIAL_SP_PARITY_CHECK == SP_PARITY_CHECK) &&
|
|
(SERIAL_SP_CARRIER_DETECT == SP_RLSD));
|
|
ASSERT((SERIAL_BAUD_075 == BAUD_075) &&
|
|
(SERIAL_BAUD_110 == BAUD_110) &&
|
|
(SERIAL_BAUD_134_5 == BAUD_134_5) &&
|
|
(SERIAL_BAUD_150 == BAUD_150) &&
|
|
(SERIAL_BAUD_300 == BAUD_300) &&
|
|
(SERIAL_BAUD_600 == BAUD_600) &&
|
|
(SERIAL_BAUD_1200 == BAUD_1200) &&
|
|
(SERIAL_BAUD_1800 == BAUD_1800) &&
|
|
(SERIAL_BAUD_2400 == BAUD_2400) &&
|
|
(SERIAL_BAUD_4800 == BAUD_4800) &&
|
|
(SERIAL_BAUD_7200 == BAUD_7200) &&
|
|
(SERIAL_BAUD_9600 == BAUD_9600) &&
|
|
(SERIAL_BAUD_14400 == BAUD_14400) &&
|
|
(SERIAL_BAUD_19200 == BAUD_19200) &&
|
|
(SERIAL_BAUD_38400 == BAUD_38400) &&
|
|
(SERIAL_BAUD_56K == BAUD_56K) &&
|
|
(SERIAL_BAUD_57600 == BAUD_57600) &&
|
|
(SERIAL_BAUD_115200 == BAUD_115200) &&
|
|
(SERIAL_BAUD_USER == BAUD_USER) &&
|
|
(SERIAL_DATABITS_5 == DATABITS_5) &&
|
|
(SERIAL_DATABITS_6 == DATABITS_6) &&
|
|
(SERIAL_DATABITS_7 == DATABITS_7) &&
|
|
(SERIAL_DATABITS_8 == DATABITS_8) &&
|
|
(SERIAL_DATABITS_16 == DATABITS_16));
|
|
ASSERT((SERIAL_DATABITS_16X == DATABITS_16X) &&
|
|
(SERIAL_STOPBITS_10 == STOPBITS_10) &&
|
|
(SERIAL_STOPBITS_15 == STOPBITS_15) &&
|
|
(SERIAL_STOPBITS_20 == STOPBITS_20) &&
|
|
(SERIAL_PARITY_NONE == PARITY_NONE) &&
|
|
(SERIAL_PARITY_ODD == PARITY_ODD) &&
|
|
(SERIAL_PARITY_EVEN == PARITY_EVEN) &&
|
|
(SERIAL_PARITY_MARK == PARITY_MARK) &&
|
|
(SERIAL_PARITY_SPACE == PARITY_SPACE));
|
|
ASSERT((SERIAL_SP_UNSPECIFIED == PST_UNSPECIFIED) &&
|
|
(SERIAL_SP_RS232 == PST_RS232) &&
|
|
(SERIAL_SP_PARALLEL == PST_PARALLELPORT) &&
|
|
(SERIAL_SP_RS422 == PST_RS422) &&
|
|
(SERIAL_SP_RS423 == PST_RS423) &&
|
|
(SERIAL_SP_RS449 == PST_RS449) &&
|
|
(SERIAL_SP_FAX == PST_FAX) &&
|
|
(SERIAL_SP_SCANNER == PST_SCANNER) &&
|
|
(SERIAL_SP_BRIDGE == PST_NETWORK_BRIDGE) &&
|
|
(SERIAL_SP_LAT == PST_LAT) &&
|
|
(SERIAL_SP_TELNET == PST_TCPIP_TELNET) &&
|
|
(SERIAL_SP_X25 == PST_X25));
|
|
ASSERT(sizeof(SERIAL_COMMPROP) == sizeof(COMMPROP));
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_COMMPROP));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the current properties.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's communication properties
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
serverProperties = (PSERIAL_COMMPROP)outputBuf;
|
|
|
|
if (GetCommProperties(FileHandle, (LPCOMMPROP)serverProperties)) {
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(SERIAL_COMMPROP);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommProperties failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
}
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialXoffCounter(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port XOFF Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::SerialXoffCounter");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// This IOCTL is not supported by Win32 COMM functions. What
|
|
// else can we do, but pass it directly to the driver. We should ASSERT
|
|
// to find out under which circumstances this happens, however.
|
|
//
|
|
ASSERT(FALSE);
|
|
DispatchIOCTLDirectlyToDriver(pIoReq);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialLSRMSTInsert(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port LSRMST Insert Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::SerialLSRMSTInsert");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// This IOCTL is not supported by Win32 COMM functions. What
|
|
// else can we do, but pass it directly to the driver. We should ASSERT
|
|
// to find out under which circumstances this happens, however.
|
|
//
|
|
ASSERT(FALSE);
|
|
DispatchIOCTLDirectlyToDriver(pIoReq);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialConfigSize(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Config Size Request from Server.
|
|
|
|
We don't support the IOCTL that is used to fetch the
|
|
configuration. Neither does the NT serial driver ...
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
#ifndef OS_WINCE
|
|
DCB dcb;
|
|
#endif
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
ULONG *configSize;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialConfigSize");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Check the size of the output buffer.
|
|
//
|
|
status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(ULONG));
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
}
|
|
|
|
//
|
|
// Get the configuration size.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's wait mask.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
configSize = (ULONG *)outputBuf;
|
|
|
|
#ifndef OS_WINCE
|
|
if (GetCommConfig(FileHandle, NULL, configSize)) {
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= sizeof(ULONG);
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
|
|
TRC_ALT((TB, _T("GetCommConfig failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
#else
|
|
status = STATUS_NOT_SUPPORTED;
|
|
#endif
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
#ifndef OS_WINCE
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetConfig(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Config Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG replyPacketSize;
|
|
PBYTE outputBuf;
|
|
ULONG configSize;
|
|
PRDPDR_DEVICE_IOREQUEST pIoRequest;
|
|
HANDLE FileHandle;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetConfig");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// Get the IO request.
|
|
//
|
|
pIoRequest = &pIoReq->IoRequest;
|
|
|
|
//
|
|
// Get Port Handle
|
|
//
|
|
FileHandle = GetPortHandle(pIoRequest->FileId);
|
|
ASSERT(FileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
//
|
|
// Allocate reply buffer.
|
|
//
|
|
status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
|
|
|
|
//
|
|
// Get the configuration size.
|
|
//
|
|
if (status == STATUS_SUCCESS) {
|
|
//
|
|
// Get a pointer to the output buffer server's wait mask.
|
|
//
|
|
outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
|
|
configSize = pIoRequest->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
#ifndef OS_WINCE
|
|
if (GetCommConfig(FileHandle, (COMMCONFIG *)outputBuf, &configSize)) {
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= configSize;
|
|
}
|
|
else {
|
|
DWORD err = GetLastError();
|
|
TRC_ALT((TB, _T("GetCommConfig failed with %08x"), err));
|
|
status = TranslateWinError(err);
|
|
#else
|
|
status = STATUS_NOT_SUPPORTED;
|
|
#endif
|
|
pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
|
|
= 0;
|
|
replyPacketSize = (ULONG)FIELD_OFFSET(
|
|
RDPDR_IOCOMPLETION_PACKET,
|
|
IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
|
|
#ifndef OS_WINCE
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Finish the response and send it.
|
|
//
|
|
pReplyPacket->IoCompletion.IoStatus = status;
|
|
|
|
TRACERESP(pIoReq, pReplyPacket);
|
|
ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
|
|
}
|
|
else {
|
|
//
|
|
// Send the results to the server.
|
|
//
|
|
TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
|
|
DefaultIORequestMsgHandle(pIoReq, status);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialGetStats(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Get Stats Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::SerialGetStats");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// This IOCTL is not supported by Win32 COMM functions. What
|
|
// else can we do, but pass it directly to the driver. We should ASSERT
|
|
// to find out under which circumstances this happens, however.
|
|
//
|
|
ASSERT(FALSE);
|
|
DispatchIOCTLDirectlyToDriver(pIoReq);
|
|
DC_END_FN();
|
|
}
|
|
|
|
void
|
|
W32DrPRT::SerialClearStats(
|
|
IN PRDPDR_IOREQUEST_PACKET pIoReq
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle Serial Port Clear Stats Request from Server.
|
|
|
|
Arguments:
|
|
|
|
pIoReq - Request packet received from server.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("W32DrPRT::SerialClearStats");
|
|
|
|
TRACEREQ(pIoReq);
|
|
|
|
//
|
|
// This IOCTL is not supported by Win32 COMM functions. What
|
|
// else can we do, but pass it directly to the driver. We should ASSERT
|
|
// to find out under which circumstances this happens, however.
|
|
//
|
|
ASSERT(FALSE);
|
|
DispatchIOCTLDirectlyToDriver(pIoReq);
|
|
DC_END_FN();
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
BOOL
|
|
W32DrPRT::GetIniCommValues(
|
|
LPTSTR pName,
|
|
LPDCB pdcb
|
|
)
|
|
/*++
|
|
|
|
It goes to win.ini [ports] section to get the comm (serial) port
|
|
settings such as
|
|
|
|
com1:=9600,n,8,1
|
|
|
|
And build a DCB.
|
|
|
|
Code modified from
|
|
|
|
\\muroc\slm\proj\win\src\CORE\SPOOL32\SPOOLSS\newdll\localmon.c
|
|
|
|
--*/
|
|
{
|
|
COMMCONFIG ccDummy;
|
|
COMMCONFIG *pcc;
|
|
DWORD dwSize;
|
|
TCHAR buf[MAX_PATH];
|
|
|
|
DC_BEGIN_FN("GetIniCommValues");
|
|
|
|
int len = _tcslen(pName) - 1;
|
|
BOOL ret = FALSE;
|
|
HRESULT hr;
|
|
|
|
hr = StringCchCopy(buf, SIZE_TCHARS(buf), pName);
|
|
if (FAILED(hr)) {
|
|
TRC_ERR((TB,_T("Failed to copy pName to temp buf: 0x%x"),hr));
|
|
return FALSE;
|
|
}
|
|
if (buf[len] == _T(':'))
|
|
buf[len] = 0;
|
|
|
|
ccDummy.dwProviderSubType = PST_RS232;
|
|
dwSize = sizeof(ccDummy);
|
|
GetDefaultCommConfig(buf, &ccDummy, &dwSize);
|
|
if (pcc = (COMMCONFIG *)LocalAlloc(LPTR, dwSize))
|
|
{
|
|
pcc->dwProviderSubType = PST_RS232;
|
|
if (GetDefaultCommConfig(buf, pcc, &dwSize))
|
|
{
|
|
*pdcb = pcc->dcb;
|
|
ret = TRUE;
|
|
}
|
|
LocalFree(pcc);
|
|
}
|
|
|
|
DC_END_FN();
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
|
|
VOID
|
|
W32DrPRT::InitializeSerialPort(
|
|
IN TCHAR *portName,
|
|
IN HANDLE portHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set a serial port to its initial state.
|
|
|
|
Arguments:
|
|
|
|
portName - Port name.
|
|
portHandle - Handle to open serial port.
|
|
|
|
Return Value:
|
|
|
|
This function always succeeds. Subsequent operations will fail if
|
|
the port cannot be properly initialized.
|
|
|
|
--*/
|
|
{
|
|
DCB dcb;
|
|
COMMTIMEOUTS cto;
|
|
|
|
DC_BEGIN_FN("W32DrPRT::InitializeSerialPort");
|
|
|
|
//
|
|
// Initialize serial port
|
|
//
|
|
if (!GetCommState(portHandle, &dcb)) {
|
|
TRC_ERR((TB, _T("GetCommState() returns %ld"), GetLastError()));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if (!GetCommTimeouts(portHandle, &cto)) {
|
|
TRC_ERR((TB, _T("GetCommTimeouts() returns %ld"), GetLastError()));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
if (!GetIniCommValues(portName, &dcb)) {
|
|
TRC_ERR((TB, _T("GetIniCommValues() returns %ld"), GetLastError()));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
#endif
|
|
|
|
cto.WriteTotalTimeoutConstant = WRITE_TOTAL_TIMEOUT;
|
|
cto.ReadTotalTimeoutConstant = READ_TOTAL_TIMEOUT;
|
|
cto.ReadIntervalTimeout = READ_INTERVAL_TIMEOUT;
|
|
|
|
//
|
|
// Ignore error from following.
|
|
//
|
|
SetCommState(portHandle, &dcb);
|
|
SetCommTimeouts(portHandle, &cto);
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
|