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