/****************************************************************************** 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(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; im_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 ); }