/*++ Copyright (c) 2002 Microsoft Corporation Module Name: monitorhndl.cxx Abstract: This is the class that wrapps the port/language monitor handle. Author: Adina Trufinescu July 16th, 2002 Revision History: --*/ #include "precomp.h" #pragma hdrstop #include "monhndl.hxx" WCHAR TMonitorHandle::m_szFILE[] = L"FILE:"; /*++ Routine Name: Constructor Routine Description: Returns number of elements that could be enumerated. NOT thread safe. Arguments: pIniPort - pointer to INIPORT structure pIniLangMonitor - pointer to INIMONITOR structure represented the preffered language monitor. pszPrinterName - string representing the printer name Return Value: NONE Last Error: Not Set. --*/ TMonitorHandle:: TMonitorHandle( IN PINIPORT pIniPort, IN PINIMONITOR pIniLangMonitor, IN LPWSTR pszPrinterName ) : m_pIniPort(pIniPort), m_pIniLangMonitor(pIniLangMonitor), m_pszPrinterName(pszPrinterName), m_RefCnt(0), m_hPort(NULL), m_OpenedMonitorType(kNone), m_hValid(E_FAIL) { SplInSem(); if (SUCCEEDED(m_hValid = (m_pIniPort) ? S_OK : E_INVALIDARG)) { if (SUCCEEDED(m_hValid)) { if (m_pIniPort->Status & PP_FILE) { m_hValid = OpenMonitorForFILEPort(); } else { if (m_pIniLangMonitor && !m_pIniLangMonitor->Monitor2.pfnOpenPortEx) { m_pIniLangMonitor = NULL; } m_hValid = Open(); } if (SUCCEEDED(m_hValid)) { INCPORTREF(m_pIniPort); INCSPOOLERREF(m_pIniPort->pIniSpooler); INCMONITORREF(static_cast(*this)); } } } } /*++ Routine Name: Destructor Routine Description: Destructor Arguments: NONE Return Value: NONE Last Error: Not Set. --*/ TMonitorHandle:: ~TMonitorHandle( VOID ) { SplInSem(); if (SUCCEEDED(m_hValid)) { Close(); DECPORTREF(m_pIniPort); DECSPOOLERREF(m_pIniPort->pIniSpooler); } } /*++ Routine Name: Open Routine Description: Opens the correct monitor. If the language monitor is NULL or it doesn't support OpenPortEx, it will open the port monitor. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: Open( VOID ) { HRESULT hr; hr = m_pIniLangMonitor ? (m_pIniLangMonitor->bUplevel ? OpenLangMonitorUplevel() : OpenLangMonitorDownlevel()): OpenPortMonitor(); return hr; } /*++ Routine Name: Close Routine Description: Closes the opened monitor. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: Close( VOID ) { HRESULT hr = m_hValid; HANDLE hPort = m_hPort; if (SUCCEEDED(hr)) { PINIMONITOR pIniMonitor = static_cast(*this); if (pIniMonitor) { LeaveSpoolerSem(); if (!(pIniMonitor->Monitor2.pfnClosePort)(hPort)) { hPort = NULL; hr = HResultFromWin32(GetLastError()); } ReEnterSpoolerSem(); if (SUCCEEDED(hr)) { if (pIniMonitor == m_pIniPort->pIniLangMonitor) { m_pIniPort->pIniLangMonitor = NULL; } m_hPort = NULL; DECMONITORREF(pIniMonitor); } } } return hr; } /*++ Routine Name: OpenLangMonitorUplevel Routine Description: Opens the language monitor using Monitor2.OpenPortEx. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: OpenLangMonitorUplevel( VOID ) { HRESULT hr = S_OK; INCMONITORREF(m_pIniLangMonitor); LeaveSpoolerSem(); SetLastError(ERROR_SUCCESS); if (!(*(m_pIniLangMonitor)->Monitor2.pfnOpenPortEx)(m_pIniLangMonitor->hMonitor, m_pIniPort->pIniMonitor->hMonitor, m_pIniPort->pName, m_pszPrinterName, &m_hPort, &m_pIniPort->pIniMonitor->Monitor2)) { if (SUCCEEDED(hr = HResultFromWin32(GetLastError()))) { hr = HResultFromWin32(ERROR_INVALID_HANDLE); } } else { hr = m_hPort ? S_OK : HResultFromWin32(ERROR_INVALID_HANDLE); } ReEnterSpoolerSem(); DECMONITORREF(m_pIniLangMonitor); if (SUCCEEDED(hr)) { m_OpenedMonitorType = kLanguage; m_pIniPort->pIniLangMonitor = m_pIniLangMonitor; } SetLastError(HRESULT_CODE(hr)); return hr; } /*++ Routine Name: OpenLangMonitorDownlevel Routine Description: Opens the language monitor using Monitor.OpenPortEx. If the port monitor is downlevel, create unique name string. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: OpenLangMonitorDownlevel( VOID ) { HRESULT hr = S_OK; LPWSTR pszPort = NULL; WCHAR szPortNew[MAX_PATH]; if (m_pIniPort->pIniMonitor->bUplevel) { // // Downlevel port monitor; create hack string. // if (SUCCEEDED(StringCchPrintf(szPortNew, COUNTOF(szPortNew), TEXT("%s,%p"), m_pIniPort->pName, m_pIniPort->pIniMonitor))) { pszPort = szPortNew; } } else { pszPort = m_pIniPort->pName; } if (pszPort) { INCMONITORREF(m_pIniLangMonitor); LeaveSpoolerSem(); SetLastError(ERROR_SUCCESS); if (!(*(m_pIniLangMonitor)->Monitor.pfnOpenPortEx)(pszPort, m_pszPrinterName, &m_hPort, &m_pIniPort->pIniMonitor->Monitor)) { if (SUCCEEDED(hr = HResultFromWin32(GetLastError()))) { hr = HResultFromWin32(ERROR_INVALID_HANDLE); } } else { hr = m_hPort ? S_OK : HResultFromWin32(ERROR_INVALID_HANDLE); } ReEnterSpoolerSem(); DECMONITORREF(m_pIniLangMonitor); if (SUCCEEDED(hr)) { m_OpenedMonitorType = kLanguage; m_pIniPort->pIniLangMonitor = m_pIniLangMonitor; } } else { m_pIniLangMonitor = NULL; hr = OpenPortMonitor(); } SetLastError(HRESULT_CODE(hr)); return hr; } /*++ Routine Name: OpenPortMonitor Routine Description: Opens the port monitor using Monitor2.pfnOpenPort. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: OpenPortMonitor( VOID ) { HRESULT hr = E_INVALIDARG; if (m_pIniPort && m_pIniPort->pIniMonitor && m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort) { INCMONITORREF(m_pIniPort->pIniMonitor); LeaveSpoolerSem(); SetLastError(ERROR_SUCCESS); if ((m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)(m_pIniPort->pIniMonitor->hMonitor, m_pIniPort->pName, &m_hPort)) { hr = m_hPort ? S_OK : HResultFromWin32(ERROR_INVALID_HANDLE); } else { if (SUCCEEDED(hr = HResultFromWin32(GetLastError()))) { hr = HResultFromWin32(ERROR_INVALID_HANDLE); } } ReEnterSpoolerSem(); DECMONITORREF(m_pIniPort->pIniMonitor); if (SUCCEEDED(hr)) { m_OpenedMonitorType = kPort; } } SetLastError(HRESULT_CODE(hr)); return hr; } /*++ Routine Name: OpenMonitorForFILEPort Routine Description: Opens the port monitor for FILE: port. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: OpenMonitorForFILEPort( VOID ) { HRESULT hr = E_INVALIDARG; if (m_pIniPort && m_pIniPort->pIniMonitor && m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort) { INCMONITORREF(m_pIniPort->pIniMonitor); LeaveSpoolerSem(); SetLastError(ERROR_SUCCESS); if ((m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)(m_pIniPort->pIniMonitor->hMonitor, m_szFILE, &m_hPort)) { hr = m_hPort ? S_OK : HResultFromWin32(ERROR_INVALID_HANDLE); } else { if (SUCCEEDED(hr = HResultFromWin32(GetLastError()))) { hr = HResultFromWin32(ERROR_INVALID_HANDLE); } } ReEnterSpoolerSem(); DECMONITORREF(m_pIniPort->pIniMonitor); if (SUCCEEDED(hr)) { m_OpenedMonitorType = kFile; } } SetLastError(HRESULT_CODE(hr)); return hr; } /*++ Routine Name: AddRef Routine Description: Increments object refcount. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ ULONG TMonitorHandle :: AddRef( VOID ) { return InterlockedIncrement(&m_RefCnt); } /*++ Routine Name: Release Routine Description: Decrements object refcount. Notice that it doesn't delete the object as the destructor would exit the Spooler CS while the pIniPort still has a reference to the object. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ ULONG TMonitorHandle :: Release( VOID ) { ULONG RefCnt = InterlockedDecrement(&m_RefCnt); InterlockedCompareExchange(&m_RefCnt, 0, ULONG(-1)); return RefCnt; } /*++ Routine Name: InUse Routine Description: Checks whether the ref count is zero. If it is, then the object can be deleted. Arguments: NONE Return Value: ULONG - the ref count value. Last Error: Not Set. --*/ ULONG TMonitorHandle :: InUse( VOID ) { return InterlockedCompareExchange(&m_RefCnt, 0 , 0); } /*++ Routine Name: IsValid Routine Description: Checks object validity. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ HRESULT TMonitorHandle:: IsValid( VOID ) { return m_hValid; } /*++ Routine Name: LeaveSpoolerSem Routine Description: Leaves Spooler CS Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ VOID TMonitorHandle:: LeaveSpoolerSem( VOID ) { INCPORTREF(m_pIniPort); INCSPOOLERREF(m_pIniPort->pIniSpooler); LeaveSplSem(); SplOutSem(); } /*++ Routine Name: ReEnterSpoolerSem Routine Description: Enters Spooler CS Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ VOID TMonitorHandle:: ReEnterSpoolerSem( VOID ) { EnterSplSem(); DECPORTREF(m_pIniPort); DECSPOOLERREF(m_pIniPort->pIniSpooler); SplInSem(); } /*++ Routine Name: operator PINIMONITOR Routine Description: Returns a pointer to the opened monitor. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ TMonitorHandle:: operator PINIMONITOR( VOID ) { PINIMONITOR pIniMonitor = NULL; switch (m_OpenedMonitorType) { case kLanguage: { pIniMonitor = m_pIniLangMonitor; break; } case kPort: case kFile: { pIniMonitor = m_pIniPort->pIniMonitor; break; } default: { break; } } return pIniMonitor; } /*++ Routine Name: operator HANDLE Routine Description: Returns a monitor handle. Arguments: NONE Return Value: HRESULT Last Error: Not Set. --*/ TMonitorHandle:: operator HANDLE( VOID ) { return m_hPort; }