#include "precomp.h" #include "version.h" #include "nacguids.h" #include "RegEntry.h" #include "ConfReg.h" #include "NmSysInfo.h" #include "capflags.h" #define SZ_YES _T("1") #define SZ_NO _T("0") // // Hack alert: // // The follwoing system property constant is used to inform // the Netmeeting Manager object that the caller is Whistler // RTC client so that it can take some actions for performance // purpose, i.e. don't poll A/V capabilities and don't do // ILS logon. // // This value MUST NOT collide with the NM_SYSPROP_Consts defined // in imsconf3.idl // #define NM_SYSPROP_CALLERISRTC 300 /////////////////////////////////////////////// // Init and construction methods /////////////////////////////////////////////// HRESULT CNmSysInfoObj::FinalConstruct() { DBGENTRY(CNmSysInfoObj::FinalConstruct); HRESULT hr = S_OK; m_dwID = 0; DBGEXIT_HR(CNmSysInfoObj::FinalConstruct,hr); return hr; } void CNmSysInfoObj::FinalRelease() { DBGENTRY(CNmSysInfoObj::FinalRelease); m_spConfHook = NULL; DBGEXIT(CNmSysInfoObj::FinalRelease); } /////////////////////////////////////////////// // INmSysInfo2 methods /////////////////////////////////////////////// STDMETHODIMP CNmSysInfoObj::IsInstalled(void) { DBGENTRY(CNmSysInfoObj::IsInstalled); HRESULT hr = S_OK; TCHAR sz[MAX_PATH]; // Fail if not a valid installation directory if (GetInstallDirectory(sz) && FDirExists(sz)) { // Validate ULS entries RegEntry reUls(ISAPI_KEY "\\" REGKEY_USERDETAILS, HKEY_CURRENT_USER); LPTSTR psz; hr = NM_E_NOT_INITIALIZED; psz = reUls.GetString(REGVAL_ULS_EMAIL_NAME); if (lstrlen(psz)) { psz = reUls.GetString(REGVAL_ULS_RES_NAME); { RegEntry reConf(CONFERENCING_KEY, HKEY_CURRENT_USER); // check to see if the wizard has been run in UI mode DWORD dwVersion = reConf.GetNumber(REGVAL_WIZARD_VERSION_UI, 0); BOOL fForceWizard = (VER_PRODUCTVERSION_DW != dwVersion); if (fForceWizard) { // the wizard has not been run in UI mode, check to see if its been run in NOUI mode dwVersion = reConf.GetNumber(REGVAL_WIZARD_VERSION_NOUI, 0); fForceWizard = (VER_PRODUCTVERSION_DW != dwVersion); } if (fForceWizard) { hr = S_FALSE; // Wizard has never been run } else { hr = S_OK; } } } } else { hr = E_FAIL; } DBGEXIT_HR(CNmSysInfoObj::IsInstalled,hr); return hr; } STDMETHODIMP CNmSysInfoObj::GetProperty(NM_SYSPROP uProp, BSTR *pbstrProp) { DBGENTRY(CNmSysInfoObj::GetProperty); HRESULT hr = S_OK; if(pbstrProp) { switch (uProp) { case NM_SYSPROP_BUILD_VER: *pbstrProp = T2BSTR(VER_PRODUCTVERSION_STR); break; case NM_SYSPROP_LOGGED_ON: _EnsureConfHook(); if(m_spConfHook) { *pbstrProp = T2BSTR((S_OK == m_spConfHook->LoggedIn()) ? SZ_YES : SZ_NO); } break; case NM_SYSPROP_IS_RUNNING: _EnsureConfHook(); if(m_spConfHook) { *pbstrProp = T2BSTR((S_OK == m_spConfHook->IsRunning()) ? SZ_YES : SZ_NO); } break; case NM_SYSPROP_IN_CONFERENCE: _EnsureConfHook(); if(m_spConfHook) { *pbstrProp = T2BSTR((S_OK == m_spConfHook->InConference()) ? SZ_YES : SZ_NO); } break; case NM_SYSPROP_USER_CITY: case NM_SYSPROP_USER_COUNTRY: case NM_SYSPROP_USER_CATEGORY: *pbstrProp = T2BSTR(("")); break; case NM_SYSPROP_ICA_ENABLE: *pbstrProp = T2BSTR(("0")); break; default: { HKEY hkey; LPTSTR pszSubKey; LPTSTR pszValue; bool fString; TCHAR sz[MAX_PATH]; if(GetKeyDataForProp(uProp, &hkey, &pszSubKey, &pszValue, &fString)) { RegEntry re(pszSubKey, hkey); if (fString) { *pbstrProp = T2BSTR(re.GetString(pszValue)); } else { DWORD dw = re.GetNumber(pszValue, 0); wsprintf(sz, "%d", dw); *pbstrProp = T2BSTR(sz); break; } } else { pbstrProp = NULL; hr = E_INVALIDARG; } } } } else { hr = E_POINTER; } DBGEXIT_HR(CNmSysInfoObj::GetProperty,hr); return hr; } STDMETHODIMP CNmSysInfoObj::SetProperty(NM_SYSPROP uProp, BSTR bstrName) { DBGENTRY(CNmSysInfoObj::SetProperty); USES_CONVERSION; HRESULT hr = S_OK; LPTSTR psz; if( bstrName ) { // Special processing for new NM 2.x functions switch (uProp) { case NM_SYSPROP_LOGGED_ON: { _EnsureConfHook(); if(m_spConfHook) { if(0 == lstrcmp(SZ_YES,OLE2T(bstrName))) { m_spConfHook->LDAPLogon(TRUE); } else { m_spConfHook->LDAPLogon(FALSE); } } break; } case NM_SYSPROP_DISABLE_H323: { _EnsureConfHook(); if(m_spConfHook) { hr = m_spConfHook->DisableH323(0 == lstrcmp(SZ_YES,OLE2T(bstrName))); } } break; case NM_SYSPROP_DISABLE_INITIAL_ILS_LOGON: { _EnsureConfHook(); if(m_spConfHook) { hr = m_spConfHook->DisableInitialILSLogon(0 == lstrcmp(SZ_YES,OLE2T(bstrName))); } } break; case NM_SYSPROP_CALLERISRTC: { _EnsureConfHook(); if(m_spConfHook) { hr = m_spConfHook->SetCallerIsRTC(0 == lstrcmp(SZ_YES,OLE2T(bstrName))); } } break; case NM_SYSPROP_ICA_ENABLE: case NM_SYSPROP_USER_CITY: case NM_SYSPROP_USER_COUNTRY: case NM_SYSPROP_USER_CATEGORY: case NM_SYSPROP_USER_LOCATION: // We don't support these properties anymore hr = S_OK; break; case NM_SYSPROP_WB_HELPFILE: case NM_SYSPROP_CB_HELPFILE: { // We don't use these anymare hr = S_OK; break; } default: { LPTSTR pszSubKey; LPTSTR pszValue; LPTSTR pszData; bool fString; HKEY hkey; if(GetKeyDataForProp(uProp, &hkey, &pszSubKey, &pszValue, &fString)) { pszData = NULL; pszData = OLE2T(bstrName); RegEntry re(pszSubKey, hkey); if (fString) { if (0 != re.SetValue(pszValue, pszData)) { hr = E_UNEXPECTED; } } else { DWORD dw = DecimalStringToUINT(pszData); if (0 != re.SetValue(pszValue, dw)) { hr = E_UNEXPECTED; } } } else { hr = E_INVALIDARG; } break; } } } else { hr = E_INVALIDARG; } DBGEXIT_HR(CNmSysInfoObj::SetProperty,hr); return hr; } STDMETHODIMP CNmSysInfoObj::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb) { HRESULT hr = E_FAIL; _EnsureConfHook(); if(m_spConfHook) { return m_spConfHook->GetUserData(rguid, ppb, pcb); } return hr; } STDMETHODIMP CNmSysInfoObj::SetUserData(REFGUID rguid, BYTE *pb, ULONG cb) { HRESULT hr = E_FAIL; _EnsureConfHook(); if(m_spConfHook) { return m_spConfHook->SetUserData(rguid, pb, cb); } return hr; } STDMETHODIMP CNmSysInfoObj::GetNmApp(REFGUID rguid,BSTR *pbstrApplication, BSTR *pbstrCommandLine, BSTR *pbstrDirectory) { HRESULT hr = S_OK; DBGENTRY(CNmSysInfoObj::GetNmApp); bool bErr = FALSE; TCHAR szKey[MAX_PATH]; // Validate parameters if ((!pbstrApplication) || (!IsBadWritePtr(pbstrApplication, sizeof(BSTR *))) && (!pbstrCommandLine) || (!IsBadWritePtr(pbstrCommandLine, sizeof(BSTR *))) && (!pbstrDirectory) || (!IsBadWritePtr(pbstrDirectory, sizeof(BSTR *))) ) { _GetSzKeyForGuid(szKey, rguid); RegEntry re(szKey, HKEY_LOCAL_MACHINE); if(pbstrApplication) { *pbstrApplication = T2BSTR(re.GetString(REGVAL_GUID_APPNAME)); if(NULL == *pbstrApplication) { bErr = true; } } if(pbstrCommandLine) { *pbstrCommandLine = T2BSTR(re.GetString(REGVAL_GUID_CMDLINE)); if(NULL == *pbstrCommandLine) { bErr = true; } } if(pbstrDirectory) { *pbstrDirectory = T2BSTR(re.GetString(REGVAL_GUID_CURRDIR)); if(NULL == *pbstrDirectory) { bErr = true; } } if(bErr) { if (NULL != pbstrApplication) { SysFreeString(*pbstrApplication); *pbstrApplication = NULL; } if (NULL != pbstrCommandLine) { SysFreeString(*pbstrCommandLine); *pbstrCommandLine = NULL; } if (NULL != pbstrDirectory) { SysFreeString(*pbstrDirectory); *pbstrDirectory = NULL; } hr = E_OUTOFMEMORY; } } else { hr = E_POINTER; } DBGEXIT_HR(CNmSysInfoObj::GetNmApp,hr); return hr; } STDMETHODIMP CNmSysInfoObj::SetNmApp(REFGUID rguid,BSTR bstrApplication, BSTR bstrCommandLine, BSTR bstrDirectory) { HRESULT hr = S_OK; DBGENTRY(CNmSysInfoObj::SetNmApp); USES_CONVERSION; bool bDeleteKey = TRUE; LPTSTR psz = NULL; TCHAR szKey[MAX_PATH]; _GetSzKeyForGuid(szKey, rguid); RegEntry re(szKey, HKEY_LOCAL_MACHINE); if(!bstrApplication) { re.DeleteValue(REGVAL_GUID_APPNAME); } else { psz = OLE2T(bstrApplication); if(psz) { re.SetValue(REGVAL_GUID_APPNAME, psz); } else { hr = E_OUTOFMEMORY; } bDeleteKey = false; } if (NULL == bstrCommandLine) { re.DeleteValue(REGVAL_GUID_CMDLINE); } else { psz = OLE2T(bstrCommandLine); if(psz) { re.SetValue(REGVAL_GUID_CMDLINE, psz); } else { hr = E_OUTOFMEMORY; } bDeleteKey = false; } if (NULL == bstrDirectory) { re.DeleteValue(REGVAL_GUID_CURRDIR); } else { psz = OLE2T(bstrDirectory); if(psz) { re.SetValue(REGVAL_GUID_CURRDIR, psz); } else { hr = E_OUTOFMEMORY; } bDeleteKey = false; } if (bDeleteKey) { // All keys were NULL - delete the entire key RegEntry reApps(GUID_KEY, HKEY_LOCAL_MACHINE); GuidToSz((GUID *) &rguid, szKey); reApps.DeleteValue(szKey); } DBGEXIT_HR(CNmSysInfoObj::SetNmApp,hr); return hr; } STDMETHODIMP CNmSysInfoObj::GetNmchCaps(ULONG *pchCaps) { DBGENTRY(CNmSysInfoObj::GetNmchCaps); HRESULT hr = S_OK; _EnsureConfHook(); if(m_spConfHook) { if(pchCaps && !IsBadWritePtr(pchCaps, sizeof(ULONG *))) { ULONG nmch = NMCH_DATA; // Always capable of data RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER); if ((DEFAULT_POL_NO_FILETRANSFER_SEND == re.GetNumber(REGVAL_POL_NO_FILETRANSFER_SEND, DEFAULT_POL_NO_FILETRANSFER_SEND)) && (DEFAULT_POL_NO_FILETRANSFER_RECEIVE == re.GetNumber(REGVAL_POL_NO_FILETRANSFER_RECEIVE, DEFAULT_POL_NO_FILETRANSFER_RECEIVE)) ) { nmch |= NMCH_FT; } if (DEFAULT_POL_NO_APP_SHARING == re.GetNumber(REGVAL_POL_NO_APP_SHARING, DEFAULT_POL_NO_APP_SHARING)) { nmch |= NMCH_SHARE; } if (DEFAULT_POL_NO_AUDIO == re.GetNumber(REGVAL_POL_NO_AUDIO, DEFAULT_POL_NO_AUDIO)) { if(S_OK == m_spConfHook->IsNetMeetingRunning()) { DWORD dwLocalCaps; if(SUCCEEDED(m_spConfHook->GetLocalCaps(&dwLocalCaps)) && (dwLocalCaps & CAPFLAG_SEND_AUDIO)) { nmch |= NMCH_AUDIO; } } } if ((DEFAULT_POL_NO_VIDEO_SEND == re.GetNumber(REGVAL_POL_NO_VIDEO_SEND, DEFAULT_POL_NO_VIDEO_SEND)) && (DEFAULT_POL_NO_VIDEO_RECEIVE == re.GetNumber(REGVAL_POL_NO_VIDEO_RECEIVE, DEFAULT_POL_NO_VIDEO_RECEIVE)) ) { if(S_OK == m_spConfHook->IsNetMeetingRunning()) { DWORD dwLocalCaps; if(SUCCEEDED(m_spConfHook->GetLocalCaps(&dwLocalCaps)) && (dwLocalCaps & CAPFLAG_SEND_VIDEO)) { nmch |= NMCH_VIDEO; } } } *pchCaps = nmch; } else { hr = E_POINTER; } if(SUCCEEDED(hr)) { hr = m_spConfHook->IsNetMeetingRunning(); } } else { ERROR_OUT(("The confhook should be valid")); hr = E_UNEXPECTED; } DBGEXIT_HR(CNmSysInfoObj::GetNmchCaps,hr); return hr; } STDMETHODIMP CNmSysInfoObj::GetLaunchInfo(INmConference **ppConference, INmMember **ppMember) { DBGENTRY(CNmSysInfoObj::GetLaunchInfo); HRESULT hr = S_OK; if(ppMember) { *ppMember = NULL; } if(ppConference) { *ppConference = NULL; } _EnsureConfHook(); if(m_spConfHook) { // If NetMeeting is not initialized, return NM_E_NOT_INITIALIZED hr = m_spConfHook->IsNetMeetingRunning(); if(S_OK != hr) goto end; // If there is no default conference, return S_FALSE CComPtr spConf; hr = m_spConfHook->GetActiveConference(&spConf); if(S_OK != hr) goto end; // If the confID environment variable is not there, return S_FALSE TCHAR sz[MAX_PATH]; if (0 == GetEnvironmentVariable(ENV_CONFID, sz, CCHMAX(sz))) { hr = S_FALSE; goto end; } // If the conference ID from the environment variable is not there, return S_FALSE DWORD dw = DecimalStringToUINT(sz); DWORD dwGCCConfID; if(SUCCEEDED(hr = spConf->GetID(&dwGCCConfID))) { if(dw != dwGCCConfID) { // Conferenec does not exist anymore hr = S_FALSE; goto end; } // If the nodeID environment variable is note there, return S_FALSE if (0 == GetEnvironmentVariable(ENV_NODEID, sz, CCHMAX(sz))) { hr = S_FALSE; goto end; } // If ppMember is not NULL, fill it with a new SDKMember object from the nodeID if(ppMember) { CComPtr spConfObj = com_cast(spConf); if(spConfObj) { hr = spConfObj->GetMemberFromNodeID(DecimalStringToUINT(sz), ppMember); } else { hr = E_UNEXPECTED; goto end; } } // If ppConferenec is not NULL, fill it with a new SDKMember object if(ppConference) { *ppConference = spConf; (*ppConference)->AddRef(); } } } else { hr = E_UNEXPECTED; } end: DBGEXIT_HR(CNmSysInfoObj::GetLaunchInfo,hr); return hr; } /////////////////////////////////////////////// // Helper Fns /////////////////////////////////////////////// /*static*/ bool CNmSysInfoObj::GetKeyDataForProp(NM_SYSPROP uProp, HKEY * phkey, LPTSTR * ppszSubKey, LPTSTR * ppszValue, bool *pfString) { DBGENTRY(CNmSysInfoObj::GetKeyDataForProp); // Default to ULS registry key *phkey = HKEY_CURRENT_USER; *ppszSubKey = ISAPI_KEY "\\" REGKEY_USERDETAILS; *pfString = true; bool bRet = true; switch (uProp) { case NM_SYSPROP_EMAIL_NAME: *ppszValue = REGVAL_ULS_EMAIL_NAME; break; case NM_SYSPROP_SERVER_NAME: *ppszValue = REGVAL_SERVERNAME; break; case NM_SYSPROP_RESOLVE_NAME: *ppszValue = REGVAL_ULS_RES_NAME; break; case NM_SYSPROP_FIRST_NAME: *ppszValue = REGVAL_ULS_FIRST_NAME; break; case NM_SYSPROP_LAST_NAME: *ppszValue = REGVAL_ULS_LAST_NAME; break; case NM_SYSPROP_USER_NAME: *ppszValue = REGVAL_ULS_NAME; break; case NM_SYSPROP_USER_COMMENTS: *ppszValue = REGVAL_ULS_COMMENTS_NAME; break; case NM_SYSPROP_USER_CITY: *ppszValue = REGVAL_ULS_LOCATION_NAME; break; case NM_SYSPROP_H323_GATEWAY: *ppszSubKey = AUDIO_KEY; *ppszValue = REGVAL_H323_GATEWAY; break; case NM_SYSPROP_H323_GATEWAY_ENABLE: *ppszSubKey = AUDIO_KEY; *ppszValue = REGVAL_USE_H323_GATEWAY; *pfString = FALSE; break; case NM_SYSPROP_INSTALL_DIRECTORY: *phkey = HKEY_LOCAL_MACHINE; *ppszSubKey = CONFERENCING_KEY; *ppszValue = REGVAL_INSTALL_DIR; break; case NM_SYSPROP_APP_NAME: *phkey = HKEY_LOCAL_MACHINE; *ppszSubKey = CONFERENCING_KEY; *ppszValue = REGVAL_NC_NAME; break; default: WARNING_OUT(("GetKeyDataForProp - invalid argument %d", uProp)); bRet = false; break; } /* switch (uProp) */ DBGEXIT_BOOL(CNmSysInfoObj::GetKeyDataForProp,bRet ? TRUE : FALSE); return bRet; } /*static*/ void CNmSysInfoObj::_GetSzKeyForGuid(LPTSTR psz, REFGUID rguid) { DBGENTRY(CNmSysInfoObj::_GetSzKeyForGuid); lstrcpy(psz, GUID_KEY "\\"); GuidToSz((GUID *) &rguid, &psz[lstrlen(psz)]); DBGEXIT(CNmSysInfoObj::_GetSzKeyForGuid); } HRESULT CNmSysInfoObj::_EnsureConfHook(void) { HRESULT hr = S_OK; if(!m_spConfHook) { hr = CoCreateInstance(CLSID_NmManager, NULL, CLSCTX_ALL, IID_IInternalConfExe, reinterpret_cast(&m_spConfHook)); if(SUCCEEDED(hr)) { m_spConfHook->SetSysInfoID(m_dwID); } } return hr; }