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