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.
400 lines
9.8 KiB
400 lines
9.8 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
All Rights Reserved
|
|
|
|
|
|
Module Name:
|
|
DynaMon.cpp
|
|
|
|
Abstract:
|
|
Multiple Transport core port monitor routines
|
|
|
|
Author: M. Fenelon
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "ntddpar.h"
|
|
|
|
// Global Values for Monitor
|
|
TCHAR cszUSB[] = TEXT("USB");
|
|
TCHAR cszDOT4[] = TEXT("DOT4");
|
|
TCHAR cszTS[] = TEXT("TS");
|
|
TCHAR csz1394[] = TEXT("1394");
|
|
TCHAR cszBaseName[] = TEXT("Base Name");
|
|
TCHAR cszPortNumber[] = TEXT("Port Number");
|
|
TCHAR cszRecyclable[] = TEXT("recyclable");
|
|
TCHAR cszPortDescription[] = TEXT("Port Description");
|
|
TCHAR cszMaxBufferSize[] = TEXT("MaxBufferSize");
|
|
TCHAR cszUSBPortDesc[] = TEXT("Virtual printer port for USB");
|
|
TCHAR cszDot4PortDesc[] = TEXT("Virtual printer port for Dot4");
|
|
TCHAR csz1394PortDesc[] = TEXT("Virtual printer port for 1394");
|
|
TCHAR cszTSPortDesc[] = TEXT("Virtual printer port for TS");
|
|
|
|
DYNAMON_MONITOR_INFO gDynaMonInfo;
|
|
|
|
MODULE_DEBUG_INIT( DBG_ERROR, DBG_ERROR );
|
|
|
|
BOOL
|
|
APIENTRY
|
|
DllMain(
|
|
HANDLE hModule,
|
|
DWORD dwReason,
|
|
LPVOID lpRes
|
|
)
|
|
{
|
|
|
|
if ( dwReason == DLL_PROCESS_ATTACH )
|
|
DisableThreadLibraryCalls(hModule);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Construct MonitorEx structure to provide to Spooler
|
|
MONITOREX MonitorEx = {
|
|
sizeof(MONITOR),
|
|
{
|
|
DynaMon_EnumPorts,
|
|
DynaMon_OpenPort,
|
|
NULL, // OpenPortEx not supported
|
|
DynaMon_StartDocPort,
|
|
DynaMon_WritePort,
|
|
DynaMon_ReadPort,
|
|
DynaMon_EndDocPort,
|
|
DynaMon_ClosePort,
|
|
NULL, // AddPort not supported
|
|
NULL, // AddPortEx not supported
|
|
NULL, // ConfigurePort not supported
|
|
NULL, // DeletePort not supported
|
|
DynaMon_GetPrinterDataFromPort,
|
|
DynaMon_SetPortTimeOuts,
|
|
NULL, // XcvOpenPort not supported
|
|
NULL, // XcvDataPort not supported
|
|
NULL // XcvClosePort not supported
|
|
}
|
|
};
|
|
|
|
|
|
LPMONITOREX
|
|
WINAPI
|
|
InitializePrintMonitor(
|
|
LPTSTR pszRegistryRoot
|
|
)
|
|
|
|
{
|
|
BOOL bEnumPortsCS = FALSE;
|
|
BOOL bUpdateListCS = FALSE;
|
|
LPMONITOREX pMonitorEx = NULL;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
// Clear the Global info
|
|
ZeroMemory( &gDynaMonInfo, sizeof(gDynaMonInfo) );
|
|
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
__try
|
|
{
|
|
InitializeCriticalSection (&gDynaMonInfo.EnumPortsCS);
|
|
bEnumPortsCS = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwStatus = GetExceptionCode ();
|
|
}
|
|
}
|
|
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
__try
|
|
{
|
|
InitializeCriticalSection (&gDynaMonInfo.UpdateListCS);
|
|
bUpdateListCS = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwStatus = GetExceptionCode ();
|
|
}
|
|
}
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
gDynaMonInfo.hUpdateEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
if (gDynaMonInfo.hUpdateEvent == NULL)
|
|
{
|
|
dwStatus = GetLastError ();
|
|
}
|
|
}
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Get the Background Thread going
|
|
//
|
|
dwStatus = SpinUpdateThread ();
|
|
}
|
|
//
|
|
//
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
pMonitorEx = &MonitorEx;
|
|
}
|
|
else
|
|
{
|
|
if (bEnumPortsCS)
|
|
{
|
|
DeleteCriticalSection (&gDynaMonInfo.EnumPortsCS);
|
|
}
|
|
if (bUpdateListCS)
|
|
{
|
|
DeleteCriticalSection (&gDynaMonInfo.UpdateListCS);
|
|
}
|
|
if (gDynaMonInfo.hUpdateEvent)
|
|
{
|
|
CloseHandle (&gDynaMonInfo.hUpdateEvent);
|
|
}
|
|
ZeroMemory( &gDynaMonInfo, sizeof(gDynaMonInfo) );
|
|
SetLastError (dwStatus);
|
|
}
|
|
return pMonitorEx;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_EnumPorts(
|
|
LPTSTR pszName,
|
|
DWORD dwLevel,
|
|
LPBYTE pPorts,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned
|
|
)
|
|
{
|
|
DWORD dwLastError = ERROR_SUCCESS, dwRequestIndex;
|
|
LPBYTE pEnd;
|
|
PDYNAMON_PORT pPortList;
|
|
PPORT_UPDATE pPortUpdateList = NULL;
|
|
|
|
*pcbNeeded = *pcReturned = 0;
|
|
if ( dwLevel != 1 && dwLevel != 2 )
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
dwRequestIndex = gDynaMonInfo.dwLastEnumIndex;
|
|
ECS( gDynaMonInfo.EnumPortsCS );
|
|
|
|
if ( dwRequestIndex >= gDynaMonInfo.dwLastEnumIndex )
|
|
{
|
|
//
|
|
// No complete enumeration has occurred since this request was made.
|
|
// Since the request may be an indication that something has changed,
|
|
// the full reenumeration must be done.
|
|
//
|
|
// Updated the index of enumeration before actually doing the
|
|
// work so it will show up as the most conservative
|
|
//
|
|
// Consequence of rollover on gdwLastEnumIndex:
|
|
// Any threads that recorded 0xFFFFFFFF as the dwRequestIndex
|
|
// will show as greater than the new value 0 and therefore reenum
|
|
// gratuitously. Not very much extra work.
|
|
//
|
|
++gDynaMonInfo.dwLastEnumIndex;
|
|
if ( dwLastError = BuildPortList( &gDynaMonInfo, &pPortUpdateList) )
|
|
goto Done;
|
|
}
|
|
|
|
for ( pPortList = gDynaMonInfo.pPortList ;
|
|
pPortList ;
|
|
pPortList = pPortList->pNext )
|
|
{
|
|
*pcbNeeded += pPortList->pBasePort->getEnumInfoSize( dwLevel );
|
|
}
|
|
|
|
if ( cbBuf < *pcbNeeded )
|
|
{
|
|
dwLastError = ERROR_INSUFFICIENT_BUFFER;
|
|
goto Done;
|
|
}
|
|
|
|
pEnd = pPorts + cbBuf;
|
|
|
|
for ( pPortList = gDynaMonInfo.pPortList ;
|
|
pPortList ;
|
|
pPortList = pPortList->pNext )
|
|
{
|
|
|
|
pEnd = pPortList->pBasePort->copyEnumInfo( dwLevel, pPorts, pEnd );
|
|
if ( dwLevel == 1 )
|
|
pPorts += sizeof(PORT_INFO_1);
|
|
else
|
|
pPorts += sizeof(PORT_INFO_2);
|
|
++(*pcReturned);
|
|
|
|
}
|
|
|
|
SPLASSERT(pEnd >= pPorts);
|
|
|
|
Done:
|
|
// If we have anything to update do it now
|
|
if ( pPortUpdateList )
|
|
PassPortUpdateListToUpdateThread( pPortUpdateList );
|
|
|
|
LCS( gDynaMonInfo.EnumPortsCS );
|
|
|
|
if ( dwLastError )
|
|
{
|
|
SetLastError(dwLastError);
|
|
return FALSE;
|
|
}
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_OpenPort(
|
|
LPTSTR pszPortName,
|
|
LPHANDLE pHandle
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort, pPrev;
|
|
|
|
pPort = FindPort( &gDynaMonInfo, pszPortName, &pPrev);
|
|
|
|
if ( pPort )
|
|
{
|
|
*pHandle = (LPHANDLE)pPort;
|
|
pPort->pBasePort->InitCS();
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_ClosePort(
|
|
HANDLE hPort
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
pPort->pBasePort->ClearCS();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_StartDocPort(
|
|
HANDLE hPort,
|
|
LPTSTR pPrinterName,
|
|
DWORD dwJobId,
|
|
DWORD dwLevel,
|
|
LPBYTE pDocInfo
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->startDoc( pPrinterName, dwJobId, dwLevel, pDocInfo );
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_EndDocPort(
|
|
HANDLE hPort
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->endDoc();
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_GetPrinterDataFromPort(
|
|
HANDLE hPort,
|
|
DWORD dwControlID,
|
|
LPWSTR pValueName,
|
|
LPWSTR lpInBuffer,
|
|
DWORD cbInBuffer,
|
|
LPWSTR lpOutBuffer,
|
|
DWORD cbOutBuffer,
|
|
LPDWORD lpcbReturned
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->getPrinterDataFromPort( dwControlID, pValueName, lpInBuffer, cbInBuffer,
|
|
lpOutBuffer, cbOutBuffer, lpcbReturned );
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_ReadPort(
|
|
HANDLE hPort,
|
|
LPBYTE pBuffer,
|
|
DWORD cbBuffer,
|
|
LPDWORD pcbRead
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->read( pBuffer, cbBuffer, pcbRead );
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_WritePort(
|
|
HANDLE hPort,
|
|
LPBYTE pBuffer,
|
|
DWORD cbBuffer,
|
|
LPDWORD pcbWritten
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->write( pBuffer, cbBuffer, pcbWritten );
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DynaMon_SetPortTimeOuts(
|
|
HANDLE hPort,
|
|
LPCOMMTIMEOUTS lpCTO,
|
|
DWORD reserved
|
|
)
|
|
{
|
|
PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
|
|
|
|
IF_INVALID_PORT_FAIL( pPort )
|
|
|
|
return pPort->pBasePort->setPortTimeOuts( lpCTO );
|
|
}
|