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.
595 lines
19 KiB
595 lines
19 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
dllmain.cpp
|
|
|
|
Abstract:
|
|
Implementation of DLL Exports.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 04/15/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
CComModule _Module;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CreateObject_RemoteDesktopSession( /*[in] */ REMOTE_DESKTOP_SHARING_CLASS sharingClass ,
|
|
/*[in] */ long lTimeout ,
|
|
/*[in] */ BSTR bstrConnectionParms ,
|
|
/*[in] */ BSTR bstrUserHelpBlob ,
|
|
/*[out, retval]*/ ISAFRemoteDesktopSession* *ppRCS );
|
|
|
|
HRESULT ConnectToExpert(/* [in] */ BSTR bstrExpertConnectParm,
|
|
/* [in] */ LONG lTimeout,
|
|
/* [retval][out] */ LONG *lSafErrorCode);
|
|
|
|
HRESULT SwitchDesktopMode(/* [in]*/ int nMode,
|
|
/* [in]*/ int nRAType);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef DEBUG
|
|
#define LAUNCH_TIMEOUT (600) // 1 minute.
|
|
#else
|
|
#define LAUNCH_TIMEOUT (300) // 10 seconds.
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const CLSID* pCLSID_PCHUpdate = &__uuidof( PCHUpdate );
|
|
static const CLSID* pCLSID_PCHUpdateReal = &__uuidof( PCHUpdateReal );
|
|
static const CLSID* pCLSID_PCHService = &__uuidof( PCHService );
|
|
static const CLSID* pCLSID_PCHServiceReal = &__uuidof( PCHServiceReal );
|
|
#ifndef NOJETBLUECOM
|
|
static const CLSID* pCLSID_PCHDBSession = &__uuidof( PCHDBSession );
|
|
static const CLSID* pCLSID_PCHDBSessionReal = &__uuidof( PCHDBSessionReal );
|
|
#endif
|
|
static const CLSID* pCLSID_MPCConnection = &__uuidof( MPCConnection );
|
|
static const CLSID* pCLSID_MPCConnectionReal = &__uuidof( MPCConnectionReal );
|
|
static const CLSID* pCLSID_MPCUpload = &__uuidof( MPCUpload );
|
|
static const CLSID* pCLSID_MPCUploadReal = &__uuidof( MPCUploadReal );
|
|
|
|
static const IID* pIID_IPCHService = &__uuidof( IPCHService );
|
|
|
|
static const WCHAR s_szRegKey [] = L"SOFTWARE\\Microsoft\\PCHealth\\PchSvc\\Profile";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const WCHAR s_szCmd_HelpSvc [] = L"\"%WINDIR%\\PCHealth\\HelpCtr\\Binaries\\HelpSvc.exe\" /Embedding";
|
|
static const WCHAR s_szCmd_UploadMgr [] = L"\"%WINDIR%\\PCHealth\\UploadLB\\Binaries\\UploadM.exe\" /Embedding";
|
|
|
|
static CComRedirectorFactory s_HelpSvc[] =
|
|
{
|
|
CComRedirectorFactory( pCLSID_PCHService, pCLSID_PCHServiceReal, pIID_IPCHService, s_szCmd_HelpSvc ),
|
|
CComRedirectorFactory( pCLSID_PCHUpdate , pCLSID_PCHUpdateReal , NULL , s_szCmd_HelpSvc ),
|
|
#ifndef NOJETBLUECOM
|
|
CComRedirectorFactory( pCLSID_PCHDBSession , pCLSID_PCHDBSessionReal , NULL , s_szCmd_HelpSvc ),
|
|
#endif
|
|
CComRedirectorFactory( NULL , NULL , NULL , NULL ),
|
|
};
|
|
|
|
static CComRedirectorFactory s_UploadMgr[] =
|
|
{
|
|
CComRedirectorFactory( pCLSID_MPCUpload , pCLSID_MPCUploadReal , NULL, s_szCmd_UploadMgr ),
|
|
CComRedirectorFactory( pCLSID_MPCConnection, pCLSID_MPCConnectionReal, NULL, s_szCmd_UploadMgr ),
|
|
CComRedirectorFactory( NULL , NULL , NULL, NULL ),
|
|
};
|
|
|
|
static ServiceHandler* s_Services[2];
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const WCHAR s_szCmd_RDSHost [] = L"\"%WINDIR%\\system32\\RDSHOST.exe\"";
|
|
|
|
static CComRedirectorFactory g_RDSHost( NULL, &CLSID_SAFRemoteDesktopServerHost, &IID_ISAFRemoteDesktopServerHost, s_szCmd_RDSHost );
|
|
|
|
HRESULT RDSHost_HACKED_CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
|
|
{
|
|
return g_RDSHost.CreateInstance( pUnkOuter, riid, ppvObj );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CComRedirectorFactory::CComRedirectorFactory( const CLSID* pclsid ,
|
|
const CLSID* pclsidReal ,
|
|
const IID* piidDirecty ,
|
|
LPCWSTR szExecutable )
|
|
{
|
|
m_pclsid = pclsid;
|
|
m_pclsidReal = pclsidReal;
|
|
m_piidDirecty = piidDirecty;
|
|
m_szExecutable = szExecutable;
|
|
m_dwRegister = 0;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP_(ULONG) CComRedirectorFactory::AddRef()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CComRedirectorFactory::Release()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
STDMETHODIMP CComRedirectorFactory::QueryInterface(REFIID iid, void ** ppvObject)
|
|
{
|
|
if(ppvObject == NULL) return E_POINTER;
|
|
|
|
*ppvObject = NULL;
|
|
|
|
if(InlineIsEqualGUID( IID_IUnknown , iid ) ||
|
|
InlineIsEqualGUID( IID_IClassFactory, iid ) )
|
|
{
|
|
*ppvObject = (IClassFactory*)this; // No AddRef, these objects are static...
|
|
return S_OK;
|
|
}
|
|
else if(InlineIsEqualGUID( IID_IDispatch , iid ) ||
|
|
InlineIsEqualGUID( IID_IPCHUtility, iid ) )
|
|
{
|
|
*ppvObject = (IPCHUtility*)this; // No AddRef, these objects are static...
|
|
return S_OK;
|
|
}
|
|
else if(m_piidDirecty && InlineIsEqualGUID( *m_piidDirecty, iid ))
|
|
{
|
|
return GetServer( NULL, iid, ppvObject );
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CComRedirectorFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
|
|
{
|
|
return StartServer( pUnkOuter, riid, ppvObj );
|
|
}
|
|
|
|
STDMETHODIMP CComRedirectorFactory::LockServer(BOOL fLock)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CComRedirectorFactory::CreateObject_RemoteDesktopSession( /*[in] */ REMOTE_DESKTOP_SHARING_CLASS sharingClass ,
|
|
/*[in] */ long lTimeout ,
|
|
/*[in] */ BSTR bstrConnectionParms ,
|
|
/*[in] */ BSTR bstrUserHelpBlob ,
|
|
/*[out, retval]*/ ISAFRemoteDesktopSession* *ppRCS )
|
|
{
|
|
return ::CreateObject_RemoteDesktopSession( sharingClass ,
|
|
lTimeout ,
|
|
bstrConnectionParms ,
|
|
bstrUserHelpBlob ,
|
|
ppRCS );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CComRedirectorFactory::ConnectToExpert(/* [in] */ BSTR bstrExpertConnectParm,
|
|
/* [in] */ LONG lTimeout,
|
|
/* [retval][out] */ LONG *lSafErrorCode)
|
|
|
|
{
|
|
return ::ConnectToExpert( bstrExpertConnectParm,
|
|
lTimeout,
|
|
lSafErrorCode);
|
|
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CComRedirectorFactory::SwitchDesktopMode(/* [in]*/ int nMode,
|
|
/* [in]*/ int nRAType)
|
|
|
|
{
|
|
return ::SwitchDesktopMode(nMode, nRAType);
|
|
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CComRedirectorFactory::GetServer( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
|
|
{
|
|
return ::CoCreateInstance( *m_pclsidReal, pUnkOuter, CLSCTX_LOCAL_SERVER, riid, ppvObj );
|
|
}
|
|
|
|
bool CComRedirectorFactory::GetCommandLine( /*[out]*/ WCHAR* rgCommandLine, /*[in]*/ DWORD dwSize, /*[out]*/ bool& fProfiling )
|
|
{
|
|
fProfiling = false;
|
|
|
|
//
|
|
// If there's a string value in the registry for this CLSID, prepend the command line with it.
|
|
//
|
|
{
|
|
WCHAR rgGUID[128];
|
|
|
|
if(::StringFromGUID2 ( *m_pclsid, rgGUID, MAXSTRLEN(rgGUID) ) > 0)
|
|
{
|
|
HKEY hKey;
|
|
|
|
if(::RegOpenKeyExW( HKEY_LOCAL_MACHINE, s_szRegKey, 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
|
|
{
|
|
WCHAR rgVALUE[MAX_PATH*3];
|
|
DWORD dwVALUE = sizeof(rgVALUE)-1;
|
|
DWORD dwType;
|
|
|
|
if(::RegQueryValueExW( hKey, rgGUID, NULL, &dwType, (BYTE*)rgVALUE, &dwVALUE ) == ERROR_SUCCESS && dwType == REG_SZ)
|
|
{
|
|
rgVALUE[dwVALUE/sizeof(WCHAR)] = 0;
|
|
|
|
if((dwVALUE = ::ExpandEnvironmentStringsW( rgVALUE, rgCommandLine, dwSize )))
|
|
{
|
|
rgCommandLine[dwVALUE-1] = ' '; // Padding space.
|
|
|
|
rgCommandLine += dwVALUE;
|
|
dwSize -= dwVALUE;
|
|
|
|
fProfiling = true;
|
|
}
|
|
}
|
|
|
|
::RegCloseKey( hKey );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Prepare the command line.
|
|
//
|
|
if(::ExpandEnvironmentStringsW( m_szExecutable, rgCommandLine, dwSize ))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
HRESULT CComRedirectorFactory::StartServer( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(FAILED(hr = GetServer( pUnkOuter, riid, ppvObj )))
|
|
{
|
|
WCHAR rgCommandLine[MAX_PATH*3];
|
|
bool fProfiling;
|
|
|
|
::EnterCriticalSection( &m_sec );
|
|
|
|
//
|
|
// Prepare the command line.
|
|
//
|
|
if(GetCommandLine( rgCommandLine, MAXSTRLEN(rgCommandLine), fProfiling ))
|
|
{
|
|
PROCESS_INFORMATION piProcessInformation;
|
|
STARTUPINFOW siStartupInfo;
|
|
BOOL fStarted;
|
|
|
|
::ZeroMemory( (PVOID)&piProcessInformation, sizeof( piProcessInformation ) );
|
|
::ZeroMemory( (PVOID)&siStartupInfo , sizeof( siStartupInfo ) ); siStartupInfo.cb = sizeof( siStartupInfo );
|
|
|
|
//
|
|
// Start the process, changing the WinStation to the console one in case of profiling.
|
|
//
|
|
{
|
|
if(fProfiling)
|
|
{
|
|
// siStartupInfo.lpDesktop = L"WinSta0\\Default";
|
|
}
|
|
|
|
fStarted = ::CreateProcessW( NULL ,
|
|
rgCommandLine ,
|
|
NULL ,
|
|
NULL ,
|
|
FALSE ,
|
|
NORMAL_PRIORITY_CLASS ,
|
|
NULL ,
|
|
NULL ,
|
|
&siStartupInfo ,
|
|
&piProcessInformation );
|
|
}
|
|
|
|
if(fStarted)
|
|
{
|
|
int iCount = LAUNCH_TIMEOUT;
|
|
|
|
if(fProfiling) iCount *= 10; // Give more time to start.
|
|
|
|
while(iCount-- > 0)
|
|
{
|
|
if(::WaitForSingleObject( piProcessInformation.hProcess, 100 ) != WAIT_TIMEOUT) break; // Process bailed out.
|
|
|
|
if(SUCCEEDED(hr = GetServer( pUnkOuter, riid, ppvObj ))) break;
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
::TerminateProcess( piProcessInformation.hProcess, 0 );
|
|
}
|
|
}
|
|
|
|
if(piProcessInformation.hProcess) ::CloseHandle( piProcessInformation.hProcess );
|
|
if(piProcessInformation.hThread ) ::CloseHandle( piProcessInformation.hThread );
|
|
}
|
|
|
|
::LeaveCriticalSection( &m_sec );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CComRedirectorFactory::Register()
|
|
{
|
|
::InitializeCriticalSection( &m_sec );
|
|
|
|
if(!m_pclsid) return S_OK;
|
|
|
|
return ::CoRegisterClassObject( *m_pclsid ,
|
|
(IClassFactory*)this ,
|
|
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ,
|
|
REGCLS_MULTIPLEUSE ,
|
|
&m_dwRegister );
|
|
}
|
|
|
|
void CComRedirectorFactory::Unregister()
|
|
{
|
|
if(m_dwRegister)
|
|
{
|
|
::CoRevokeClassObject( m_dwRegister );
|
|
|
|
m_dwRegister = 0;
|
|
}
|
|
|
|
::DeleteCriticalSection( &m_sec );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ServiceHandler::ServiceHandler( /*[in]*/ LPCWSTR szServiceName, /*[in]*/ CComRedirectorFactory* rgClasses )
|
|
{
|
|
m_szServiceName = szServiceName; // LPCWSTR m_szServiceName;
|
|
m_rgClasses = rgClasses; // CComRedirectorFactory* m_rgClasses;
|
|
//
|
|
m_fComInitialized = false; // bool m_fComInitialized;
|
|
//
|
|
m_hShutdownEvent = NULL; // HANDLE m_hShutdownEvent;
|
|
//
|
|
// SERVICE_STATUS_HANDLE m_hServiceStatus;
|
|
// SERVICE_STATUS m_status;
|
|
|
|
::ZeroMemory( &m_status, sizeof( m_status ) );
|
|
|
|
m_status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
|
|
m_status.dwCurrentState = SERVICE_STOPPED;
|
|
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
m_status.dwWin32ExitCode = 0;
|
|
m_status.dwServiceSpecificExitCode = 0;
|
|
m_status.dwCheckPoint = 0;
|
|
m_status.dwWaitHint = 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DLL Entry Point
|
|
|
|
extern "C"
|
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
|
{
|
|
if(dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
_Module.Init( NULL, hInstance, NULL );
|
|
|
|
DisableThreadLibraryCalls( hInstance );
|
|
|
|
s_Services[0] = new ServiceHandler_HelpSvc( L"HelpSvc" , s_HelpSvc );
|
|
s_Services[1] = new ServiceHandler ( L"UploadMgr", s_UploadMgr );
|
|
|
|
g_RDSHost.Register();
|
|
}
|
|
else if(dwReason == DLL_PROCESS_DETACH)
|
|
{
|
|
delete s_Services[0];
|
|
delete s_Services[1];
|
|
|
|
g_RDSHost.Unregister();
|
|
|
|
_Module.Term();
|
|
}
|
|
|
|
return TRUE; // ok
|
|
}
|
|
|
|
DWORD WINAPI _HandlerEx( DWORD dwControl , // requested control code
|
|
DWORD dwEventType , // event type
|
|
LPVOID lpEventData , // event data
|
|
LPVOID lpContext ) // user-defined context data
|
|
{
|
|
ServiceHandler* handler = static_cast<ServiceHandler*>(lpContext);
|
|
|
|
return handler->HandlerEx( dwControl , // requested control code
|
|
dwEventType , // event type
|
|
lpEventData ); // user-defined context data
|
|
}
|
|
|
|
void WINAPI ServiceMain( DWORD dwArgc, LPWSTR* lpszArgv )
|
|
{
|
|
#if 0
|
|
BOOL fWait = true;
|
|
|
|
while(fWait)
|
|
{
|
|
Sleep(1000);
|
|
}
|
|
#endif
|
|
|
|
LPWSTR szName = lpszArgv[0];
|
|
ServiceHandler** ph = s_Services;
|
|
int i;
|
|
|
|
for(i=0; i<ARRAYSIZE(s_Services); i++)
|
|
{
|
|
ServiceHandler* h = *ph++;
|
|
|
|
if(h && !_wcsicmp( h->m_szServiceName, szName ))
|
|
{
|
|
h->Run(); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD ServiceHandler::HandlerEx( DWORD dwControl , // requested control code
|
|
DWORD dwEventType , // event type
|
|
LPVOID lpEventData ) // event data
|
|
{
|
|
switch(dwControl)
|
|
{
|
|
case SERVICE_CONTROL_STOP:
|
|
SetServiceStatus( SERVICE_STOP_PENDING );
|
|
|
|
if(m_hShutdownEvent) ::SetEvent( m_hShutdownEvent );
|
|
break;
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
break;
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
break;
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
break;
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
break;
|
|
|
|
default:
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
HRESULT ServiceHandler::Initialize()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "ServiceHandler::Initialize" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
m_status.dwWin32ExitCode = S_OK;
|
|
m_status.dwCheckPoint = 0;
|
|
m_status.dwWaitHint = 0;
|
|
|
|
try
|
|
{
|
|
CComRedirectorFactory* classes;
|
|
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (m_hServiceStatus = ::RegisterServiceCtrlHandlerExW( m_szServiceName, _HandlerEx, this )));
|
|
|
|
SetServiceStatus( SERVICE_START_PENDING );
|
|
|
|
////////////////////
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoInitializeEx( NULL, COINIT_MULTITHREADED ));
|
|
m_fComInitialized = true;
|
|
|
|
for(classes=m_rgClasses; SUCCEEDED(hr) && classes->m_pclsid; classes++)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, classes->Register());
|
|
}
|
|
|
|
////////////////////
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (m_hShutdownEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL )));
|
|
|
|
SetServiceStatus( SERVICE_RUNNING );
|
|
}
|
|
catch(...)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
void ServiceHandler::WaitUntilStopped()
|
|
{
|
|
if(m_hShutdownEvent) ::WaitForSingleObject( m_hShutdownEvent, INFINITE );
|
|
}
|
|
|
|
void ServiceHandler::Cleanup()
|
|
{
|
|
if(m_hShutdownEvent)
|
|
{
|
|
::CloseHandle( m_hShutdownEvent );
|
|
|
|
m_hShutdownEvent = NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
if(m_fComInitialized)
|
|
{
|
|
CComRedirectorFactory* classes;
|
|
|
|
for(classes=m_rgClasses; classes->m_pclsid; classes++)
|
|
{
|
|
classes->Unregister();
|
|
}
|
|
|
|
::CoUninitialize();
|
|
m_fComInitialized = false;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
if(m_hServiceStatus)
|
|
{
|
|
SetServiceStatus( SERVICE_STOPPED );
|
|
m_hServiceStatus = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void ServiceHandler::Run()
|
|
{
|
|
//
|
|
// When the Run function returns, the service has been stopped.
|
|
//
|
|
|
|
if(SUCCEEDED(Initialize()))
|
|
{
|
|
WaitUntilStopped();
|
|
}
|
|
|
|
Cleanup();
|
|
}
|
|
|
|
void ServiceHandler::SetServiceStatus( DWORD dwState )
|
|
{
|
|
m_status.dwCurrentState = dwState;
|
|
|
|
::SetServiceStatus( m_hServiceStatus, &m_status );
|
|
}
|