//**************************************************************************** // File: CCONF.CPP // Content: // // // Copyright (c) Microsoft Corporation 1997 // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. //**************************************************************************** #include #include "srvccall.h" #include "cstring.hpp" #define ZERO_DELAY "0" const int SERVICE_IN_CALL = 1001; const int SERVICE_NOT_IN_CALL = 1000; // Global Variables INmManager * g_pMgr = NULL; // The Conference Manager CMgrNotify * g_pMgrNotify = NULL; // Notifications for the Manager INmConference * g_pConference = NULL; // The Current Conference CConfNotify * g_pConferenceNotify =NULL; // Notifications for the Conference IAppSharing * g_pAS = NULL; // Interface to AppSharing int g_cPersonsInConf = 0; int g_cPersonsInShare = 0; extern BOOL g_fInShutdown; CHAR szConfName[64]; static BOOL RunScrSaver(void); /* I N I T C O N F M G R */ /*------------------------------------------------------------------------- %%Function: InitConfMgr -------------------------------------------------------------------------*/ HRESULT InitConfMgr(void) { HRESULT hr; TRACE_OUT(("InitConfMgr")); ASSERT(!g_pMgr); hr = CreateNmManager(&g_pMgr); if (SUCCEEDED(hr)) { // Connect to the conference manager object g_pMgrNotify = new CMgrNotify(); if (NULL != g_pMgrNotify) { hr = g_pMgrNotify->Connect(g_pMgr); // // Now initialize, with the user name, credentials, and // port. // if (SUCCEEDED(hr)) { HCERTSTORE hStore; PCCERT_CONTEXT pCertContext = NULL; DWORD dwResult = -1; TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1]; DWORD dwComputerNameLength = sizeof(szComputerName) / sizeof(szComputerName[0]); // Open the "MY" local machine certificate store. This one will be // used when we're running as a service hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY" ); if ( NULL != hStore ) { #ifdef DUMPCERTS DumpCertStore(this, "Local Machine Store MY", hStore); #endif // DUMPCERTS // Check the local machine store for a certificate - any! pCertContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); CertCloseStore( hStore, 0); } if ( NULL == pCertContext ) { // Open the RDS local machine certificate store. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, WSZNMSTORE ); if ( NULL != hStore ) { #ifdef DUMPCERTS DumpCertStore(this, "Local Machine Store _RDSTR", hStore); #endif // DUMPCERTS // Check the local machine store for a certificate - any! pCertContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); CertCloseStore( hStore, 0); } } if ( NULL == pCertContext ) { ERROR_OUT(("No service context cert found!")); } if ( !GetComputerName( szComputerName, &dwComputerNameLength)) { lstrcpy(szComputerName,TEXT("?")); ERROR_OUT(("GetComputerName failed")); } // // Do the intialization // hr = g_pMgr->Initialize(BSTRING(szComputerName), (DWORD_PTR)pCertContext, DEFAULT_LISTEN_PORT, NMMANAGER_SERVICE | NMMANAGER_SERVER); if (pCertContext) { CertFreeCertificateContext ( pCertContext ); } if (FAILED(hr)) { ERROR_OUT(("g_pMgr->Initialize failed")); } } else ERROR_OUT(("g_pMgrNotify->Connect failed")); } else ERROR_OUT(("new CMgrNotify failed")); } if (!g_pMgr) { ERROR_OUT(("Failed to init conference manager")); return hr; } // // Init app sharing // hr = ::CreateASObject(g_pMgrNotify, AS_SERVICE | AS_UNATTENDED, &g_pAS); if (FAILED(hr)) { ERROR_OUT(("Failed to start AppSharing")); return(hr); } // // Make sure that sharing is enabled // if ( !g_pAS->IsSharingAvailable() ) { WARNING_OUT(("MNMSRVC: sharing not enabled")); return E_FAIL; } // Create conference ASSERT(g_pConference == NULL); // // Only allow remotes to send files, they can't initiate anything else // themselves. LoadString(GetModuleHandle(NULL), IDS_MNMSRVC_TITLE, szConfName, CCHMAX(szConfName)); BSTRING bstrConfName(szConfName); hr = g_pMgr->CreateConference(&g_pConference, bstrConfName, NULL, TRUE); if (FAILED(hr)) { ERROR_OUT(("Conference could not be created")); return hr; } hr = g_pConference->Host(); if (FAILED(hr)) { ERROR_OUT(("Could not host conference")); return hr; } return hr; } /* F R E E C O N F M G R */ /*------------------------------------------------------------------------- %%Function: FreeConfMgr -------------------------------------------------------------------------*/ VOID FreeConfMgr(void) { DebugEntry(FreeConfMgr); // Release conference manager notify if (NULL != g_pMgrNotify) { g_pMgrNotify->Disconnect(); UINT ref = g_pMgrNotify->Release(); TRACE_OUT(("g_pMgrNotify after Release: refcount: %d", ref)); g_pMgrNotify = NULL; } // Release conference manager if (NULL != g_pMgr) { UINT ref; ref = g_pMgr->Release(); TRACE_OUT(("g_pMgr after Release: refcount: %d", ref)); g_pMgr = NULL; } DebugExitVOID(FreeConfMgr); } /* F R E E C O N F E R E N C E */ /*------------------------------------------------------------------------- %%Function: FreeConference -------------------------------------------------------------------------*/ VOID FreeConference(void) { DebugEntry(FreeConference); if (g_pConference) { g_pConference->Leave(); } if (NULL != g_pConferenceNotify) { g_pConferenceNotify->Disconnect(); g_pConferenceNotify->Release(); g_pConferenceNotify = NULL; } if (NULL != g_pConference) { UINT ref = g_pConference->Release(); ASSERT(1 == ref); // The confmgr holds last reference g_pConference = NULL; } else { WARNING_OUT(("FreeConference: no conference???")); } DebugExitVOID(FreeConference); } ////////////////////////////////////////////////////////////////////////// // C C N F M G R N O T I F Y CMgrNotify::CMgrNotify() : RefCount(), CNotify() { TRACE_OUT(("CMgrNotify created")); } CMgrNotify::~CMgrNotify() { TRACE_OUT(("CMgrNotify destroyed")); } /////////////////////////// // CMgrNotify:IUnknown ULONG STDMETHODCALLTYPE CMgrNotify::AddRef(void) { return RefCount::AddRef(); } ULONG STDMETHODCALLTYPE CMgrNotify::Release(void) { return RefCount::Release(); } HRESULT STDMETHODCALLTYPE CMgrNotify::QueryInterface(REFIID riid, PVOID *ppvObject) { HRESULT hr = S_OK; TRACE_OUT(("CMgrNotify QI'd")); if (riid == IID_IUnknown || riid == IID_INmManagerNotify) { *ppvObject = (INmManagerNotify *)this; } else { hr = E_NOINTERFACE; *ppvObject = NULL; } if (S_OK == hr) { AddRef(); } return hr; } //////////////////////////// // CMgrNotify:ICNotify HRESULT STDMETHODCALLTYPE CMgrNotify::Connect(IUnknown *pUnk) { TRACE_OUT(("CMgrNotify::Connect")); return CNotify::Connect(pUnk, IID_INmManagerNotify, (INmManagerNotify *)this); } HRESULT STDMETHODCALLTYPE CMgrNotify::Disconnect(void) { TRACE_OUT(("CMgrNotify::Disconnect")); return CNotify::Disconnect(); } ////////////////////////////////// // CMgrNotify:INmManagerNotify HRESULT STDMETHODCALLTYPE CMgrNotify::NmUI(CONFN confn) { TRACE_OUT(("CMgrNotify::NmUI")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::CallCreated(INmCall *pNmCall) { new CSrvcCall(pNmCall); TRACE_OUT(("CMgrNotify::CallCreated")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::ConferenceCreated(INmConference *pConference) { g_cPersonsInConf = 0; g_cPersonsInShare = 0; if (NULL == g_pConference) { TRACE_OUT(("CMgrNotify::ConferenceCreated")); HookConference(pConference); } else { ERROR_OUT(("Second conference created???")); } return S_OK; } // CMgrNotify::IAppSharingNotify HRESULT STDMETHODCALLTYPE CMgrNotify::OnReadyToShare(BOOL fReady) { TRACE_OUT(("CMgrNotify::OnReadyToShare")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnShareStarted() { TRACE_OUT(("CMgrNotify::OnShareStarted")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnSharingStarted() { TRACE_OUT(("CMgrNotify::OnSharingStarted")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnShareEnded() { TRACE_OUT(("CMgrNotify::OnShareEnded")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnPersonJoined(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnPersonJoined")); ASSERT(g_pAS); ASSERT(g_cPersonsInShare >= 0); g_cPersonsInShare++; // // Once we are no longer alone in the share, invite the remote party to // take control of us. // if ( 2 == g_cPersonsInShare && g_pAS) { HRESULT hr; TRACE_OUT(("OnPersonJoined: giving control to 2nd dude %d", gccID)); // // Give control to the remote party // hr = g_pAS->GiveControl(gccID); if ( S_OK != hr ) { ERROR_OUT(("OnPersonJoined: GiveControl to %d failed: %x", gccID, hr)); } } return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnPersonLeft(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnPersonLeft")); ASSERT(g_pAS); g_cPersonsInShare--; ASSERT(g_cPersonsInShare >= 0); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnStartInControl(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnStartInControl")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnStopInControl(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnStopInControl")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnControllable(BOOL fControllable) { TRACE_OUT(("CMgrNotify::OnControllable")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnStartControlled(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnStartControlled")); return S_OK; } HRESULT STDMETHODCALLTYPE CMgrNotify::OnStopControlled(IAS_GCC_ID gccID) { TRACE_OUT(("CMgrNotify::OnStopControlled")); ::RunScrSaver(); return S_OK; } /* H O O K C O N F E R E N C E */ /*------------------------------------------------------------------------- %%Function: HookConference -------------------------------------------------------------------------*/ HRESULT HookConference(INmConference * pConference) { HRESULT hr; DebugEntry(HookConference); TRACE_OUT(("HookConference")); ASSERT(NULL != pConference); ASSERT(NULL == g_pConference); TRACE_OUT(("Set g_pConference in HookConference")); g_pConference = pConference; pConference->AddRef(); // Connect to the conference object ASSERT(NULL == g_pConferenceNotify); g_pConferenceNotify = new CConfNotify(); if (NULL == g_pConferenceNotify) { ERROR_OUT(("failed to new CConfNotify")); hr = E_OUTOFMEMORY; } else { hr = g_pConferenceNotify->Connect(pConference); if (FAILED(hr)) { ERROR_OUT(("Failed to connect to g_pConferenceNotify")); g_pConferenceNotify->Release(); g_pConferenceNotify = NULL; } } DebugExitHRESULT(HookConference,hr); return hr; } ////////////////////////////////////////////////////////////////////////// // C C N F N O T I F Y CConfNotify::CConfNotify() : RefCount(), CNotify() { TRACE_OUT(("CConfNotify created")); } CConfNotify::~CConfNotify() { TRACE_OUT(("CConfNotify destroyed")); } /////////////////////////// // CConfNotify:IUknown ULONG STDMETHODCALLTYPE CConfNotify::AddRef(void) { TRACE_OUT(("CConfNotify::AddRef")); return RefCount::AddRef(); } ULONG STDMETHODCALLTYPE CConfNotify::Release(void) { TRACE_OUT(("CConfNotify::Release")); return RefCount::Release(); } HRESULT STDMETHODCALLTYPE CConfNotify::QueryInterface(REFIID riid, PVOID *ppvObject) { HRESULT hr = S_OK; TRACE_OUT(("CConfNotify::QueryInterface")); if (riid == IID_IUnknown) { TRACE_OUT(("CConfNotify::QueryInterface IID_IUnknown")); *ppvObject = (IUnknown *)this; } else if (riid == IID_INmConferenceNotify) { TRACE_OUT(("CConfNotify::QueryInterface IID_INmConferenceNotify")); *ppvObject = (INmConferenceNotify *)this; } else { WARNING_OUT(("CConfNotify::QueryInterface bogus")); hr = E_NOINTERFACE; *ppvObject = NULL; } if (S_OK == hr) { AddRef(); } return hr; } //////////////////////////// // CConfNotify:ICNotify HRESULT STDMETHODCALLTYPE CConfNotify::Connect(IUnknown *pUnk) { TRACE_OUT(("CConfNotify::Connect")); return CNotify::Connect(pUnk,IID_INmConferenceNotify,(IUnknown *)this); } HRESULT STDMETHODCALLTYPE CConfNotify::Disconnect(void) { TRACE_OUT(("CConfNotify::Disconnect")); // // Release for Addref in HookConference before CConfNotify::Connect // if ( g_pConference ) g_pConference->Release(); return CNotify::Disconnect(); } ////////////////////////////////// // CConfNotify:IConfNotify HRESULT STDMETHODCALLTYPE CConfNotify::NmUI(CONFN uNotify) { TRACE_OUT(("CConfNotify::NmUI")); TRACE_OUT(("NmUI called.")); return S_OK; } HRESULT STDMETHODCALLTYPE CConfNotify::StateChanged(NM_CONFERENCE_STATE uState) { TRACE_OUT(("CConfNotify::StateChanged")); if (NULL == g_pConference) return S_OK; // weird switch (uState) { case NM_CONFERENCE_ACTIVE: if (IS_NT) { g_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; SetServiceStatus(g_sshStatusHandle,&g_ssStatus); } break; case NM_CONFERENCE_INITIALIZING: break; // can't do anything just yet case NM_CONFERENCE_WAITING: if (IS_NT) { g_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; SetServiceStatus(g_sshStatusHandle,&g_ssStatus); } break; case NM_CONFERENCE_IDLE: break; } return S_OK; } HRESULT STDMETHODCALLTYPE CConfNotify::MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pMember) { switch (uNotify) { case NM_MEMBER_ADDED: { TRACE_OUT(("CConfNotify::MemberChanged() Member added")); ASSERT( g_cPersonsInConf >= 0 ); g_cPersonsInConf++; // // Once we are no longer alone in the conference, share the desktop // and allow control: // if ( 2 == g_cPersonsInConf && g_pAS ) { HRESULT hr; TRACE_OUT(("%d parties in conf, Sharing the desktop", g_cPersonsInConf)); // // Share out the desktop // hr = g_pAS->ShareDesktop(); if ( S_OK != hr ) { ERROR_OUT(("OnPersonJoined: sharing desktop failed: %x",hr)); } // // Allow control // hr = g_pAS->AllowControl ( TRUE ); if ( S_OK != hr ) { ERROR_OUT(("OnPersonJoined: allowing control failed: %x",hr)); } } break; } case NM_MEMBER_REMOVED: { TRACE_OUT(("CConfNotify::MemberChanged() Member removed")); g_cPersonsInConf--; ASSERT( g_cPersonsInConf >= 0 ); if ( 1 == g_cPersonsInConf && g_pAS ) { HRESULT hr; TRACE_OUT(("%d parties in conf, Unsharing the desktop", g_cPersonsInConf)); // // Disallow control // hr = g_pAS->AllowControl ( FALSE ); if ( S_OK != hr ) { ERROR_OUT(("Disallowing control failed: %x",hr)); } // // Unshare the desktop // hr = g_pAS->UnshareDesktop(); if ( S_OK != hr ) { ERROR_OUT(("Unsharing desktop failed: %x",hr)); } } break; } case NM_MEMBER_UPDATED: { TRACE_OUT(("CConfNotify::MemberChanged() Member updated")); break; } default: break; } return S_OK; } BOOL ServiceCtrlHandler(DWORD dwCtrlType) { HRESULT hr = S_OK; TRACE_OUT(("ServiceCtrlHandler received %d",dwCtrlType)); switch (dwCtrlType) { case CTRL_SHUTDOWN_EVENT: if (g_pConference != NULL) { TRACE_OUT(("Leaving conference in CTRL_SHUTDOWN_EVENT")); hr = g_pConference->Leave(); if (FAILED(hr)) { WARNING_OUT(("Service Ctrl Handler failed to leave")); } } else { WARNING_OUT(("g_pConference NULL in CTRL_SHUTDOWN_EVENT")); } break; default: break; } return FALSE; } static BOOL RunScrSaver(void) { BOOL fIsScrSaverActive = FALSE; if (g_fInShutdown) { return FALSE; } if (!SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fIsScrSaverActive, 0)) { ERROR_OUT(("RunScrSaver: SystemParametersInfo failed")); return FALSE; } if (fIsScrSaverActive) { RegEntry reWinlogon(IS_NT ? WINNT_WINLOGON_KEY : WIN95_WINLOGON_KEY, HKEY_LOCAL_MACHINE); CSTRING strGracePeriod = reWinlogon.GetString(REGVAL_SCREENSAVER_GRACEPERIOD); reWinlogon.SetValue(REGVAL_SCREENSAVER_GRACEPERIOD, ZERO_DELAY); reWinlogon.FlushKey(); DefWindowProc(GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0); if (lstrlen(strGracePeriod)) { int cSeconds = RtStrToInt(strGracePeriod); if (cSeconds > 0 && cSeconds <= 20) { Sleep(1000*cSeconds); reWinlogon.SetValue(REGVAL_SCREENSAVER_GRACEPERIOD, strGracePeriod); reWinlogon.FlushKey(); return TRUE; } } Sleep(5000); reWinlogon.DeleteValue(REGVAL_SCREENSAVER_GRACEPERIOD); reWinlogon.FlushKey(); return TRUE; } else { return FALSE; } }