Leaked source code of windows server 2003
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.

504 lines
12 KiB

  1. // File: isysinfo.cpp
  2. //
  3. // INmSysInfo interface (system information)
  4. #include "precomp.h"
  5. #include "imanager.h"
  6. #include "cuserdta.hpp"
  7. #include "isysinfo.h"
  8. #include <iappldr.h>
  9. #include <tsecctrl.h>
  10. extern VOID SetBandwidth(UINT uBandwidth);
  11. CNmSysInfo* CNmSysInfo::m_pSysInfo = NULL;
  12. BOOL g_fLoggedOn = FALSE; // Set by NM_SYSOPT_LOGGED_ON
  13. static HRESULT OnGateKeeperNotify(IUnknown *pNmSysNotify, LPVOID code, REFIID riid);
  14. static const IID * g_apiidCP_Manager[] =
  15. {
  16. {&IID_INmSysInfoNotify}
  17. };
  18. /* C N M S Y S I N F O */
  19. /*-------------------------------------------------------------------------
  20. %%Function: CNmSysInfo
  21. -------------------------------------------------------------------------*/
  22. CNmSysInfo::CNmSysInfo() :
  23. CConnectionPointContainer(g_apiidCP_Manager, ARRAY_ELEMENTS(g_apiidCP_Manager)),
  24. m_bstrUserName(NULL)
  25. {
  26. DbgMsg(iZONE_OBJECTS, "Obj: %08X created CNmSysInfo", this);
  27. ASSERT(NULL == m_pSysInfo);
  28. m_pSysInfo = this;
  29. }
  30. CNmSysInfo::~CNmSysInfo(void)
  31. {
  32. DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CNmSysInfo", this);
  33. SysFreeString(m_bstrUserName);
  34. m_pSysInfo = NULL;
  35. }
  36. //////////////////////////////////////////////////////////////////////////
  37. // CNmSysInfo:IUknown
  38. ULONG STDMETHODCALLTYPE CNmSysInfo::AddRef(void)
  39. {
  40. return RefCount::AddRef();
  41. }
  42. ULONG STDMETHODCALLTYPE CNmSysInfo::Release(void)
  43. {
  44. return RefCount::Release();
  45. }
  46. HRESULT STDMETHODCALLTYPE CNmSysInfo::QueryInterface(REFIID riid, PVOID *ppv)
  47. {
  48. HRESULT hr = S_OK;
  49. if ((riid == IID_INmSysInfo2) || (riid == IID_INmSysInfo) || (riid == IID_IUnknown))
  50. {
  51. *ppv = (INmSysInfo *)this;
  52. ApiDebugMsg(("CNmSysInfo::QueryInterface()"));
  53. }
  54. else if (riid == IID_IConnectionPointContainer)
  55. {
  56. *ppv = (IConnectionPointContainer *) this;
  57. DbgMsgApi("CNmSysInfo::QueryInterface(): Returning IConnectionPointContainer.");
  58. }
  59. else
  60. {
  61. hr = E_NOINTERFACE;
  62. *ppv = NULL;
  63. ApiDebugMsg(("CNmSysInfo::QueryInterface(): Called on unknown interface."));
  64. }
  65. if (S_OK == hr)
  66. {
  67. AddRef();
  68. }
  69. return hr;
  70. }
  71. //////////////////////////////////////////////////////////////////////////
  72. // INmSysInfo
  73. HRESULT STDMETHODCALLTYPE CNmSysInfo::IsInstalled(void)
  74. {
  75. // TODO: GetLaunchInfo isn't useful for in-proc
  76. return S_OK;
  77. }
  78. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetProperty(NM_SYSPROP uProp, BSTR *pbstrProp)
  79. {
  80. return E_NOTIMPL;
  81. }
  82. HRESULT STDMETHODCALLTYPE CNmSysInfo::SetProperty(NM_SYSPROP uProp, BSTR bstrData)
  83. {
  84. switch (uProp)
  85. {
  86. case NM_SYSPROP_USER_NAME:
  87. SysFreeString(m_bstrUserName);
  88. m_bstrUserName = SysAllocString(bstrData);
  89. if (NULL != g_pH323UI)
  90. {
  91. g_pH323UI->SetUserName(bstrData);
  92. }
  93. return S_OK;
  94. default:
  95. break;
  96. }
  97. return E_INVALIDARG;
  98. }
  99. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb)
  100. {
  101. return m_UserData.GetUserData(rguid,ppb,pcb);
  102. }
  103. HRESULT STDMETHODCALLTYPE CNmSysInfo::SetUserData(REFGUID rguid, BYTE *pb, ULONG cb)
  104. {
  105. return m_UserData.AddUserData((GUID *)&rguid,(unsigned short)cb,pb);
  106. }
  107. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetNmApp(REFGUID rguid,
  108. BSTR *pbstrApplication, BSTR *pbstrCommandLine, BSTR *pbstrDirectory)
  109. {
  110. return E_NOTIMPL;
  111. }
  112. HRESULT STDMETHODCALLTYPE CNmSysInfo::SetNmApp(REFGUID rguid,
  113. BSTR bstrApplication, BSTR bstrCommandLine, BSTR bstrDirectory)
  114. {
  115. return E_NOTIMPL;
  116. }
  117. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetNmchCaps(ULONG *pchCaps)
  118. {
  119. return E_NOTIMPL;
  120. }
  121. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetLaunchInfo(INmConference **ppConference, INmMember **ppMember)
  122. {
  123. return E_NOTIMPL;
  124. }
  125. //////////////////////////////////////////////////////////////////////////
  126. // INmSysInfo3
  127. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetOption(NM_SYSOPT uOption, ULONG * plValue)
  128. {
  129. return E_NOTIMPL;
  130. }
  131. HRESULT STDMETHODCALLTYPE CNmSysInfo::SetOption(NM_SYSOPT uOption, ULONG lValue)
  132. {
  133. IAudioDevice *pAudioDevice = NULL;
  134. IMediaChannelBuilder *pMCB = NULL;
  135. switch (uOption)
  136. {
  137. case NM_SYSOPT_BANDWIDTH:
  138. {
  139. ::SetBandwidth(lValue);
  140. return S_OK;
  141. }
  142. case NM_SYSOPT_CAPTURE_DEVICE:
  143. {
  144. if (NULL == g_pH323UI)
  145. return E_FAIL;
  146. g_pH323UI->SetCaptureDevice(lValue);
  147. return S_OK;
  148. }
  149. case NM_SYSOPT_LOGGED_ON:
  150. {
  151. g_fLoggedOn = lValue;
  152. return S_OK;
  153. }
  154. case NM_SYSOPT_DIRECTSOUND:
  155. {
  156. if (NULL == g_pH323UI)
  157. return E_FAIL;
  158. pMCB = g_pH323UI->GetStreamProvider();
  159. if (pMCB)
  160. {
  161. pMCB->QueryInterface(IID_IAudioDevice, (void**)&pAudioDevice);
  162. pAudioDevice->SetDirectSound((BOOL)lValue);
  163. pAudioDevice->Release();
  164. pMCB->Release();
  165. return S_OK;
  166. }
  167. }
  168. case NM_SYSOPT_FULLDUPLEX:
  169. {
  170. if (NULL == g_pH323UI)
  171. return E_FAIL;
  172. pMCB = g_pH323UI->GetStreamProvider();
  173. if (pMCB)
  174. {
  175. pMCB->QueryInterface(IID_IAudioDevice, (void**)&pAudioDevice);
  176. pAudioDevice->SetDuplex((BOOL)lValue); // true==full, false==half
  177. pAudioDevice->Release();
  178. pMCB->Release();
  179. return S_OK;
  180. }
  181. }
  182. default:
  183. break;
  184. }
  185. return E_INVALIDARG;
  186. }
  187. HRESULT STDMETHODCALLTYPE CNmSysInfo::ProcessSecurityData(DWORD dwTaskCode, DWORD_PTR dwParam1, DWORD_PTR dwParam2,
  188. DWORD * pdwResult)
  189. {
  190. switch (dwTaskCode)
  191. {
  192. case LOADFTAPPLET:
  193. {
  194. ::T120_LoadApplet(APPLET_ID_FT, TRUE, 0, FALSE, NULL);
  195. return S_OK;
  196. }
  197. case UNLOADFTAPPLET:
  198. {
  199. ::T120_CloseApplet(APPLET_ID_FT, TRUE, TRUE, 600);
  200. return S_OK;
  201. }
  202. default:
  203. {
  204. if (NULL != pdwResult) {
  205. (* pdwResult) = ::T120_TprtSecCtrl(dwTaskCode, dwParam1, dwParam2);
  206. return S_OK;
  207. }
  208. else {
  209. return E_FAIL;
  210. }
  211. }
  212. }
  213. }
  214. //////////////////////////////////////////////////////////////////////////
  215. // Gatekeeper / Alias routines
  216. HRESULT STDMETHODCALLTYPE CNmSysInfo::GkLogon(BSTR bstrServer, BSTR bstrAliasID, BSTR bstrAliasE164)
  217. {
  218. TRACE_OUT(("Gatekeeper Logon: Server=[%ls] AliasID=[%ls] AliasE164=[%ls]",
  219. bstrServer,
  220. bstrAliasID ? bstrAliasID : L"<NULL>",
  221. bstrAliasE164 ? bstrAliasE164 : L"<NULL>"));
  222. HRESULT hr = E_FAIL;
  223. if (NULL != g_pH323UI)
  224. {
  225. IH323CallControl * pH323CallControl = g_pH323UI->GetH323CallControl();
  226. if (NULL != pH323CallControl)
  227. {
  228. SOCKADDR_IN sin;
  229. sin.sin_family = AF_INET;
  230. sin.sin_addr.s_addr = inet_addr(CUSTRING(bstrServer));
  231. // If inet_addr failed, this may be a host address, so try to
  232. // resolve it
  233. if (INADDR_NONE == sin.sin_addr.s_addr)
  234. {
  235. HOSTENT *host_info;
  236. if ( NULL != (host_info = gethostbyname(CUSTRING(bstrServer))))
  237. {
  238. // Only expecting IP addresses..
  239. ASSERT(( host_info->h_addrtype == AF_INET ));
  240. ASSERT(( host_info->h_length == sizeof(DWORD)));
  241. sin.sin_addr.s_addr = *((DWORD *)host_info->h_addr);
  242. }
  243. }
  244. if ((INADDR_NONE != sin.sin_addr.s_addr)
  245. && (INADDR_ANY != sin.sin_addr.s_addr))
  246. {
  247. H323ALIASLIST AliasList;
  248. H323ALIASNAME AliasNames[2];
  249. UINT nAliases = 0;
  250. UINT nLen;
  251. nLen = SysStringLen(bstrAliasID);
  252. if (nLen > 0)
  253. {
  254. AliasNames[nAliases].aType = AT_H323_ID;
  255. AliasNames[nAliases].lpwData = bstrAliasID;
  256. AliasNames[nAliases].wDataLength = (WORD)nLen;// # of unicode chars, w/o NULL terminator
  257. ++nAliases;
  258. }
  259. nLen = SysStringLen(bstrAliasE164);
  260. if (nLen > 0)
  261. {
  262. AliasNames[nAliases].aType = AT_H323_E164;
  263. AliasNames[nAliases].lpwData = bstrAliasE164;
  264. AliasNames[nAliases].wDataLength = (WORD)nLen;// # of unicode chars, w/o NULL terminator
  265. ++nAliases;
  266. }
  267. AliasList.wCount = (WORD)nAliases;
  268. AliasList.pItems = AliasNames;
  269. hr = pH323CallControl->EnableGatekeeper(TRUE, &sin, &AliasList, CNmSysInfo::RasNotify);
  270. if (SUCCEEDED(hr))
  271. {
  272. // keep a global copy of the Getkeeper SOCKADDR_IN
  273. g_sinGateKeeper = sin;
  274. }
  275. }
  276. }
  277. }
  278. return hr;
  279. }
  280. HRESULT STDMETHODCALLTYPE CNmSysInfo::GkLogoff(void)
  281. {
  282. TRACE_OUT(("Gatekeeper Logoff"));
  283. HRESULT hr = S_OK;
  284. if (NULL != g_pH323UI)
  285. {
  286. IH323CallControl * pH323CallControl = g_pH323UI->GetH323CallControl();
  287. if (NULL != pH323CallControl)
  288. {
  289. hr = pH323CallControl->EnableGatekeeper(FALSE, NULL, NULL, CNmSysInfo::RasNotify);
  290. if (SUCCEEDED(hr))
  291. {
  292. // invalidate the global Getkeeper SOCKADDR_IN
  293. g_sinGateKeeper.sin_addr.s_addr = INADDR_NONE;
  294. }
  295. }
  296. }
  297. return hr;
  298. }
  299. HRESULT STDMETHODCALLTYPE CNmSysInfo::GkState(NM_GK_STATE * pgkState)
  300. {
  301. if (NULL == pgkState)
  302. return E_POINTER;
  303. *pgkState = NM_GK_INVALID;
  304. return E_NOTIMPL;
  305. }
  306. VOID CALLBACK CNmSysInfo::RasNotify(DWORD dwRasEvent, HRESULT hReason)
  307. {
  308. NM_GK_NOTIFY_CODE code = NM_GKNC_INVALID;
  309. switch(dwRasEvent)
  310. {
  311. case RAS_REG_TIMEOUT: // GK did not respond. (no hReason)
  312. code = NM_GKNC_LOGON_TIMEOUT;
  313. break;
  314. case RAS_REG_CONFIRM: // received RCF (registration confirmed) (no hReason)
  315. code = NM_GKNC_REG_CONFIRM;
  316. break;
  317. case RAS_UNREG_CONFIRM: // received UCF (unregistration confirmed) (no hReason)
  318. code = NM_GKNC_UNREG_CONFIRM;
  319. break;
  320. case RAS_REJECTED: // received RRJ (registration rejected)
  321. code = NM_GKNC_REJECTED;
  322. ASSERT(CUSTOM_FACILITY(hReason) == FACILITY_GKIREGISTRATION);
  323. switch(CUSTOM_FACILITY_CODE(hReason))
  324. {
  325. case RRJ_DISCOVERY_REQ: TRACE_OUT(("NmSysInfo::RasNotify: GateKeeper logon failed with code RRJ_DISCOVERY_REQ"));
  326. break;
  327. case RRJ_INVALID_REVISION: TRACE_OUT(("GateKeeper logon failed with code RRJ_INVALID_REVISION"));
  328. break;
  329. case RRJ_INVALID_CALL_ADDR: TRACE_OUT(("GateKeeper logon failed with code RRJ_INVALID_CALL_ADDR"));
  330. break;
  331. case RRJ_INVALID_RAS_ADDR: TRACE_OUT(("GateKeeper logon failed with code RRJ_INVALID_RAS_ADDR"));
  332. break;
  333. case RRJ_DUPLICATE_ALIAS: TRACE_OUT(("GateKeeper logon failed with code RRJ_DUPLICATE_ALIAS"));
  334. break;
  335. case RRJ_INVALID_TERMINAL_TYPE: TRACE_OUT(("GateKeeper logon failed with code RRJ_INVALID_TERMINAL_TYPE"));
  336. break;
  337. case RRJ_UNDEFINED: TRACE_OUT(("GateKeeper logon failed with code RRJ_UNDEFINED"));
  338. break;
  339. case RRJ_TRANSPORT_NOT_SUPPORTED: TRACE_OUT(("GateKeeper logon failed with code RRJ_TRANSPORT_NOT_SUPPORTED"));
  340. break;
  341. case RRJ_TRANSPORT_QOS_NOT_SUPPORTED: TRACE_OUT(("GateKeeper logon failed with code RRJ_TRANSPORT_QOS_NOT_SUPPORTED"));
  342. break;
  343. case RRJ_RESOURCE_UNAVAILABLE: TRACE_OUT(("GateKeeper logon failed with code RRJ_RESOURCE_UNAVAILABLE"));
  344. break;
  345. case RRJ_INVALID_ALIAS: TRACE_OUT(("GateKeeper logon failed with code RRJ_INVALID_ALIAS"));
  346. break;
  347. case RRJ_SECURITY_DENIAL: TRACE_OUT(("GateKeeper logon failed with code RRJ_SECURITY_DENIAL"));
  348. break;
  349. default:
  350. break;
  351. }
  352. break;
  353. case RAS_UNREG_REQ: // received URQ
  354. code = NM_GKNC_UNREG_REQ;
  355. // (unregistration request - means that gatekeeper booted the endpoint off)
  356. ASSERT(CUSTOM_FACILITY(hReason) == FACILITY_GKIUNREGREQ);
  357. switch(CUSTOM_FACILITY_CODE(hReason))
  358. {
  359. case URQ_REREG_REQUIRED: // GK wants another registration
  360. case URQ_TTL_EXPIRED: // TimeToLive expired
  361. case URQ_SECURITY_DENIAL:
  362. case URQ_UNDEFINED:
  363. default:
  364. break;
  365. }
  366. break;
  367. default:
  368. break;
  369. }
  370. if( NM_GKNC_INVALID != code )
  371. {
  372. if (m_pSysInfo)
  373. {
  374. m_pSysInfo->NotifySink(reinterpret_cast<LPVOID>(code), OnGateKeeperNotify);
  375. }
  376. }
  377. }
  378. HRESULT OnGateKeeperNotify(IUnknown *pNmSysNotify, LPVOID code, REFIID riid)
  379. {
  380. HRESULT hr = S_OK;
  381. if( riid == IID_INmSysInfoNotify )
  382. {
  383. NM_GK_NOTIFY_CODE gknc = (NM_GK_NOTIFY_CODE)((DWORD_PTR)(code));
  384. static_cast<INmSysInfoNotify*>(pNmSysNotify)->GateKeeperNotify( gknc );
  385. }
  386. return hr;
  387. }
  388. //////////////////////////////////////////////////////////////////////////
  389. // Internal Methods
  390. HRESULT STDMETHODCALLTYPE CNmSysInfo::GetUserDataList(ULONG * pnRecords, GCCUserData *** pppUserData)
  391. {
  392. unsigned short nsRecords;
  393. HRESULT hr = m_UserData.GetUserDataList(&nsRecords,pppUserData);
  394. *pnRecords = nsRecords;
  395. return hr;
  396. }