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.
844 lines
14 KiB
844 lines
14 KiB
/*++
|
|
|
|
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<PINIMONITOR>(*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<PINIMONITOR>(*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;
|
|
}
|