Leaked source code of windows server 2003
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

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