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.
1886 lines
63 KiB
1886 lines
63 KiB
/*++
|
|
Copyright (C) 2000 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
ldmgr.cxx
|
|
|
|
Abstract:
|
|
This file contains the methods and class implementation
|
|
necessary for the RPC surrogate used to load 64 bit dlls from
|
|
within 32 bit apps.
|
|
|
|
Author:
|
|
Khaled Sedky (khaleds) 18-Jan-2000
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#ifndef __LDINTERFACES_HPP__
|
|
#include "ldintrfcs.hpp"
|
|
#endif __LDINTERFACES_HPP__
|
|
|
|
#ifndef __LDFUNCS_HPP__
|
|
#include "ldfuncs.hpp"
|
|
#endif
|
|
|
|
#ifndef __LDMGR_HPP__
|
|
#include "ldmgr.hpp"
|
|
#endif
|
|
|
|
extern TLoad64BitDllsMgr* pGLdrObj;
|
|
extern DWORD DeviceCapsReqSize[MAX_CAPVAL];
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: TLoad64BitDllsMgr
|
|
|
|
Description:
|
|
Constructor of the main Loader Object. Mainly initializes
|
|
the private data of the class and creates whatever resources
|
|
are required
|
|
|
|
Parameters:
|
|
HRESULT *hRes: Returns result of constructing the object
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
TLoad64BitDllsMgr ::
|
|
TLoad64BitDllsMgr(
|
|
OUT HRESULT *phRes
|
|
) :
|
|
m_UIRefCnt(0),
|
|
TClassID("TLoad64BitDllsMgr")
|
|
{
|
|
HRESULT hLocalRes = S_OK;
|
|
HKEY hPrintKey = NULL;
|
|
DWORD ValueSize = sizeof(DWORD);
|
|
|
|
//
|
|
// Initializing the time structure before any time
|
|
// calculations
|
|
//
|
|
ZeroMemory(&m_LastTransactionTime,sizeof(SYSTEMTIME));
|
|
|
|
//
|
|
// Read the expiration time from the registry
|
|
//
|
|
if((ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Control\\Print",
|
|
&hPrintKey)) ||
|
|
(ERROR_SUCCESS != RegQueryValueEx(hPrintKey,
|
|
L"SplWOW64TimeOut",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE) &m_ExpirationTime,
|
|
&ValueSize)))
|
|
{
|
|
m_ExpirationTime = KTwoMinutes;
|
|
}
|
|
else
|
|
{
|
|
m_ExpirationTime = m_ExpirationTime * KOneMinute;
|
|
}
|
|
|
|
if(hPrintKey)
|
|
{
|
|
RegCloseKey(hPrintKey);
|
|
}
|
|
|
|
__try
|
|
{
|
|
DWORD CurrProcessId = GetCurrentProcessId();
|
|
//
|
|
// Initializing the Critical Section
|
|
//
|
|
InitializeCriticalSection(&m_LdMgrLock);
|
|
//
|
|
// Setting the initial time to that of the process
|
|
// first instantiation
|
|
//
|
|
GetSystemTime(&m_LastTransactionTime);
|
|
//
|
|
// The Session ID uniquely identifies each process for
|
|
// both the RPC end point and the LPC port name
|
|
//
|
|
ProcessIdToSessionId(CurrProcessId,&m_CurrSessionId);
|
|
|
|
AddRef();
|
|
}
|
|
__except(1)
|
|
{
|
|
hLocalRes = GetLastErrorAsHRESULT(TranslateExceptionCode(GetExceptionCode()));
|
|
}
|
|
|
|
if(phRes)
|
|
{
|
|
*phRes = hLocalRes;
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: ~TLoad64BitDllsMgr
|
|
|
|
Description:
|
|
Destructor of the main Loader Object. Mainly fress up any
|
|
allocated resources
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
TLoad64BitDllsMgr ::
|
|
~TLoad64BitDllsMgr()
|
|
{
|
|
DeleteCriticalSection(&m_LdMgrLock);
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: QueryInterface
|
|
|
|
Description:
|
|
Returned the correct object for each set of simillar functions
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
HRESULT hREs = S_OK in case of a suitable Interface
|
|
E_NOINTERFACE in case of none
|
|
--*/
|
|
HRESULT
|
|
TLoad64BitDllsMgr ::
|
|
QueryInterface(
|
|
IN REFIID InterfaceID,
|
|
OUT PVOID *ppInterface
|
|
)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
|
|
if(!ppInterface)
|
|
{
|
|
hRes = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
*ppInterface = NULL;
|
|
if(InterfaceID == IID_PRINTEREVENT)
|
|
{
|
|
*ppInterface = reinterpret_cast<TPrinterEventMgr *>(new TPrinterEventMgr(this));
|
|
}
|
|
else if(InterfaceID == IID_PRINTUIOPERATIONS)
|
|
{
|
|
*ppInterface = reinterpret_cast<TPrintUIMgr *>(new TPrintUIMgr(this));
|
|
}
|
|
else if(InterfaceID == IID_PRINTERCONFIGURATION)
|
|
{
|
|
*ppInterface = reinterpret_cast<TPrinterCfgMgr *>(new TPrinterCfgMgr(this));
|
|
}
|
|
else if(InterfaceID == IID_LPCMGR)
|
|
{
|
|
*ppInterface = reinterpret_cast<TLPCMgr *>(new TLPCMgr(this));
|
|
}
|
|
else
|
|
{
|
|
hRes = E_NOINTERFACE;
|
|
}
|
|
|
|
if(*ppInterface)
|
|
{
|
|
(reinterpret_cast<TRefCntMgr *>(*ppInterface))->AddRef();
|
|
}
|
|
else
|
|
{
|
|
hRes = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: Run
|
|
|
|
Description:
|
|
Creates the object expiration monitoring Thread and starts the
|
|
RPC server listening process
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
DWORD RetVal : ERROR_SUCCESS in case of success
|
|
ErrorCode in case of failure
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
Run(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD RetVal = ERROR_SUCCESS;
|
|
HANDLE hMonSrvrThrd = NULL;
|
|
DWORD MonSrvrThrdId = 0;
|
|
//
|
|
// Create a Thread which monitors the expiration of this
|
|
// process. Expiration means that more than a given amount
|
|
// of time , no one requested a service from this surrogate.
|
|
//
|
|
if(hMonSrvrThrd = CreateThread(NULL,
|
|
0,
|
|
MonitorSrvrLifeExpiration,
|
|
(PVOID)this,
|
|
0,
|
|
&MonSrvrThrdId))
|
|
{
|
|
//
|
|
// SetUp the RPC server and start listening
|
|
//
|
|
if((RetVal = StartLdrRPCServer()) == RPC_S_OK)
|
|
{
|
|
WaitForSingleObject(hMonSrvrThrd,INFINITE);
|
|
}
|
|
CloseHandle(hMonSrvrThrd);
|
|
}
|
|
else
|
|
{
|
|
RetVal = GetLastError();
|
|
}
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: StartldrRPCServer
|
|
|
|
Description:
|
|
This function encapsulates specifying the EndPoints,
|
|
the RPC protocol and the Bindings. It also has the
|
|
main listening loop for the RPC server.
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value
|
|
DWORD RetVal : ERROR_SUCCESS in case of success
|
|
ErrorCode in case of failure
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
StartLdrRPCServer(
|
|
VOID
|
|
)
|
|
{
|
|
RPC_BINDING_VECTOR *pBindingVector;
|
|
RPC_STATUS RpcStatus;
|
|
WCHAR szSessionEndPoint[50];
|
|
DWORD CurrProcessId = GetCurrentProcessId();
|
|
|
|
//
|
|
// The EndPointName would be the concatenation of
|
|
// both the app name and the session ID. Session
|
|
// ID is a dword and hence needs max. 10 wchars ,
|
|
// App name is "splwow64" which is 8 wchars. So
|
|
// the max we might need is 18 whcars. I might
|
|
// adjust the buffer size later. This is done
|
|
// specially for terminal server because a Window
|
|
// handle is not shared between differnet sessions,
|
|
// hence we need a process/session
|
|
//
|
|
StringCchPrintfW(szSessionEndPoint,
|
|
50,
|
|
L"%s_%x",
|
|
APPNAME,m_CurrSessionId);
|
|
|
|
|
|
if(!(((RpcStatus = RpcServerUseProtseqEp((WCHAR *)L"ncalrpc",
|
|
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
|
|
(WCHAR *)szSessionEndPoint,
|
|
NULL)) == RPC_S_OK) &&
|
|
((RpcStatus = RpcServerRegisterIf2(Lding64BitDlls_ServerIfHandle,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
|
|
kMaxRPCPacketSize,
|
|
NULL)) == RPC_S_OK) &&
|
|
((RpcStatus = RpcServerInqBindings(&pBindingVector)) == RPC_S_OK) &&
|
|
((RpcStatus = RpcBindingVectorFree(&pBindingVector)) == RPC_S_OK) &&
|
|
((RpcStatus = RpcServerRegisterAuthInfo(0,RPC_C_AUTHN_WINNT,0,0 )) == RPC_S_OK) &&
|
|
((RpcStatus = RpcServerListen(1,
|
|
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
|
|
FALSE)) == RPC_S_OK)))
|
|
{
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: StartLdrRPCServer failed with %u\n",RpcStatus));
|
|
}
|
|
return (DWORD)RpcStatus;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: LockSelf
|
|
|
|
Description:
|
|
Locks the object from other threads for
|
|
internal data update.
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
LockSelf(
|
|
VOID
|
|
)
|
|
{
|
|
EnterCriticalSection(&m_LdMgrLock);
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: ReleaseSelf
|
|
|
|
Description:
|
|
Release the object for use by other Threads
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value
|
|
None
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
ReleaseSelf(
|
|
VOID
|
|
)
|
|
{
|
|
LeaveCriticalSection(&m_LdMgrLock);
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: RefreshLifeSpan
|
|
|
|
Description:
|
|
Updates the last time @ which the object
|
|
was accessed
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
RefreshLifeSpan(
|
|
VOID
|
|
)
|
|
{
|
|
LockSelf();
|
|
{
|
|
GetSystemTime(&m_LastTransactionTime);
|
|
}
|
|
ReleaseSelf();
|
|
}
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: StillAlive
|
|
|
|
Description:
|
|
This function calculates the difference of
|
|
time between the last time the object was
|
|
accessed by any connected client and the
|
|
current system time
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
BOOL RetVal : TRUE if time delta is <= server expiration time
|
|
FALSE if time delta is > server expiration time
|
|
--*/
|
|
BOOL
|
|
TLoad64BitDllsMgr ::
|
|
StillAlive(
|
|
VOID
|
|
)
|
|
{
|
|
FILETIME FileTime;
|
|
FILETIME LocalFileTime;
|
|
SYSTEMTIME LocalSystemTime;
|
|
BOOL bRetVal = TRUE;
|
|
|
|
LockSelf();
|
|
{
|
|
GetSystemTime(&LocalSystemTime);
|
|
SystemTimeToFileTime(&LocalSystemTime,&LocalFileTime);
|
|
SystemTimeToFileTime(&m_LastTransactionTime,&FileTime);
|
|
ULONGLONG TimeDiff = ((ULARGE_INTEGER *)&LocalFileTime)->QuadPart -
|
|
((ULARGE_INTEGER *)&FileTime)->QuadPart;
|
|
//
|
|
// Since FileTime is calculated as a 100 nanosecond interval
|
|
// we have to divide by 10**4 to get the value in meli seconds
|
|
//
|
|
if((TimeDiff/10000) > m_ExpirationTime)
|
|
{
|
|
if(GetUIRefCnt())
|
|
{
|
|
GetSystemTime(&m_LastTransactionTime);
|
|
}
|
|
else
|
|
{
|
|
bRetVal = FALSE;
|
|
//
|
|
// Here we should terminate the Listen loop and kill the
|
|
// process, by releasing the listen loop.
|
|
//
|
|
RpcMgmtStopServerListening(NULL);
|
|
}
|
|
}
|
|
}
|
|
ReleaseSelf();
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: StillAlive
|
|
|
|
Description:
|
|
Monitors the expiration of the server and in case of
|
|
expiration terminations the RPC server listening loop.
|
|
|
|
Parameters:
|
|
PVOID pData : Pointer to the Loader Object
|
|
|
|
Return Value:
|
|
Always returns 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
MonitorSrvrLifeExpiration(
|
|
IN PVOID pData
|
|
)
|
|
{
|
|
TLoad64BitDllsMgr *pMgrInstance = reinterpret_cast<TLoad64BitDllsMgr *>(pData);
|
|
|
|
while(pMgrInstance->StillAlive())
|
|
{
|
|
Sleep(pMgrInstance->m_ExpirationTime);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: IncUIRefCnt
|
|
|
|
Description:
|
|
While poping other components UI , the server process
|
|
should never expire and that's why we incerement ref cnt
|
|
on UI objects.
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
IncUIRefCnt(
|
|
VOID
|
|
)
|
|
{
|
|
LockSelf();
|
|
{
|
|
//
|
|
// Since I am already in the critical section,
|
|
// I don't need to use InterLocked operations
|
|
//
|
|
m_UIRefCnt++;
|
|
}
|
|
ReleaseSelf();
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: DecUIRefCnt
|
|
|
|
Description:
|
|
We have to dec the ref cnt once the UI returns, in order
|
|
to be able to release the process once time expires
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
DecUIRefCnt(
|
|
VOID
|
|
)
|
|
{
|
|
LockSelf();
|
|
{
|
|
SPLASSERT(m_UIRefCnt);
|
|
//
|
|
// Since I am already in the critical section,
|
|
// I don't need to use InterLocked operations
|
|
//
|
|
m_UIRefCnt--;
|
|
}
|
|
ReleaseSelf();
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: GetUIRefCnt
|
|
|
|
Description:
|
|
Returns the current number of poped UIs
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
Number of poped UIs
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
GetUIRefCnt(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_UIRefCnt;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: ExecuteMonitorOperation
|
|
|
|
Description:
|
|
Loads the monitor UI Dll , Initializes the monitor UI ,
|
|
determines the required Monitor Operation , and start
|
|
the function whcih spins off this operation in a
|
|
separate Thread
|
|
|
|
Parameters:
|
|
DWORD hWnd : Windows Handle for parent windows
|
|
LPWSTR ServerName : Server Name
|
|
LPWSTR UIDllName : The Monitor UI Dll name
|
|
LPWSTR Name : Port Name or Monitor Name
|
|
PortOp Index : Required Operation
|
|
|
|
Return Value:
|
|
DWORD RetVal : ERROR_SUCCESS in case of success
|
|
ErrorCode in case of failure
|
|
--*/
|
|
BOOL
|
|
TLoad64BitDllsMgr ::
|
|
ExecuteMonitorOperation(
|
|
IN ULONG_PTR hWnd,
|
|
IN LPWSTR pszServerName,
|
|
IN LPWSTR pszUIDllName,
|
|
IN LPWSTR pszName,
|
|
IN EPortOp Index,
|
|
OUT PDWORD pErrorCode
|
|
)
|
|
{
|
|
PMONITORUI (*pfnInitializePrintMonitorUI)(VOID) = NULL;
|
|
RPC_STATUS RpcStatus;
|
|
HMODULE hLib = NULL;
|
|
HANDLE hActCtx = NULL;
|
|
ULONG_PTR lActCtx = 0;
|
|
BOOL bActivated = FALSE;
|
|
|
|
*pErrorCode = ERROR_SUCCESS;
|
|
|
|
if((RpcStatus = RpcImpersonateClient(0)) == RPC_S_OK)
|
|
{
|
|
RefreshLifeSpan();
|
|
|
|
//
|
|
// For Fusion, we run the code the gets us the
|
|
// monitor UI activation context
|
|
//
|
|
if((*pErrorCode = this->GetMonitorUIActivationContext(pszUIDllName,&hActCtx,&lActCtx,&bActivated)) == ERROR_SUCCESS)
|
|
{
|
|
if(hLib = LoadLibrary(pszUIDllName))
|
|
{
|
|
if(pfnInitializePrintMonitorUI = (PMONITORUI (*)(VOID))
|
|
GetProcAddress(hLib, "InitializePrintMonitorUI"))
|
|
{
|
|
PMONITORUI pMonitorUI;
|
|
|
|
if(pMonitorUI = (pfnInitializePrintMonitorUI)())
|
|
{
|
|
LPTHREAD_START_ROUTINE pThrdFn = NULL;
|
|
switch (Index)
|
|
{
|
|
case KAddPortOp:
|
|
{
|
|
pThrdFn = AddPortUI;
|
|
break;
|
|
}
|
|
|
|
case KConfigurePortOp:
|
|
case KDeletePortOp:
|
|
{
|
|
pThrdFn = (Index == KConfigurePortOp) ? ConfigurePortUI : DeletePortUI;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SPLASSERT(pThrdFn);
|
|
*pErrorCode = SpinPortOperationThread((HWND)hWnd,
|
|
pszServerName,
|
|
pszName,
|
|
pMonitorUI,
|
|
Index,
|
|
pThrdFn,
|
|
hLib,
|
|
hActCtx,
|
|
lActCtx,
|
|
bActivated
|
|
);
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: ExecuteMonitorOperation failed to Load Monitor Initializaiton fn. with %u\n",
|
|
*pErrorCode));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: ExecuteMonitorOperation failed to load Monitor UI Dll with %u\n",
|
|
*pErrorCode));
|
|
}
|
|
}
|
|
if(*pErrorCode != ERROR_SUCCESS)
|
|
{
|
|
ReleaseMonitorActivationContext(hLib,hActCtx,lActCtx,bActivated);
|
|
}
|
|
RpcStatus = RpcRevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = static_cast<DWORD>(RpcStatus);
|
|
}
|
|
|
|
return *pErrorCode == ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: SpinPortOperationThread
|
|
|
|
Description:
|
|
Spins the appropriate monitor operation in a separate thread
|
|
|
|
Parameters:
|
|
HWND hWnd : Windows Handle for parent windows
|
|
LPWSTR ServerName : Server Name
|
|
LPWSTR UIDllName : The Monitor UI Dll name
|
|
LPWSTR Name : Port Name or Monitor Name
|
|
PortOp Index : Required Operation
|
|
PMONITORUI pMonitorUI : Port Monitor Functions
|
|
LPTHREAD_START_ROUTINE pThrdFn : Internal Thread to be executed
|
|
|
|
Return Value:
|
|
DWORD RetVal : ERROR_SUCCESS in case of success
|
|
ErrorCode in case of failure
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
SpinPortOperationThread(
|
|
IN HWND hWnd,
|
|
IN LPWSTR pszServerName,
|
|
IN LPWSTR pszName,
|
|
IN PMONITORUI pMonitorUI,
|
|
IN EPortOp Index,
|
|
IN LPTHREAD_START_ROUTINE pThrdFn,
|
|
IN HMODULE hLib,
|
|
IN HANDLE hActCtx,
|
|
IN ULONG_PTR lActCtx,
|
|
IN BOOL bActivated
|
|
) const
|
|
{
|
|
DWORD UIThrdId = 0;
|
|
HANDLE hUIThrd = NULL;
|
|
DWORD RetVal = ERROR_SUCCESS;
|
|
SPortAddThreadData *pNewThreadData = NULL;
|
|
|
|
if(pNewThreadData = new SPortAddThreadData)
|
|
{
|
|
switch (Index)
|
|
{
|
|
case KAddPortOp:
|
|
{
|
|
pNewThreadData->pMonFnAdd = pMonitorUI->pfnAddPortUI;
|
|
pNewThreadData->pMonFns = NULL;
|
|
pNewThreadData->pszMonitorName = pszName;
|
|
pNewThreadData->pszPortName = NULL;
|
|
break;
|
|
}
|
|
|
|
case KConfigurePortOp:
|
|
case KDeletePortOp:
|
|
{
|
|
PFNMONITORFNS pfnMonitorsFns[2];
|
|
|
|
pfnMonitorsFns[0] = pMonitorUI->pfnConfigurePortUI;
|
|
pfnMonitorsFns[1] = pMonitorUI->pfnDeletePortUI;
|
|
|
|
pNewThreadData->pMonFnAdd = NULL;
|
|
pNewThreadData->pMonFns = pfnMonitorsFns[Index];
|
|
pNewThreadData->pszMonitorName = NULL;
|
|
pNewThreadData->pszPortName = pszName;
|
|
break;
|
|
}
|
|
}
|
|
pNewThreadData->hWnd = hWnd;
|
|
pNewThreadData->pszServerName = pszServerName;
|
|
pNewThreadData->ppszRetPortName = NULL;
|
|
pNewThreadData->hLib = hLib;
|
|
pNewThreadData->hActCtx = hActCtx;
|
|
pNewThreadData->lActCtx = lActCtx;
|
|
pNewThreadData->bActivated = bActivated;
|
|
|
|
if(!(hUIThrd = CreateThread(NULL,
|
|
0,
|
|
pThrdFn,
|
|
(PVOID)pNewThreadData,
|
|
0,
|
|
&UIThrdId)))
|
|
{
|
|
RetVal = GetLastError();
|
|
delete pNewThreadData;
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: SpinPortOperationThread failed to create Port Operation fn. with %u\n",
|
|
RetVal));
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hUIThrd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RetVal = ERROR_OUTOFMEMORY;
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: SpinPortOperationThread failed to allocate required memory with %u\n",
|
|
RetVal));
|
|
}
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: AddPortUI
|
|
|
|
Description:
|
|
Calls the monitor AddPort
|
|
|
|
Parameters:
|
|
PVOID InThrdData : Thread Data for Adding a Port
|
|
|
|
Return Value:
|
|
Always 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
AddPortUI(
|
|
IN PVOID pInThrdData
|
|
)
|
|
{
|
|
DWORD RetVal = ERROR_SUCCESS;
|
|
HANDLE hMsgThrd;
|
|
DWORD MsgThrdId;
|
|
|
|
SPortAddThreadData *pNewThreadData = reinterpret_cast<SPortAddThreadData *>(pInThrdData);
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
RetVal = (DWORD) pNewThreadData->pMonFnAdd(pNewThreadData->pszServerName,
|
|
pNewThreadData->hWnd,
|
|
pNewThreadData->pszMonitorName,
|
|
NULL);
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
//
|
|
// Here we should post a message to the caller client window to inform
|
|
// it that the operation was completed and also whether it was succesful
|
|
// or not
|
|
//
|
|
PostMessage(pNewThreadData->hWnd,WM_ENDADDPORT,
|
|
(WPARAM)RetVal,
|
|
(RetVal != ERROR_SUCCESS) ? ERROR_SUCCESS : (DWORD)GetLastError());
|
|
|
|
pGLdrObj->ReleaseMonitorActivationContext(pNewThreadData->hLib,
|
|
pNewThreadData->hActCtx,
|
|
pNewThreadData->lActCtx,
|
|
pNewThreadData->bActivated);
|
|
|
|
delete pInThrdData;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: DeletePortUI
|
|
|
|
Description:
|
|
Calls the monitor DeletePort
|
|
|
|
Parameters:
|
|
PVOID InThrdData : Thread Data for Adding a Port
|
|
|
|
Return Value:
|
|
Always 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
DeletePortUI(
|
|
IN PVOID pInThrdData
|
|
)
|
|
{
|
|
DWORD RetVal = ERROR_SUCCESS;
|
|
|
|
SPortAddThreadData *pNewThreadData = reinterpret_cast<SPortAddThreadData *>(pInThrdData);
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
RetVal = (DWORD) pNewThreadData->pMonFns(pNewThreadData->pszServerName,
|
|
pNewThreadData->hWnd,
|
|
pNewThreadData->pszPortName);
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
//
|
|
// Here we should post a message to the caller window to inform them
|
|
// the operation was completed and also whether it was succesful or
|
|
// not
|
|
//
|
|
PostMessage(pNewThreadData->hWnd,WM_ENDDELPORT,
|
|
(WPARAM)RetVal,
|
|
(RetVal != ERROR_SUCCESS) ? ERROR_SUCCESS : (DWORD)GetLastError());
|
|
|
|
pGLdrObj->ReleaseMonitorActivationContext(pNewThreadData->hLib,
|
|
pNewThreadData->hActCtx,
|
|
pNewThreadData->lActCtx,
|
|
pNewThreadData->bActivated);
|
|
|
|
delete pInThrdData;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: ConfigurePortUI
|
|
|
|
Description:
|
|
Calls the monitor ConfigurePort
|
|
|
|
Parameters:
|
|
PVOID InThrdData : Thread Data for Adding a Port
|
|
|
|
Return Value:
|
|
Always 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
ConfigurePortUI(
|
|
IN PVOID pInThrdData
|
|
)
|
|
{
|
|
DWORD RetVal = ERROR_SUCCESS;
|
|
|
|
SPortAddThreadData *pNewThreadData = reinterpret_cast<SPortAddThreadData *>(pInThrdData);
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
RetVal = (DWORD) pNewThreadData->pMonFns(pNewThreadData->pszServerName,
|
|
pNewThreadData->hWnd,
|
|
pNewThreadData->pszPortName);
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
//
|
|
// Here we should post a message to the caller window to inform them
|
|
// the operation was completed and also whether it was succesful or
|
|
// not
|
|
//
|
|
PostMessage(pNewThreadData->hWnd,WM_ENDCFGPORT,
|
|
(WPARAM)RetVal,
|
|
(RetVal != ERROR_SUCCESS) ? ERROR_SUCCESS : (DWORD)GetLastError());
|
|
|
|
pGLdrObj->ReleaseMonitorActivationContext(pNewThreadData->hLib,
|
|
pNewThreadData->hActCtx,
|
|
pNewThreadData->lActCtx,
|
|
pNewThreadData->bActivated);
|
|
|
|
delete pInThrdData;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: DeviceCapabilities
|
|
|
|
Description:
|
|
Queries the Device capabilities , by calling into
|
|
the driver
|
|
|
|
Parameters:
|
|
LPWSTR DeviceName : Device Name
|
|
LPWSTR PortName : Port Name
|
|
WORD Capabilities : Required Capabilites to Query for
|
|
DWORD DevModeSize : Input DevMode Size
|
|
LPBYTE DevMode : Input DevMode
|
|
BOOL ClonedOutputFill : Required To fill output DevMode
|
|
PDWORD ClonedOutputSize : Output DevMode size
|
|
LPBYTE* ClonedOutput : Output DevMode
|
|
|
|
Return Value:
|
|
int RetVal : -1 in case of Failure
|
|
: Some value depending on Capabilities flag in case
|
|
of Success
|
|
--*/
|
|
int
|
|
TLoad64BitDllsMgr ::
|
|
DeviceCapabilities(
|
|
IN LPWSTR pszDeviceName,
|
|
IN LPWSTR pszPortName,
|
|
IN WORD Capabilities,
|
|
IN DWORD DevModeSize,
|
|
IN LPBYTE pDevMode,
|
|
IN BOOL bClonedOutputFill,
|
|
OUT PDWORD pClonedOutputSize,
|
|
OUT LPBYTE *ppClonedOutput,
|
|
OUT PDWORD pErrorCode
|
|
)
|
|
{
|
|
HANDLE hPrinter = NULL;
|
|
HANDLE hDriver = NULL;
|
|
INT ReturnValue = -1;
|
|
INT_FARPROC pfn;
|
|
LPWSTR pszDriverFileName;
|
|
RPC_STATUS RpcStatus;
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
if((RpcStatus = RpcImpersonateClient(0)) == RPC_S_OK)
|
|
{
|
|
if (OpenPrinter((LPWSTR)pszDeviceName, &hPrinter, NULL))
|
|
{
|
|
if(hDriver = LoadPrinterDriver(hPrinter))
|
|
{
|
|
if (pfn = (INT_FARPROC)GetProcAddress(hDriver,
|
|
"DrvDeviceCapabilities"))
|
|
{
|
|
__try
|
|
{
|
|
*ppClonedOutput = NULL;
|
|
|
|
ReturnValue = (*pfn)(hPrinter,
|
|
pszDeviceName,
|
|
Capabilities,
|
|
(PVOID)*ppClonedOutput,
|
|
(PDEVMODE)pDevMode);
|
|
if(ReturnValue != -1 &&
|
|
ReturnValue != 0 &&
|
|
bClonedOutputFill &&
|
|
DevCapFillsOutput(Capabilities))
|
|
{
|
|
if(*ppClonedOutput = new BYTE[*pClonedOutputSize = CalcReqSizeForDevCaps(ReturnValue,
|
|
Capabilities)])
|
|
{
|
|
ZeroMemory(*ppClonedOutput,*pClonedOutputSize);
|
|
if((ReturnValue = (*pfn)(hPrinter,
|
|
pszDeviceName,
|
|
Capabilities,
|
|
(PVOID)*ppClonedOutput,
|
|
(PDEVMODE)pDevMode)) == -1)
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ReturnValue = -1;
|
|
*pErrorCode = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if(!ReturnValue)
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
}
|
|
}
|
|
__except(1)
|
|
{
|
|
SetLastError(GetExceptionCode());
|
|
ReturnValue = -1;
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: DeviceCapabilities failed to allocate memory"));
|
|
}
|
|
}
|
|
FreeLibrary(hDriver);
|
|
}
|
|
else
|
|
{ *pErrorCode = GetLastError();
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: DeviceCapabilities failed to load driver with %u\n",
|
|
*pErrorCode));
|
|
}
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = GetLastError();
|
|
DBGMSG(DBG_WARN, ("TLoad64BitDllsMgr :: DeviceCapabilities failed to open printer with %u\n",
|
|
*pErrorCode));
|
|
}
|
|
RpcStatus = RpcRevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = RpcStatus;
|
|
}
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: DevCapFillsOutput
|
|
|
|
Description:
|
|
Does the capability fill out an out buffer or not
|
|
|
|
Parameters:
|
|
DWORD Capabilites : The required Capability
|
|
|
|
|
|
Return Value:
|
|
BOOL : 1 OR 0
|
|
--*/
|
|
BOOL
|
|
TLoad64BitDllsMgr ::
|
|
DevCapFillsOutput(
|
|
IN DWORD Capabilities
|
|
) const
|
|
{
|
|
SPLASSERT(Capabilities>0 && Capabilities<= DC_NUP);
|
|
|
|
return(!!DeviceCapsReqSize[Capabilities-1]);
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: CalcReqSizeForDevCaps
|
|
|
|
Description:
|
|
Given the required capability returns the size required
|
|
for all enumerated values of it
|
|
|
|
Parameters:
|
|
DWORD CapNum : Num Of Items for given Capability
|
|
DWORD Capabilites : The required Capability
|
|
|
|
|
|
Return Value:
|
|
DWORD : Required size to store all items of capability
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
CalcReqSizeForDevCaps(
|
|
IN DWORD CapNum,
|
|
IN DWORD Capabilities
|
|
) const
|
|
{
|
|
SPLASSERT(Capabilities>0 && Capabilities<= DC_NUP);
|
|
|
|
return((Capabilities && DeviceCapsReqSize[Capabilities-1]) ?
|
|
(CapNum * DeviceCapsReqSize[Capabilities-1]) :
|
|
CapNum);
|
|
|
|
}
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: DocumentProperties
|
|
|
|
Description:
|
|
Displays the driver specific properties
|
|
|
|
Parameters:
|
|
HWND hWnd : Parent Window Handle
|
|
LPWSTR PrinterName : Printer Name
|
|
PDWORD ClonedDevModeOutSize : Output DevMode size
|
|
LPBYTE* ClonedDevModeOut : Output DevMode
|
|
DWORD DevModeSize : Input DevMode Size
|
|
LPBYTE DevMode : Input DevMode
|
|
WORD Capabilities : Required Capabilites to Query for
|
|
BOOL ClonedDevModeOutFill : Required To fill output DevMode
|
|
DWORD fMode : Mode Options
|
|
|
|
Return Value:
|
|
int RetVal : -1 in case of Failure
|
|
: Some value depending on fMode flag and DevModes
|
|
and this might be posted to the client window in
|
|
case of running asynchronously
|
|
--*/
|
|
LONG
|
|
TLoad64BitDllsMgr ::
|
|
DocumentProperties(
|
|
IN ULONG_PTR hWnd,
|
|
IN LPWSTR pszPrinterName,
|
|
OUT PDWORD pTouchedDevModeSize,
|
|
OUT PDWORD pClonedDevModeOutSize,
|
|
OUT LPBYTE *ppClonedDevModeOut,
|
|
IN DWORD DevModeSize,
|
|
IN LPBYTE pDevMode,
|
|
IN BOOL bClonedDevModeOutFill,
|
|
IN DWORD fMode,
|
|
OUT PDWORD pErrorCode
|
|
)
|
|
{
|
|
|
|
LONG RetVal = -1;
|
|
SDocPropsThreadData *pNewThrdData = NULL;
|
|
RPC_STATUS RpcStatus;
|
|
|
|
if((RpcStatus = RpcImpersonateClient(0)) == RPC_S_OK)
|
|
{
|
|
RefreshLifeSpan();
|
|
|
|
if(pNewThrdData = new SDocPropsThreadData)
|
|
{
|
|
pNewThrdData->hWnd = (HWND)hWnd;
|
|
pNewThrdData->pszPrinterName = pszPrinterName;
|
|
pNewThrdData->pClonedDevModeOutSize = pClonedDevModeOutSize;
|
|
pNewThrdData->pTouchedDevModeSize = pTouchedDevModeSize;
|
|
pNewThrdData->ppClonedDevModeOut = ppClonedDevModeOut;
|
|
pNewThrdData->DevModeSize = DevModeSize;
|
|
pNewThrdData->pDevMode = pDevMode;
|
|
pNewThrdData->bClonedDevModeOutFill = bClonedDevModeOutFill;
|
|
pNewThrdData->fMode = fMode;
|
|
pNewThrdData->fExclusionFlags = 0;
|
|
pNewThrdData->ErrorCode = ERROR_SUCCESS;
|
|
pNewThrdData->RetVal = -1;
|
|
InternalDocumentProperties((PVOID)pNewThrdData);
|
|
|
|
RetVal = pNewThrdData->RetVal;
|
|
*pErrorCode = pNewThrdData->ErrorCode;
|
|
|
|
delete pNewThrdData;
|
|
}
|
|
RpcStatus = RpcRevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = RpcStatus;
|
|
}
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: AsyncDocumentProperties
|
|
|
|
Description:
|
|
Displays the driver specific UI in a separate sheet
|
|
|
|
Parameters:
|
|
PVOID : Thread Data
|
|
|
|
Return Value:
|
|
Always returns 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
InternalDocumentProperties(
|
|
PVOID pInThrdData
|
|
)
|
|
{
|
|
|
|
DOCUMENTPROPERTYHEADER DPHdr;
|
|
HANDLE hPrinter = NULL;
|
|
SDocPropsThreadData *pNewThreadData = reinterpret_cast<SDocPropsThreadData *>(pInThrdData);
|
|
TLoad64BitDllsMgr *pMgrInstance = pNewThreadData->pMgrInstance;
|
|
HWND hWnd = pNewThreadData->hWnd;
|
|
LPWSTR pszPrinterName = pNewThreadData->pszPrinterName;
|
|
PDWORD pClonedDevModeOutSize = pNewThreadData->pClonedDevModeOutSize;
|
|
PDWORD pTouchedDevModeSize = pNewThreadData->pTouchedDevModeSize;
|
|
LPBYTE* ppClonedDevModeOut = pNewThreadData->ppClonedDevModeOut;
|
|
DWORD DevModeSize = pNewThreadData->DevModeSize;
|
|
LPBYTE pDevMode = pNewThreadData->pDevMode;
|
|
BOOL bClonedDevModeOutFill = pNewThreadData->bClonedDevModeOutFill;
|
|
DWORD fMode = pNewThreadData->fMode;
|
|
HMODULE hWinSpool = NULL;
|
|
PFNDOCPROPSHEETS pfnDocPropSheets = NULL;
|
|
LONG Result = -1;
|
|
LONG cbOut = 0;
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
if(hWinSpool = LoadLibrary(L"winspool.drv"))
|
|
{
|
|
if(pfnDocPropSheets = reinterpret_cast<PFNDOCPROPSHEETS>(GetProcAddress(hWinSpool,
|
|
"DocumentPropertySheets")))
|
|
{
|
|
if(OpenPrinter(pszPrinterName,&hPrinter,NULL))
|
|
{
|
|
//
|
|
// Do I need to protect the printer handle ?????
|
|
//
|
|
DPHdr.cbSize = sizeof(DPHdr);
|
|
DPHdr.Reserved = 0;
|
|
DPHdr.hPrinter = hPrinter;
|
|
DPHdr.pszPrinterName = pszPrinterName;
|
|
|
|
if(bClonedDevModeOutFill)
|
|
{
|
|
DPHdr.pdmIn = NULL;
|
|
DPHdr.pdmOut = NULL;
|
|
DPHdr.fMode = 0;
|
|
|
|
cbOut = pfnDocPropSheets(NULL, (LPARAM)&DPHdr);
|
|
|
|
//
|
|
// The function returns zero or a negative number when it fails.
|
|
//
|
|
if (cbOut > 0)
|
|
{
|
|
DPHdr.cbOut = cbOut;
|
|
if(*ppClonedDevModeOut = new BYTE[DPHdr.cbOut])
|
|
{
|
|
ZeroMemory(*ppClonedDevModeOut, DPHdr.cbOut);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPHdr.cbOut = 0;
|
|
*ppClonedDevModeOut = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPHdr.cbOut = 0;
|
|
*ppClonedDevModeOut = NULL;
|
|
}
|
|
|
|
*pClonedDevModeOutSize = DPHdr.cbOut;
|
|
|
|
DPHdr.pdmIn = (PDEVMODE)pDevMode;
|
|
DPHdr.pdmOut = (PDEVMODE)*ppClonedDevModeOut;
|
|
DPHdr.fMode = fMode;
|
|
|
|
if (fMode & DM_PROMPT)
|
|
{
|
|
PFNCALLCOMMONPROPSHEETUI pfnCallCommonPropSheeUI = NULL;
|
|
Result = CPSUI_CANCEL;
|
|
|
|
if(pfnCallCommonPropSheeUI= reinterpret_cast<PFNCALLCOMMONPROPSHEETUI>(GetProcAddress(hWinSpool,
|
|
(LPCSTR) MAKELPARAM(218, 0))))
|
|
{
|
|
pGLdrObj->IncUIRefCnt();
|
|
if(pfnCallCommonPropSheeUI(hWnd,
|
|
pfnDocPropSheets,
|
|
(LPARAM)&DPHdr,
|
|
(LPDWORD)&Result) < 0)
|
|
{
|
|
Result = -1;
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
Result = (Result == CPSUI_OK) ? IDOK : IDCANCEL;
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
}
|
|
else
|
|
{
|
|
Result = -1;
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Result = pfnDocPropSheets(NULL, (LPARAM)&DPHdr);
|
|
if(Result<0)
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Here we try to adjust the required memory . Sometimes it is less
|
|
//
|
|
if((PDEVMODE)*ppClonedDevModeOut)
|
|
{
|
|
if((DWORD)(((PDEVMODE)*ppClonedDevModeOut)->dmSize +
|
|
((PDEVMODE)*ppClonedDevModeOut)->dmDriverExtra) <
|
|
*pClonedDevModeOutSize)
|
|
{
|
|
*pTouchedDevModeSize = (((PDEVMODE)*ppClonedDevModeOut)->dmSize +
|
|
((PDEVMODE)*ppClonedDevModeOut)->dmDriverExtra);
|
|
}
|
|
else
|
|
{
|
|
*pTouchedDevModeSize = *pClonedDevModeOutSize;
|
|
}
|
|
}
|
|
|
|
if(hPrinter)
|
|
{
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
FreeLibrary(hWinSpool);
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
if(hWnd && (fMode & DM_PROMPT))
|
|
{
|
|
PostMessage(pNewThreadData->hWnd,WM_ENDDOCUMENTPROPERTIES,
|
|
(WPARAM)Result,
|
|
(LPARAM)pNewThreadData->ErrorCode);
|
|
}
|
|
pNewThreadData->RetVal = Result;
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: PrinUIDocumentProperties
|
|
|
|
Description:
|
|
Displays the driver specific properties
|
|
|
|
Parameters:
|
|
HWND hWnd : Parent Window Handle
|
|
LPWSTR PrinterName : Printer Name
|
|
PDWORD ClonedDevModeOutSize : Output DevMode size
|
|
LPBYTE* ClonedDevModeOut : Output DevMode
|
|
DWORD DevModeSize : Input DevMode Size
|
|
LPBYTE DevMode : Input DevMode
|
|
WORD Capabilities : Required Capabilites to Query for
|
|
BOOL ClonedDevModeOutFill : Required To fill output DevMode
|
|
DWORD fMode : Mode Options
|
|
|
|
Return Value:
|
|
int RetVal : -1 in case of Failure
|
|
: Some value depending on fMode flag and DevModes
|
|
and this might be posted to the client window in
|
|
case of running asynchronously
|
|
--*/
|
|
LONG
|
|
TLoad64BitDllsMgr ::
|
|
PrintUIDocumentProperties(
|
|
IN ULONG_PTR hWnd,
|
|
IN LPWSTR pszPrinterName,
|
|
OUT PDWORD pTouchedDevModeSize,
|
|
OUT PDWORD pClonedDevModeOutSize,
|
|
OUT LPBYTE *ppClonedDevModeOut,
|
|
IN DWORD DevModeSize,
|
|
IN LPBYTE pDevMode,
|
|
IN BOOL bClonedDevModeOutFill,
|
|
IN DWORD fMode,
|
|
IN DWORD fExclusionFlags,
|
|
OUT PDWORD pErrorCode
|
|
)
|
|
{
|
|
|
|
LONG RetVal = -1;
|
|
SDocPropsThreadData *pNewThrdData = NULL;
|
|
RPC_STATUS RpcStatus;
|
|
|
|
|
|
if((RpcStatus = RpcImpersonateClient(0)) == RPC_S_OK)
|
|
{
|
|
RefreshLifeSpan();
|
|
|
|
if(pNewThrdData = new SDocPropsThreadData)
|
|
{
|
|
pNewThrdData->hWnd = (HWND)hWnd;
|
|
pNewThrdData->pszPrinterName = pszPrinterName;
|
|
pNewThrdData->pClonedDevModeOutSize = pClonedDevModeOutSize;
|
|
pNewThrdData->pTouchedDevModeSize = pTouchedDevModeSize;
|
|
pNewThrdData->ppClonedDevModeOut = ppClonedDevModeOut;
|
|
pNewThrdData->DevModeSize = DevModeSize;
|
|
pNewThrdData->pDevMode = pDevMode;
|
|
pNewThrdData->bClonedDevModeOutFill = bClonedDevModeOutFill;
|
|
pNewThrdData->fMode = fMode;
|
|
pNewThrdData->fExclusionFlags = fExclusionFlags;
|
|
pNewThrdData->ErrorCode = ERROR_SUCCESS;
|
|
pNewThrdData->RetVal = -1;
|
|
InternalPrintUIDocumentProperties((PVOID)pNewThrdData);
|
|
|
|
RetVal = pNewThrdData->RetVal;
|
|
*pErrorCode = pNewThrdData->ErrorCode;
|
|
|
|
delete pNewThrdData;
|
|
}
|
|
|
|
RpcStatus = RpcRevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
*pErrorCode = RpcStatus;
|
|
}
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: AsyncDocumentProperties
|
|
|
|
Description:
|
|
Displays the driver specific UI in a separate sheet
|
|
|
|
Parameters:
|
|
PVOID : Thread Data
|
|
|
|
Return Value:
|
|
Always returns 0
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
InternalPrintUIDocumentProperties(
|
|
PVOID pInThrdData
|
|
)
|
|
{
|
|
|
|
DOCUMENTPROPERTYHEADER DPHdr;
|
|
HANDLE hPrinter = NULL;
|
|
SDocPropsThreadData *pNewThreadData = reinterpret_cast<SDocPropsThreadData *>(pInThrdData);
|
|
TLoad64BitDllsMgr *pMgrInstance = pNewThreadData->pMgrInstance;
|
|
HWND hWnd = pNewThreadData->hWnd;
|
|
LPWSTR pszPrinterName = pNewThreadData->pszPrinterName;
|
|
PDWORD pClonedDevModeOutSize = pNewThreadData->pClonedDevModeOutSize;
|
|
PDWORD pTouchedDevModeSize = pNewThreadData->pTouchedDevModeSize;
|
|
LPBYTE* ppClonedDevModeOut = pNewThreadData->ppClonedDevModeOut;
|
|
DWORD DevModeSize = pNewThreadData->DevModeSize;
|
|
LPBYTE pDevMode = pNewThreadData->pDevMode;
|
|
BOOL bClonedDevModeOutFill = pNewThreadData->bClonedDevModeOutFill;
|
|
DWORD fMode = pNewThreadData->fMode;
|
|
DWORD fExclusionFlags = pNewThreadData->fExclusionFlags;
|
|
HMODULE hWinSpool = NULL;
|
|
PFNDOCPROPSHEETS pfnDocPropSheets = NULL;
|
|
LONG Result = -1;
|
|
|
|
pGLdrObj->IncUIRefCnt();
|
|
{
|
|
if(hWinSpool = LoadLibrary(L"winspool.drv"))
|
|
{
|
|
if(pfnDocPropSheets = reinterpret_cast<PFNDOCPROPSHEETS>(GetProcAddress(hWinSpool,
|
|
"DocumentPropertySheets")))
|
|
{
|
|
if(OpenPrinter(pszPrinterName,&hPrinter,NULL))
|
|
{
|
|
DPHdr.cbSize = sizeof(DPHdr);
|
|
DPHdr.Reserved = 0;
|
|
DPHdr.hPrinter = hPrinter;
|
|
DPHdr.pszPrinterName = pszPrinterName;
|
|
|
|
if(bClonedDevModeOutFill)
|
|
{
|
|
DPHdr.pdmIn = NULL;
|
|
DPHdr.pdmOut = NULL;
|
|
DPHdr.fMode = 0;
|
|
|
|
DPHdr.cbOut = pfnDocPropSheets(NULL,
|
|
(LPARAM)&DPHdr);
|
|
|
|
*ppClonedDevModeOut = new BYTE[DPHdr.cbOut];
|
|
}
|
|
else
|
|
{
|
|
DPHdr.cbOut = 0;
|
|
*ppClonedDevModeOut = NULL;
|
|
}
|
|
|
|
*pClonedDevModeOutSize = DPHdr.cbOut;
|
|
|
|
PFNPRINTUIDOCUMENTPROPERTIES pfnPrintUIDocumentProperties = NULL;
|
|
HMODULE hPrintUI = NULL;
|
|
|
|
if(hPrintUI = LoadLibrary(L"printui.dll"))
|
|
{
|
|
if(pfnPrintUIDocumentProperties = reinterpret_cast<PFNPRINTUIDOCUMENTPROPERTIES>(GetProcAddress(hPrintUI,
|
|
"DocumentPropertiesWrap")))
|
|
{
|
|
pGLdrObj->IncUIRefCnt();
|
|
Result = pfnPrintUIDocumentProperties(hWnd,
|
|
hPrinter,
|
|
pszPrinterName,
|
|
(PDEVMODE)*ppClonedDevModeOut,
|
|
(PDEVMODE)pDevMode,
|
|
fMode,
|
|
fExclusionFlags
|
|
);
|
|
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
|
|
pGLdrObj->DecUIRefCnt();
|
|
//
|
|
// Here we try to adjust the required memory . Sometimes it is less
|
|
//
|
|
if((PDEVMODE)*ppClonedDevModeOut)
|
|
{
|
|
if((DWORD)(((PDEVMODE)*ppClonedDevModeOut)->dmSize +
|
|
((PDEVMODE)*ppClonedDevModeOut)->dmDriverExtra) <
|
|
*pClonedDevModeOutSize)
|
|
{
|
|
*pTouchedDevModeSize = (((PDEVMODE)*ppClonedDevModeOut)->dmSize +
|
|
((PDEVMODE)*ppClonedDevModeOut)->dmDriverExtra);
|
|
}
|
|
else
|
|
{
|
|
*pTouchedDevModeSize = *pClonedDevModeOutSize;
|
|
}
|
|
}
|
|
}
|
|
FreeLibrary(hPrintUI);
|
|
}
|
|
|
|
if(hPrinter)
|
|
{
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
FreeLibrary(hWinSpool);
|
|
}
|
|
else
|
|
{
|
|
pNewThreadData->ErrorCode = GetLastError();
|
|
}
|
|
if(hWnd)
|
|
{
|
|
PostMessage(pNewThreadData->hWnd,WM_ENDPRINTUIDOCUMENTPROPERTIES,
|
|
(WPARAM)Result,
|
|
(LPARAM)pNewThreadData->ErrorCode);
|
|
}
|
|
pNewThreadData->RetVal = Result;
|
|
}
|
|
pGLdrObj->DecUIRefCnt();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: GetCurrSeesionId
|
|
|
|
Description:
|
|
returns the Current Session ID for terminal server
|
|
sessions
|
|
|
|
Parameters:
|
|
None
|
|
|
|
Return Value:
|
|
DWORD: Session ID
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
GetCurrSessionId() const
|
|
{
|
|
return m_CurrSessionId;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: GetMonitorUIActivationContext
|
|
|
|
Description:
|
|
This routine gets the monitor UI activation context and then
|
|
activates the context. If the monitor does not have an activation
|
|
context in it's resource file it will activate the empty context
|
|
for compatiblity with previous version of common control.
|
|
|
|
Parameters:
|
|
pszUIDllName - The name of the monitor ui DLL.
|
|
phActCtx - Pointer to the activation context handle
|
|
|
|
Return Value:
|
|
DWORD: Error Code if any else ERROR_SUCCESS
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
GetMonitorUIActivationContext(
|
|
IN LPWSTR pszUIDllName,
|
|
IN OUT HANDLE *phActCtx,
|
|
IN OUT ULONG_PTR *plActCtx,
|
|
IN OUT BOOL *pbActivated
|
|
) const
|
|
{
|
|
DWORD ErrorCode = ERROR_SUCCESS;
|
|
LPWSTR pszFullPath = NULL;
|
|
|
|
if(!pszUIDllName)
|
|
{
|
|
ErrorCode = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if(pszFullPath = new WCHAR[MAX_PATH])
|
|
{
|
|
ZeroMemory(pszFullPath,MAX_PATH*sizeof(WCHAR));
|
|
if((ErrorCode = this->GetMonitorUIFullPath(pszUIDllName,pszFullPath)) == ERROR_SUCCESS)
|
|
{
|
|
ACTCTX ActCtx;
|
|
|
|
ZeroMemory(&ActCtx, sizeof(ActCtx));
|
|
|
|
ActCtx.cbSize = sizeof(ActCtx);
|
|
ActCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
|
|
ActCtx.lpSource = pszFullPath;
|
|
ActCtx.lpResourceName = MAKEINTRESOURCE(ACTIVATION_CONTEXT_RESOURCE_ID);
|
|
|
|
if((*phActCtx = CreateActCtx(&ActCtx)) == INVALID_HANDLE_VALUE)
|
|
{
|
|
*phActCtx = ACTCTX_EMPTY;
|
|
if(!ActivateActCtx(*phActCtx,plActCtx))
|
|
{
|
|
ErrorCode = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
*pbActivated = TRUE;
|
|
}
|
|
}
|
|
}
|
|
delete [] pszFullPath;
|
|
}
|
|
else
|
|
{
|
|
ErrorCode = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return ErrorCode;
|
|
}
|
|
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: GetMonitorUIFullPath
|
|
|
|
Description:
|
|
Functioning returning the full path to create an activation context.
|
|
We have at this stage the monitor name not the full path.
|
|
|
|
Parameters:
|
|
pszUIDllName - The name of the monitor ui DLL.
|
|
pszFullPath - The FullPath
|
|
|
|
Return Value:
|
|
DWORD: Error Code if any else ERROR_SUCCESS
|
|
|
|
--*/
|
|
DWORD
|
|
TLoad64BitDllsMgr ::
|
|
GetMonitorUIFullPath(
|
|
IN LPWSTR pszUIDllName,
|
|
IN OUT LPWSTR pszFullPath
|
|
) const
|
|
{
|
|
DWORD ErrorCode = ERROR_SUCCESS;
|
|
PWSTR pszFileName = NULL;
|
|
DWORD CchCount;
|
|
|
|
|
|
if( !pszFullPath && !pszUIDllName)
|
|
{
|
|
ErrorCode = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the monitor full path and the monitor name.
|
|
// pszFullPath is already allocated of MAX_PATH size.
|
|
//
|
|
if (!GetFullPathName(pszUIDllName, MAX_PATH, pszFullPath, &pszFileName))
|
|
{
|
|
ErrorCode = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
ErrorCode = ERROR_INVALID_NAME;
|
|
//
|
|
// Check to see if the monitor name came as a fully qualified path.
|
|
//
|
|
if (_wcsicmp(pszFullPath, pszUIDllName) == 0)
|
|
{
|
|
//
|
|
// We got a full path. Use it as it is.
|
|
//
|
|
ErrorCode = ERROR_SUCCESS;
|
|
}
|
|
else if (_wcsicmp(pszFileName, pszUIDllName) == 0)
|
|
{
|
|
//
|
|
// Xcv can return the monitor name. We want to build the full path
|
|
// out of the name and system directory.
|
|
//
|
|
if (!(CchCount = GetSystemDirectory(pszFullPath, MAX_PATH)))
|
|
{
|
|
ErrorCode = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Append the monitor name to the system directory.
|
|
//
|
|
ErrorCode = StatusFromHResult(StringCchPrintf(pszFullPath + CchCount,
|
|
MAX_PATH - CchCount,
|
|
L"\\%s",
|
|
pszUIDllName));
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Check if the file actually exists.
|
|
//
|
|
if (ErrorCode == ERROR_SUCCESS)
|
|
{
|
|
if (GetFileAttributes(pszFullPath) == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
ErrorCode = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ErrorCode;
|
|
}
|
|
|
|
/*++
|
|
Function Name:
|
|
TLoad64BitDllsMgr :: ReleaseMonitorActivationContext
|
|
|
|
Description:
|
|
This function releases data relative to activating the monitor UI
|
|
context. It is responsible of releasing the monitor library as well
|
|
the monitor fusion activation context. Note this function is called
|
|
in error cases when GetMonitorUI fails so all the parameters must be
|
|
checked for validity before use.
|
|
|
|
Parameters:
|
|
hLib - The handle of the monitor ui DLL.
|
|
hActCtx - The Activation context
|
|
lActCtx = The Activation Cookie
|
|
|
|
Return Value:
|
|
VOID
|
|
|
|
--*/
|
|
VOID
|
|
TLoad64BitDllsMgr ::
|
|
ReleaseMonitorActivationContext(
|
|
IN HINSTANCE hLib ,
|
|
IN HANDLE hActCtx ,
|
|
IN ULONG_PTR lActCtx ,
|
|
IN BOOL bActivated
|
|
) const
|
|
{
|
|
//
|
|
// Release the monitor library.
|
|
//
|
|
if (hLib)
|
|
{
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
//
|
|
// If we have an activation cookie then deactivate this context
|
|
//
|
|
if (bActivated)
|
|
{
|
|
DeactivateActCtx(0 , lActCtx);
|
|
}
|
|
|
|
//
|
|
// If we have created an activation context then release it.
|
|
//
|
|
if (hActCtx != INVALID_HANDLE_VALUE && hActCtx != ACTCTX_EMPTY)
|
|
{
|
|
ReleaseActCtx(hActCtx);
|
|
}
|
|
}
|