|
|
/*++
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(); }
|