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.
544 lines
11 KiB
544 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
openmon.cxx
|
|
|
|
Abstract:
|
|
|
|
Methods to interact with the language/port monitor.
|
|
The methods in this file are a replacement for the old OpenMonitorPort/CloseMonitorPort
|
|
that used to close an opened handle on OpenMonitorPort while another thread was using it.
|
|
|
|
OpenMonitorPort - Opens a handle to the language or port monitor.
|
|
If the port has already an opened handle to the requested
|
|
monitor, then bump the handle's refcount and use it.If the
|
|
port has already an opened handle to another monitor then the
|
|
one requested, then fail the call with ERROR_BUSY.
|
|
CloseMonitorPort - Decrements the monitor handle's refcount and deletes the object
|
|
if no longer in use.
|
|
GetMonitorHandle - Returns the monitor handle curently opened
|
|
on the port.
|
|
GetOpenedMonitor - Returns a pointer to the INIMONITOR curently opened.
|
|
on the port.
|
|
ReleaseMonitorPort - Releases the port handle so that it can be closed.
|
|
|
|
Author:
|
|
|
|
Adina Trufinescu July 16th, 2002
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "monhndl.hxx"
|
|
|
|
|
|
|
|
HRESULT
|
|
InternalCloseMonitorPort(
|
|
IN PINIPORT pIniPort
|
|
);
|
|
|
|
void
|
|
AquirePortCriticalSection(
|
|
PINIPORT pIniPort
|
|
);
|
|
|
|
void
|
|
ReleasePortCriticalSection(
|
|
PINIPORT pIniPort
|
|
);
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
OpenMonitorPort
|
|
|
|
Routine Description:
|
|
|
|
Opens a handle to either the language monitor or
|
|
the port monitor. If a handle is already opened, then
|
|
use it.
|
|
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
pIniLangMonitor - pointer to INIMONITOR structure
|
|
represented the preffered language monitor.
|
|
pszPrinterName - string representing the printer name
|
|
|
|
Return Value:
|
|
|
|
HANDLE
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
HRESULT
|
|
OpenMonitorPort(
|
|
PINIPORT pIniPort,
|
|
PINIMONITOR pIniLangMonitor,
|
|
LPWSTR pszPrinterName
|
|
)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
|
|
SplInSem();
|
|
|
|
SPLASSERT (pIniPort != NULL && pIniPort->signature == IPO_SIGNATURE);
|
|
|
|
if(pIniPort &&
|
|
pIniPort->signature == IPO_SIGNATURE)
|
|
{
|
|
//
|
|
// If no monitor associated, do not have to open
|
|
//
|
|
if (!(pIniPort->Status & PP_MONITOR))
|
|
{
|
|
hRes = S_OK;
|
|
}
|
|
else
|
|
{
|
|
TMonitorHandle* pMonitorHandle = NULL;
|
|
|
|
//
|
|
// If a LM is passed and it does not have an OpenPortEx can't use it
|
|
//
|
|
if (pIniLangMonitor &&
|
|
!(pIniLangMonitor)->Monitor2.pfnOpenPortEx)
|
|
{
|
|
pIniLangMonitor = NULL;
|
|
}
|
|
|
|
AquirePortCriticalSection(pIniPort);
|
|
|
|
//
|
|
// If the port already has a handle opened to the wanted language monitor
|
|
// or if we don't care about the language monitor, then just use it.
|
|
//
|
|
pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
|
|
|
|
if (pMonitorHandle)
|
|
{
|
|
if (static_cast<PINIMONITOR>(*pMonitorHandle) ==
|
|
(pIniLangMonitor ? pIniLangMonitor : pIniPort->pIniMonitor))
|
|
{
|
|
pMonitorHandle->AddRef();
|
|
hRes = S_OK;
|
|
}
|
|
else
|
|
{
|
|
if (SUCCEEDED(hRes = InternalCloseMonitorPort(pIniPort)))
|
|
{
|
|
pMonitorHandle = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRes) && !pMonitorHandle)
|
|
{
|
|
//
|
|
// Open a monitor handle. On constructor we exit Spooler CS.
|
|
//
|
|
pMonitorHandle = new TMonitorHandle(pIniPort,
|
|
pIniLangMonitor,
|
|
pszPrinterName);
|
|
|
|
//
|
|
// We could get an invalid handle because another thread could try open
|
|
// monitor and succeed.OpenPort fails when called multiple times.
|
|
//
|
|
if (SUCCEEDED(hRes = pMonitorHandle ? S_OK : E_OUTOFMEMORY))
|
|
{
|
|
//
|
|
// Delete the object.
|
|
//
|
|
if (FAILED(hRes = pMonitorHandle->IsValid()))
|
|
{
|
|
delete pMonitorHandle;
|
|
pMonitorHandle = NULL;
|
|
}
|
|
|
|
if (pMonitorHandle)
|
|
{
|
|
pIniPort->hMonitorHandle = reinterpret_cast<HANDLE>(pMonitorHandle);
|
|
pMonitorHandle->AddRef();
|
|
hRes = S_OK;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ReleasePortCriticalSection(pIniPort);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hRes = E_INVALIDARG;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
InternalCloseMonitorPort
|
|
|
|
Routine Description:
|
|
|
|
Closes the monitor handle if the refcount reaches 0.
|
|
It assumes the port MonitorCS is aquired.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
HANDLE
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
HRESULT
|
|
InternalCloseMonitorPort(
|
|
IN PINIPORT pIniPort
|
|
)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
TMonitorHandle* pMonitorHandle = NULL;
|
|
|
|
SplInSem();
|
|
|
|
if (pIniPort->hMonitorHandle)
|
|
{
|
|
pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
|
|
|
|
//
|
|
// If the handle refcount reached 0, then we close the handle. On the destructor,
|
|
// we exit the Spooler CS.
|
|
//
|
|
if (pMonitorHandle->InUse() == 0)
|
|
{
|
|
pIniPort->hMonitorHandle = NULL;
|
|
//
|
|
// The destructor exits the Spooler CS.
|
|
//
|
|
delete pMonitorHandle;
|
|
}
|
|
else
|
|
{
|
|
hRes = HResultFromWin32(ERROR_BUSY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hRes = E_INVALIDARG;
|
|
}
|
|
|
|
return hRes;
|
|
|
|
}
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
CloseMonitorPort
|
|
|
|
Routine Description:
|
|
|
|
Decrement the handle object refcount and
|
|
closes the monitor handle if the refcount reaches 0.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
HANDLE
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
HRESULT
|
|
CloseMonitorPort(
|
|
IN PINIPORT pIniPort
|
|
)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
SplInSem();
|
|
|
|
hr = (pIniPort &&
|
|
pIniPort->signature == IPO_SIGNATURE &&
|
|
pIniPort->hMonitorHandle) ?
|
|
S_OK :
|
|
E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AquirePortCriticalSection(pIniPort);
|
|
|
|
hr = InternalCloseMonitorPort(pIniPort);
|
|
|
|
ReleasePortCriticalSection(pIniPort);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetMonitorHandle
|
|
|
|
Routine Description:
|
|
|
|
Returns the monitor handle curently opened
|
|
on the port.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
HANDLE
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
HANDLE
|
|
GetMonitorHandle(
|
|
IN PINIPORT pIniPort
|
|
)
|
|
{
|
|
HANDLE hMonitor = NULL;
|
|
|
|
if (pIniPort &&
|
|
pIniPort->signature == IPO_SIGNATURE &&
|
|
pIniPort->hMonitorHandle)
|
|
{
|
|
TMonitorHandle* pMonitorHandle = NULL;
|
|
|
|
pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
|
|
|
|
hMonitor = static_cast<HANDLE>(*pMonitorHandle);
|
|
}
|
|
|
|
return hMonitor;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetOpenedMonitor
|
|
|
|
Routine Description:
|
|
|
|
Returns a pointer to the INIMONITOR curently opened.
|
|
on the port.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
HANDLE
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
PINIMONITOR
|
|
GetOpenedMonitor(
|
|
IN PINIPORT pIniPort
|
|
)
|
|
{
|
|
PINIMONITOR pIniMonitor = NULL;
|
|
|
|
if (pIniPort && pIniPort->hMonitorHandle)
|
|
{
|
|
TMonitorHandle* pMonitorHandle = NULL;
|
|
|
|
pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
|
|
|
|
pIniMonitor = static_cast<PINIMONITOR>(*pMonitorHandle);
|
|
}
|
|
|
|
return pIniMonitor;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
ReleaseMonitorPort
|
|
|
|
Routine Description:
|
|
|
|
This will decrement the port handle ref count. When the ref count is 0,
|
|
the port handle is "not in use" and another thread can close it.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
HRESULT
|
|
ReleaseMonitorPort(
|
|
PINIPORT pIniPort
|
|
)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
SplInSem();
|
|
|
|
hr = (pIniPort &&
|
|
pIniPort->signature == IPO_SIGNATURE &&
|
|
pIniPort->hMonitorHandle) ?
|
|
S_OK :
|
|
E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TMonitorHandle* pMonitorHandle;
|
|
|
|
AquirePortCriticalSection(pIniPort);
|
|
|
|
pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
|
|
|
|
if (pMonitorHandle)
|
|
{
|
|
pMonitorHandle->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
ReleasePortCriticalSection(pIniPort);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
AquirePortCriticalSection
|
|
|
|
Routine Description:
|
|
|
|
This method aquires the IniPort section. Because Spooler cannot
|
|
open the monitor multiple times, it needs to do the open/close calls
|
|
inside a critical section. Because the Spooler section cannot be used,
|
|
the port was added a new CS. The method must be called inside Spooler section.
|
|
The method aquires the port CS outside the Spooler section and then reenters.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
void
|
|
AquirePortCriticalSection(
|
|
IN PINIPORT pIniPort
|
|
)
|
|
{
|
|
if (pIniPort)
|
|
{
|
|
INCPORTREF(pIniPort);
|
|
INCSPOOLERREF(pIniPort->pIniSpooler);
|
|
INCMONITORREF(pIniPort->pIniMonitor);
|
|
|
|
LeaveSplSem();
|
|
SplOutSem();
|
|
|
|
EnterCriticalSection(&pIniPort->MonitorCS);
|
|
|
|
EnterSplSem();
|
|
SplInSem();
|
|
|
|
DECPORTREF(pIniPort);
|
|
DECSPOOLERREF(pIniPort->pIniSpooler);
|
|
DECMONITORREF(pIniPort->pIniMonitor);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
ReleasePortCriticalSection
|
|
|
|
Routine Description:
|
|
|
|
This method releases the IniPort section.
|
|
|
|
Arguments:
|
|
|
|
pIniPort - pointer to INIPORT structure
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
Last Error:
|
|
|
|
Not Set.
|
|
|
|
--*/
|
|
void
|
|
ReleasePortCriticalSection(
|
|
PINIPORT pIniPort
|
|
)
|
|
{
|
|
if (pIniPort)
|
|
{
|
|
LeaveCriticalSection(&pIniPort->MonitorCS);
|
|
}
|
|
}
|