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.

1215 lines
36 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Service.cpp
  5. Abstract:
  6. This file contains the implementation of IPCHService interface.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 03/14/2000
  9. created
  10. Kalyani Narlanka (Kalyanin) 10/20/2000
  11. Added functionality for Unsolicited Remote Control
  12. ******************************************************************************/
  13. #include "stdafx.h"
  14. #include <KeysLib.h>
  15. #include <wtsapi32.h>
  16. #include <winsta.h>
  17. #include <unsolicitedRC.h>
  18. #include "sessmgr_i.c"
  19. #include <sessmgr.h>
  20. #include "rassistance.h"
  21. #include "rassistance_i.c"
  22. /////////////////////////////////////////////////////////////////////////////
  23. static const WCHAR s_location_HELPCTR [] = HC_ROOT_HELPSVC_BINARIES L"\\HelpCtr.exe";
  24. static const WCHAR s_location_HELPSVC [] = HC_ROOT_HELPSVC_BINARIES L"\\HelpSvc.exe";
  25. static const WCHAR s_location_HELPHOST[] = HC_ROOT_HELPSVC_BINARIES L"\\HelpHost.exe";
  26. static const LPCWSTR s_include_Generic[] =
  27. {
  28. s_location_HELPCTR ,
  29. s_location_HELPSVC ,
  30. s_location_HELPHOST,
  31. NULL
  32. };
  33. static const LPCWSTR s_include_RegisterHost[] =
  34. {
  35. s_location_HELPHOST,
  36. NULL
  37. };
  38. static const WCHAR c_szUnsolicitedRA [] = L"Software\\Policies\\Microsoft\\Windows NT\\Terminal Services";
  39. static const WCHAR c_szUnsolicitedRA_SD[] = L"UnsolicitedAccessDACL";
  40. static const WCHAR c_szUnsolicitedListKey[]= L"RAUnsolicit";
  41. static const WCHAR c_szUnsolicitedNew_SD [] = L"UnsolicitedAccessNewDACL";
  42. static HRESULT local_MakeDACL( MPC::WStringList& sColl, LPWSTR& pwszSD );
  43. static HRESULT local_GetDACLValue( MPC::wstring& pSD, bool& fFound);
  44. /////////////////////////////////////////////////////////////////////////////
  45. CPCHService::CPCHService()
  46. {
  47. __HCP_FUNC_ENTRY( "CPCHService::CPCHService" );
  48. m_fVerified = false; // bool m_fVerified;
  49. }
  50. CPCHService::~CPCHService()
  51. {
  52. __HCP_FUNC_ENTRY( "CPCHService::~CPCHService" );
  53. }
  54. /////////////////////////////////////////////////////////////////////////////
  55. STDMETHODIMP CPCHService::get_RemoteSKUs( /*[out, retval]*/ IPCHCollection* *pVal )
  56. {
  57. __HCP_FUNC_ENTRY( "CPCHService::get_RemoteSKUs" );
  58. HRESULT hr;
  59. __MPC_PARAMCHECK_BEGIN(hr)
  60. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  61. __MPC_PARAMCHECK_END();
  62. //
  63. // Return a list with only the exported SKUs.
  64. //
  65. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHTaxonomyDatabase::SelectInstalledSKUs( true, pVal ));
  66. hr = S_OK;
  67. __HCP_FUNC_CLEANUP;
  68. __HCP_FUNC_EXIT(hr);
  69. }
  70. ////////////////////
  71. // Bug 456403
  72. STDMETHODIMP CPCHService::get_RemoteModemConnected( /*[out, retval]*/ VARIANT_BOOL *fModemConnected )
  73. {
  74. __HCP_FUNC_ENTRY( "CPCHService::RemoteModemConnected" );
  75. HRESULT hr;
  76. DWORD dwMode = 0;
  77. __MPC_PARAMCHECK_BEGIN(hr)
  78. __MPC_PARAMCHECK_POINTER_AND_SET(fModemConnected,VARIANT_FALSE);
  79. __MPC_PARAMCHECK_END();
  80. if(::InternetGetConnectedState( &dwMode, 0 ) == TRUE)
  81. {
  82. if(dwMode & INTERNET_CONNECTION_MODEM)
  83. {
  84. *fModemConnected = VARIANT_TRUE;
  85. }
  86. }
  87. hr = S_OK;
  88. __HCP_FUNC_CLEANUP;
  89. __HCP_FUNC_EXIT(hr);
  90. }
  91. ////////////////////
  92. STDMETHODIMP CPCHService::IsTrusted( /*[in]*/ BSTR bstrURL, /*[out, retval]*/ VARIANT_BOOL *pfTrusted )
  93. {
  94. __HCP_FUNC_ENTRY( "CPCHService::IsTrusted" );
  95. HRESULT hr;
  96. bool fTrusted;
  97. __MPC_PARAMCHECK_BEGIN(hr)
  98. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrURL);
  99. __MPC_PARAMCHECK_POINTER_AND_SET(pfTrusted,VARIANT_FALSE);
  100. __MPC_PARAMCHECK_NOTNULL(CPCHContentStore::s_GLOBAL);
  101. __MPC_PARAMCHECK_END();
  102. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHContentStore::s_GLOBAL->IsTrusted( bstrURL, fTrusted ));
  103. if(fTrusted) *pfTrusted = VARIANT_TRUE;
  104. hr = S_OK;
  105. __HCP_FUNC_CLEANUP;
  106. __HCP_FUNC_EXIT(hr);
  107. }
  108. ////////////////////
  109. STDMETHODIMP CPCHService::Utility( /*[in ]*/ BSTR bstrSKU ,
  110. /*[in ]*/ long lLCID ,
  111. /*[out]*/ IPCHUtility* *pVal )
  112. {
  113. __HCP_FUNC_ENTRY( "CPCHService::Utility" );
  114. HRESULT hr;
  115. CComPtr<CPCHUtility> svc;
  116. __MPC_PARAMCHECK_BEGIN(hr)
  117. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  118. __MPC_PARAMCHECK_END();
  119. //
  120. // Verify the caller is a trusted one.
  121. //
  122. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::VerifyCallerIsTrusted( s_include_Generic ));
  123. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &svc ));
  124. if(bstrSKU || lLCID)
  125. {
  126. CComPtr<IPCHUserSettings> pchus;
  127. __MPC_EXIT_IF_METHOD_FAILS(hr, svc->get_UserSettings( &pchus ));
  128. __MPC_EXIT_IF_METHOD_FAILS(hr, pchus->Select( bstrSKU, lLCID ));
  129. }
  130. __MPC_EXIT_IF_METHOD_FAILS(hr, svc.QueryInterface( pVal ));
  131. hr = S_OK;
  132. __HCP_FUNC_CLEANUP;
  133. __HCP_FUNC_EXIT(hr);
  134. }
  135. STDMETHODIMP CPCHService::RemoteHelpContents( /*[in ]*/ BSTR bstrSKU ,
  136. /*[in ]*/ long lLCID ,
  137. /*[out]*/ IPCHRemoteHelpContents* *pVal )
  138. {
  139. __HCP_FUNC_ENTRY( "CPCHService::RemoteHelpContents" );
  140. HRESULT hr;
  141. CComPtr<CPCHRemoteHelpContents> rhc;
  142. Taxonomy::HelpSet ths;
  143. Taxonomy::LockingHandle handle;
  144. Taxonomy::InstalledInstanceIter it;
  145. bool fFound;
  146. __MPC_PARAMCHECK_BEGIN(hr)
  147. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  148. __MPC_PARAMCHECK_NOTNULL(Taxonomy::InstalledInstanceStore::s_GLOBAL);
  149. __MPC_PARAMCHECK_END();
  150. __MPC_EXIT_IF_METHOD_FAILS(hr, ths.Initialize( bstrSKU, lLCID ));
  151. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  152. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( ths, fFound, it ));
  153. // (weizhao) Return remote help content only if the specified SKU is found and
  154. // it is marked as "Shared".
  155. if(fFound && it->m_inst.m_fExported)
  156. {
  157. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &rhc ));
  158. __MPC_EXIT_IF_METHOD_FAILS(hr, rhc->Init( it->m_inst ));
  159. __MPC_EXIT_IF_METHOD_FAILS(hr, rhc.QueryInterface( pVal ));
  160. }
  161. hr = S_OK;
  162. __HCP_FUNC_CLEANUP;
  163. __HCP_FUNC_EXIT(hr);
  164. }
  165. ////////////////////
  166. STDMETHODIMP CPCHService::RegisterHost( /*[in]*/ BSTR bstrID, /*[in]*/ IUnknown* pUnk )
  167. {
  168. __HCP_FUNC_ENTRY( "CPCHService::RegisterHost" );
  169. HRESULT hr;
  170. CComQIPtr<IPCHSlaveProcess> pObj = pUnk;
  171. if(pObj == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_NOINTERFACE);
  172. //
  173. // Verify the caller is really HelpHost.exe.
  174. //
  175. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::VerifyCallerIsTrusted( s_include_RegisterHost ));
  176. hr = CPCHUserProcess::s_GLOBAL ? CPCHUserProcess::s_GLOBAL->RegisterHost( bstrID, pObj ) : E_FAIL;
  177. __HCP_FUNC_CLEANUP;
  178. __HCP_FUNC_EXIT(hr);
  179. }
  180. STDMETHODIMP CPCHService::CreateScriptWrapper( /*[in ]*/ REFCLSID rclsid ,
  181. /*[in ]*/ BSTR bstrCode ,
  182. /*[in ]*/ BSTR bstrURL ,
  183. /*[out]*/ IUnknown* *ppObj )
  184. {
  185. __HCP_FUNC_ENTRY( "CPCHService::CreateScriptWrapper" );
  186. HRESULT hr;
  187. CComBSTR bstrRealCode;
  188. CPCHScriptWrapper_ServerSide::HeaderList lst;
  189. CPCHScriptWrapper_ServerSide::HeaderIter it;
  190. CPCHUserProcess::UserEntry ue;
  191. CComPtr<IPCHSlaveProcess> sp;
  192. MPC::wstring strVendorID;
  193. MPC::wstring strSignature;
  194. if(bstrURL == NULL ||
  195. CPCHContentStore::s_GLOBAL == NULL ||
  196. CSAFReg ::s_GLOBAL == NULL ||
  197. CPCHUserProcess ::s_GLOBAL == NULL )
  198. {
  199. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
  200. }
  201. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHScriptWrapper_ServerSide::ProcessBody( bstrCode, bstrRealCode, lst ));
  202. //
  203. // Look for the vendor ID.
  204. //
  205. it = std::find( lst.begin(), lst.end(), L"VENDORID" );
  206. if(it == lst.end())
  207. {
  208. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
  209. }
  210. strVendorID = it->m_strValue;
  211. //
  212. // Make sure the VendorID declared in the script matches the one which has registered the URL as trusted.
  213. //
  214. {
  215. bool fTrusted;
  216. MPC::wstring strVendorURL;
  217. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHContentStore::s_GLOBAL->IsTrusted( bstrURL, fTrusted, &strVendorURL ));
  218. if(MPC::StrICmp( strVendorID, strVendorURL ))
  219. {
  220. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
  221. }
  222. }
  223. //
  224. // Look for the script signature.
  225. //
  226. it = std::find( lst.begin(), lst.end(), L"SIGNATURE" );
  227. if(it == lst.end())
  228. {
  229. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
  230. }
  231. strSignature = it->m_strValue;
  232. //
  233. // Lookup the vendor in the SAF store (this also prepares the creation of the user process).
  234. //
  235. __MPC_EXIT_IF_METHOD_FAILS(hr, CSAFReg::s_GLOBAL->LookupAccountData( CComBSTR( strVendorID.c_str() ), ue ));
  236. //
  237. // Verify signature.
  238. //
  239. {
  240. CPCHCryptKeys key;
  241. __MPC_EXIT_IF_METHOD_FAILS(hr, key.ImportPublic( ue.GetPublicKey() ));
  242. __MPC_EXIT_IF_METHOD_FAILS(hr, key.VerifyData( strSignature.c_str(), (BYTE*)(BSTR)bstrRealCode, ::SysStringLen( bstrRealCode ) * sizeof(WCHAR) ));
  243. }
  244. //
  245. // Create the vendor's process.
  246. //
  247. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHUserProcess::s_GLOBAL->Connect( ue, &sp ));
  248. //
  249. // Forward request.
  250. //
  251. __MPC_EXIT_IF_METHOD_FAILS(hr, sp->CreateScriptWrapper( rclsid, bstrCode, bstrURL, ppObj ));
  252. hr = S_OK;
  253. __HCP_FUNC_CLEANUP;
  254. __HCP_FUNC_EXIT(hr);
  255. }
  256. ////////////////////
  257. STDMETHODIMP CPCHService::TriggerScheduledDataCollection( /*[in]*/ VARIANT_BOOL fStart )
  258. {
  259. return CPCHSystemMonitor::s_GLOBAL ? CPCHSystemMonitor::s_GLOBAL->TriggerDataCollection( fStart == VARIANT_TRUE ) : E_FAIL;
  260. }
  261. STDMETHODIMP CPCHService::PrepareForShutdown()
  262. {
  263. __HCP_FUNC_ENTRY( "CPCHService::PrepareForShutdown" );
  264. HRESULT hr;
  265. //
  266. // Allow only SYSTEM
  267. //
  268. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_SYSTEM ));
  269. _Module.ForceShutdown();
  270. hr = S_OK;
  271. __HCP_FUNC_CLEANUP;
  272. __HCP_FUNC_EXIT(hr);
  273. }
  274. ////////////////////
  275. STDMETHODIMP CPCHService::ForceSystemRestore()
  276. {
  277. __HCP_FUNC_ENTRY( "CPCHService::ForceSystemRestore" );
  278. HRESULT hr;
  279. CComObject<HCUpdate::Engine>* hc = NULL;
  280. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::VerifyCallerIsTrusted( s_include_Generic ));
  281. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
  282. __MPC_EXIT_IF_METHOD_FAILS(hr, hc->ForceSystemRestore());
  283. hr = S_OK;
  284. __HCP_FUNC_CLEANUP;
  285. if(hc) hc->Release();
  286. __HCP_FUNC_EXIT(hr);
  287. }
  288. STDMETHODIMP CPCHService::UpgradeDetected()
  289. {
  290. __HCP_FUNC_ENTRY( "CPCHService::UpgradeDetected" );
  291. HRESULT hr;
  292. //
  293. // Allow only ADMINS.
  294. //
  295. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_ADMINS ));
  296. hr = S_OK;
  297. __HCP_FUNC_CLEANUP;
  298. __HCP_FUNC_EXIT(hr);
  299. }
  300. STDMETHODIMP CPCHService::MUI_Install( /*[in]*/ long LCID, /*[in]*/ BSTR bstrFile )
  301. {
  302. __HCP_FUNC_ENTRY( "CPCHService::MUI_Install" );
  303. HRESULT hr;
  304. //
  305. // Allow only ADMINS.
  306. //
  307. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_ADMINS ));
  308. ////////////////////////////////////////
  309. {
  310. Installer::Package pkg;
  311. CComPtr<CPCHSetOfHelpTopics> sht;
  312. MPC::wstring strFile;
  313. //
  314. // Because of a possible problem with the INF, it could be that the filename has an extra "%LCID%" in it, instead of the straight %LCID%.
  315. //
  316. {
  317. WCHAR rgBufBad[64]; StringCchPrintfW( rgBufBad, ARRAYSIZE(rgBufBad), L"\"%04x\"", LCID );
  318. WCHAR rgBufOk [64]; StringCchPrintfW( rgBufOk , ARRAYSIZE(rgBufOk), L"%04x" , LCID );
  319. MPC::wstring::size_type pos;
  320. MPC::wstring::size_type len = wcslen( rgBufBad );
  321. strFile = SAFEBSTR(bstrFile);
  322. while((pos = strFile.find( rgBufBad )) != strFile.npos)
  323. {
  324. strFile.replace( pos, len, rgBufOk );
  325. }
  326. }
  327. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &sht ));
  328. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( strFile.c_str() ));
  329. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load( ));
  330. {
  331. Taxonomy::InstanceBase& base = pkg.GetData();
  332. if(_wcsicmp( base.m_ths.GetSKU() , Taxonomy::HelpSet::GetMachineSKU() ) ||
  333. base.m_ths.GetLanguage() != LCID ||
  334. LCID == Taxonomy::HelpSet::GetMachineLanguage() ) // Don't overwrite system SKU!!
  335. {
  336. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE); // Mismatch in parameter, ignore it.
  337. }
  338. }
  339. __MPC_EXIT_IF_METHOD_FAILS(hr, sht->DirectInstall( pkg, /*fSetup*/false, /*fSystem*/false, /*fMUI*/true ));
  340. }
  341. hr = S_OK;
  342. __HCP_FUNC_CLEANUP;
  343. __HCP_FUNC_EXIT(hr);
  344. }
  345. STDMETHODIMP CPCHService::MUI_Uninstall( /*[in]*/ long LCID )
  346. {
  347. __HCP_FUNC_ENTRY( "CPCHService::MUI_Uninstall" );
  348. HRESULT hr;
  349. //
  350. // Allow only ADMINS.
  351. //
  352. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_ADMINS ));
  353. ////////////////////////////////////////
  354. {
  355. Installer::Package pkg;
  356. CComPtr<CPCHSetOfHelpTopics> sht;
  357. Taxonomy::HelpSet ths;
  358. __MPC_EXIT_IF_METHOD_FAILS(hr, ths.Initialize( Taxonomy::HelpSet::GetMachineSKU(), LCID ));
  359. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &sht ));
  360. __MPC_EXIT_IF_METHOD_FAILS(hr, sht->DirectUninstall( &ths ));
  361. }
  362. hr = S_OK;
  363. __HCP_FUNC_CLEANUP;
  364. __HCP_FUNC_EXIT(hr);
  365. }
  366. ////////////////////
  367. static void local_PackString( /*[in/out]*/ CComBSTR& bstr ,
  368. /*[in ]*/ LPCWSTR szAppend )
  369. {
  370. WCHAR rgLen[64];
  371. SANITIZEWSTR( szAppend );
  372. StringCchPrintfW( rgLen, ARRAYSIZE(rgLen), L"%d;", wcslen( szAppend ) );
  373. bstr.Append( rgLen );
  374. bstr.Append( szAppend );
  375. }
  376. static HRESULT local_MakeDACL( MPC::WStringList& sColl, LPWSTR& pwszSD )
  377. {
  378. __HCP_FUNC_ENTRY( "local_MakeDACL" );
  379. SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
  380. SECURITY_DESCRIPTOR sd;
  381. SID_NAME_USE snu;
  382. WCHAR *pwszDomain = NULL, *pwszUser = NULL;
  383. WCHAR wszDom[1024];
  384. DWORD cbNeedACL, cbNeed, cchDom, dwCount;
  385. DWORD cchSD;
  386. PACL pacl = NULL;
  387. PSID *rgsid = NULL, psidAdm = NULL;
  388. BOOL fRet = FALSE;
  389. int i, cSIDs = 0;
  390. long lCount;
  391. HRESULT hr;
  392. MPC::WStringIter it;
  393. lCount = sColl.size();
  394. if (lCount == 0)
  395. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  396. rgsid = (PSID *) malloc (lCount * sizeof(PSID));
  397. if (rgsid == NULL)
  398. __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  399. if (!AllocateAndInitializeSid(&siaNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  400. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
  401. 0, &psidAdm))
  402. {
  403. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  404. }
  405. cbNeedACL = sizeof(ACL);
  406. for(it = sColl.begin(); it != sColl.end(); it++)
  407. {
  408. LPCWSTR bstrVal = it->c_str();
  409. cchDom = sizeof(wszDom)/sizeof(WCHAR);
  410. cbNeed = 0;
  411. fRet = LookupAccountNameW(NULL, bstrVal, NULL, &cbNeed, wszDom, &cchDom,
  412. &snu);
  413. rgsid[cSIDs] = (PSID) malloc (cbNeed);
  414. if (rgsid[cSIDs] == NULL)
  415. __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  416. cchDom = sizeof(wszDom)/sizeof(WCHAR);
  417. fRet = LookupAccountNameW(NULL, bstrVal, rgsid[cSIDs], &cbNeed,
  418. wszDom, &cchDom, &snu);
  419. if (fRet == FALSE)
  420. {
  421. // invalid user name;
  422. free (rgsid[cSIDs]);
  423. rgsid[cSIDs] = NULL;
  424. continue;
  425. }
  426. cbNeedACL += GetLengthSid(rgsid[cSIDs]);
  427. cbNeedACL += (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD));
  428. cSIDs++;
  429. }
  430. if (cbNeedACL == sizeof(ACL)) // No valid entry
  431. {
  432. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  433. }
  434. pacl = (PACL) malloc (cbNeedACL);
  435. if (pacl == NULL)
  436. __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  437. fRet = InitializeAcl(pacl, cbNeedACL, ACL_REVISION);
  438. if (fRet == FALSE)
  439. {
  440. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  441. }
  442. for(i = 0; i < cSIDs; i++)
  443. {
  444. fRet = AddAccessAllowedAce(pacl, ACL_REVISION,
  445. GENERIC_ALL |
  446. STANDARD_RIGHTS_ALL |
  447. SPECIFIC_RIGHTS_ALL, rgsid[i]);
  448. if (fRet == FALSE)
  449. {
  450. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  451. }
  452. }
  453. if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) == FALSE)
  454. {
  455. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  456. }
  457. // set the SD dacl
  458. if (SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE) == FALSE)
  459. {
  460. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  461. }
  462. // set the SD owner
  463. if (SetSecurityDescriptorOwner(&sd, psidAdm, FALSE) == FALSE)
  464. {
  465. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  466. }
  467. // set the SD group
  468. if (SetSecurityDescriptorGroup(&sd, psidAdm, FALSE) == FALSE)
  469. {
  470. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  471. }
  472. // Verify if the SD is valid
  473. if (IsValidSecurityDescriptor(&sd) == FALSE)
  474. {
  475. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  476. }
  477. if (FALSE == ConvertSecurityDescriptorToStringSecurityDescriptorW(&sd, SDDL_REVISION_1,
  478. GROUP_SECURITY_INFORMATION |
  479. OWNER_SECURITY_INFORMATION |
  480. DACL_SECURITY_INFORMATION,
  481. &pwszSD, &cchSD))
  482. {
  483. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(GetLastError()));
  484. }
  485. __MPC_FUNC_CLEANUP;
  486. if (rgsid != NULL)
  487. {
  488. for(i = 0; i < cSIDs; i++)
  489. {
  490. if (rgsid[i] != NULL)
  491. free(rgsid[i]);
  492. }
  493. free(rgsid);
  494. }
  495. if (pacl != NULL)
  496. free(pacl);
  497. if (psidAdm != NULL)
  498. FreeSid(psidAdm);
  499. __MPC_FUNC_EXIT(hr);
  500. }
  501. static HRESULT local_GetDACLValue(MPC::wstring& pSD, bool& fFound)
  502. {
  503. __HCP_FUNC_ENTRY( "local_GetDACLValue" );
  504. HRESULT hr;
  505. CRegKey cKey, cKeyDACL;
  506. LONG lRet;
  507. DWORD dwCount;
  508. LPWSTR pwBuf = NULL;
  509. if (ERROR_SUCCESS != cKey.Open(HKEY_LOCAL_MACHINE, c_szUnsolicitedRA))
  510. {
  511. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  512. }
  513. // Check to see if new DACL value exist
  514. dwCount = 0;
  515. if (ERROR_SUCCESS == cKey.QueryValue(NULL, c_szUnsolicitedNew_SD, &dwCount))
  516. {
  517. if (NULL == (pwBuf = (LPWSTR)malloc(dwCount)))
  518. {
  519. __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  520. }
  521. if (ERROR_SUCCESS != (lRet = cKey.QueryValue(pwBuf, c_szUnsolicitedNew_SD, &dwCount)))
  522. {
  523. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(lRet));
  524. }
  525. pSD = pwBuf;
  526. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  527. }
  528. // If we don't have DACL value, then we need to check DACL regkey list.
  529. if ( ERROR_SUCCESS != cKeyDACL.Open((HKEY)cKey, c_szUnsolicitedListKey))
  530. {
  531. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  532. }
  533. // 1. Do we have default value
  534. dwCount = 0;
  535. if ( ERROR_SUCCESS == cKeyDACL.QueryValue(NULL, NULL, &dwCount) && dwCount > sizeof(WCHAR)) // It's possible it contains '\0'
  536. {
  537. if (pwBuf) free(pwBuf);
  538. if (NULL == (pwBuf = (LPWSTR)malloc(dwCount)))
  539. {
  540. __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  541. }
  542. if ( ERROR_SUCCESS != (lRet = cKeyDACL.QueryValue(pwBuf, NULL, &dwCount)))
  543. {
  544. __MPC_SET_ERROR_AND_EXIT(hr, HRESULT_FROM_WIN32(lRet));
  545. }
  546. pSD = pwBuf;
  547. }
  548. else // Need to calculate DACL
  549. {
  550. DWORD dwIndex = 0;
  551. DWORD dwType;
  552. WCHAR szName[257];
  553. dwCount = 256;
  554. MPC::WStringList sColl;
  555. long lCount;
  556. while (ERROR_SUCCESS == RegEnumValueW((HKEY)cKeyDACL,
  557. dwIndex,
  558. &szName[0],
  559. &dwCount,
  560. NULL,
  561. &dwType,
  562. NULL, // no need to get it's data
  563. NULL))
  564. {
  565. if ((dwType == REG_SZ || dwType == REG_MULTI_SZ || dwType == REG_EXPAND_SZ) && szName[0] != L'\0')
  566. {
  567. sColl.push_back( MPC::wstring(szName) );
  568. }
  569. szName [0] = L'\0';
  570. dwIndex ++;
  571. dwCount = 256;
  572. }
  573. if (sColl.size() > 0)
  574. {
  575. LPWSTR pwDACL = NULL;
  576. __MPC_EXIT_IF_METHOD_FAILS(hr, local_MakeDACL( sColl, pwDACL ));
  577. // Update default value
  578. if (pwDACL)
  579. {
  580. pSD = pwDACL;
  581. cKeyDACL.SetValue(pwDACL);
  582. LocalFree(pwDACL);
  583. }
  584. }
  585. else
  586. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  587. }
  588. hr = S_OK;
  589. __HCP_FUNC_CLEANUP;
  590. if (pwBuf)
  591. {
  592. free(pwBuf);
  593. }
  594. fFound = (hr == S_OK);
  595. __MPC_FUNC_EXIT(hr);
  596. }
  597. static HRESULT local_CheckAccessRights()
  598. {
  599. __HCP_FUNC_ENTRY( "local_CheckAccessRights" );
  600. HRESULT hr;
  601. bool fPermit = false;
  602. CComPtr<IRARegSetting> pRARegSetting;
  603. BOOL fAllowUnsolicited;
  604. //
  605. // Check the policy settings to see whether Unsolicited RA is allowed, if not give an Access Denied error.
  606. // Create an instance of IRARegSetting.
  607. __MPC_EXIT_IF_METHOD_FAILS(hr, pRARegSetting.CoCreateInstance( CLSID_RARegSetting, NULL, CLSCTX_INPROC_SERVER ));
  608. // Call get_AllowUnSolicited() Method of IRARegSetting.
  609. __MPC_EXIT_IF_METHOD_FAILS(hr, pRARegSetting->get_AllowUnSolicited( &fAllowUnsolicited ));
  610. if(!fAllowUnsolicited)
  611. {
  612. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DISABLED_BY_POLICY);
  613. }
  614. // Allow someone from ADMINS to query for this data.
  615. if(SUCCEEDED(MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_ADMINS )))
  616. {
  617. fPermit = true;
  618. }
  619. else // If not from ADMINS, check the caller against the SD stored in the Registry in the String Format.
  620. {
  621. MPC::AccessCheck ac;
  622. MPC::wstring strSD;
  623. bool fFound;
  624. BOOL fGranted = FALSE;
  625. DWORD dwGranted = 0;
  626. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetDACLValue( strSD, fFound));
  627. if(!fFound) __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  628. // Use the SD to check against the Caller.
  629. __MPC_EXIT_IF_METHOD_FAILS(hr, ac.GetTokenFromImpersonation());
  630. if(SUCCEEDED(ac.Verify( ACCESS_READ, fGranted, dwGranted, strSD.c_str() )) && fGranted)
  631. {
  632. fPermit = true;
  633. }
  634. }
  635. if(!fPermit)
  636. {
  637. __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  638. }
  639. hr = S_OK;
  640. __HCP_FUNC_CLEANUP;
  641. __HCP_FUNC_EXIT(hr);
  642. }
  643. STDMETHODIMP CPCHService::RemoteConnectionParms( /*[in ]*/ BSTR bstrUserName ,
  644. /*[in ]*/ BSTR bstrDomainName ,
  645. /*[in ]*/ long lSessionID ,
  646. /*[in ]*/ BSTR bstrUserHelpBlob ,
  647. /*[out]*/ BSTR *pbstrConnectionString )
  648. {
  649. __HCP_FUNC_ENTRY( "CPCHService::RemoteConnectionParms" );
  650. HRESULT hr;
  651. CComPtr<IRemoteDesktopHelpSessionMgr> pRDHelpSessionMgr;
  652. MPC::wstring strSID;
  653. CComBSTR bstrString1;
  654. CComBSTR bstrString2;
  655. CComBSTR bstrExpert;
  656. PSID pExpertSid = NULL;
  657. LPCWSTR szExpertUserName = NULL;
  658. LPCWSTR szExpertDomainName = NULL;
  659. BOOL fRevertSucceeded;
  660. __MPC_PARAMCHECK_BEGIN(hr)
  661. __MPC_PARAMCHECK_POINTER_AND_SET(pbstrConnectionString,NULL);
  662. __MPC_PARAMCHECK_END();
  663. // Fix for bug 367683
  664. // If Unsolicited RA is done from one session to another on the same machine,
  665. // we need to RevertToSelf() before we do anything, this is because on the Expert end we do
  666. // an impersonation before calling this method. While this is correct when the expert
  667. // and novice are on two different machines, in case of a single machine, by the time the
  668. // novice side code is called there is an extra impersonation, which should not be there
  669. // we need to undo this by doing RevertToSelf()
  670. fRevertSucceeded = RevertToSelf();
  671. __MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckAccessRights());
  672. // Create an instance of IRemoteDesktopHelpSessionMgr in order to call its method RemoteCreateHelpSession.
  673. __MPC_EXIT_IF_METHOD_FAILS(hr, pRDHelpSessionMgr.CoCreateInstance( CLSID_RemoteDesktopHelpSessionMgr, NULL, CLSCTX_LOCAL_SERVER ));
  674. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoSetProxyBlanket( pRDHelpSessionMgr ,
  675. RPC_C_AUTHN_DEFAULT ,
  676. RPC_C_AUTHZ_DEFAULT ,
  677. NULL ,
  678. RPC_C_AUTHN_LEVEL_PKT_PRIVACY/*RPC_C_AUTHN_LEVEL_DEFAULT */,
  679. RPC_C_IMP_LEVEL_IMPERSONATE ,
  680. NULL ,
  681. EOAC_NONE ));
  682. //
  683. // Get the SID corresponding to the UserName and DomainName
  684. //
  685. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::NormalizePrincipalToStringSID( bstrUserName, bstrDomainName, strSID ));
  686. //
  687. // Get the Expert SID and then get the username and domain name corresponding to the SID.
  688. //
  689. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetCallerPrincipal ( /*fImpersonate*/true, bstrExpert ));
  690. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::ConvertPrincipalToSID( bstrExpert, pExpertSid ));
  691. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SecurityDescriptor::ConvertSIDToPrincipal( pExpertSid, &szExpertUserName, &szExpertDomainName ));
  692. // Update the user Help Blob before invoking the RemoteCreateHelpSession()
  693. // The UserHelpBlob should have the following format.
  694. // Updated UserHelpBlob = string1 + string2 + original UserHelpBlob.
  695. // string1 = "13;UNSOLICITED=1"
  696. // string2 = #ofchars in expert identity;ID=expertDomainName\expertName
  697. local_PackString( bstrString1, L"UNSOLICITED=1" );
  698. bstrString2 = L"ID=";
  699. bstrString2.Append( szExpertDomainName );
  700. bstrString2.Append( L"\\" );
  701. bstrString2.Append( szExpertUserName );
  702. local_PackString( bstrString1, bstrString2 );
  703. bstrString1.Append( bstrUserHelpBlob );
  704. //Use Salem API to get the Connection Parameters.
  705. {
  706. // Fix for Bug 252092.
  707. static const REMOTE_DESKTOP_SHARING_CLASS c_sharingClass = VIEWDESKTOP_PERMISSION_NOT_REQUIRE;
  708. static const LONG c_lTimeOut = 301; // 5 mins. Timeout after which resolver kills helpctr if
  709. // no response from user (300 seconds)
  710. CComBSTR bstrSID( strSID.c_str() );
  711. __MPC_EXIT_IF_METHOD_FAILS(hr, pRDHelpSessionMgr->RemoteCreateHelpSession( c_sharingClass, c_lTimeOut, lSessionID, bstrSID, bstrString1, pbstrConnectionString ));
  712. }
  713. hr = S_OK;
  714. __HCP_FUNC_CLEANUP;
  715. MPC::SecurityDescriptor::ReleaseMemory( (void*&)pExpertSid );
  716. MPC::SecurityDescriptor::ReleaseMemory( (void*&)szExpertUserName );
  717. MPC::SecurityDescriptor::ReleaseMemory( (void*&)szExpertDomainName );
  718. __HCP_FUNC_EXIT(hr);
  719. }
  720. STDMETHODIMP CPCHService::RemoteUserSessionInfo( /*[out]*/ IPCHCollection* *ppSessions )
  721. {
  722. __HCP_FUNC_ENTRY( "CPCHService::RemoteUserSessionInfo" );
  723. HRESULT hr;
  724. CComPtr<CPCHCollection> pColl;
  725. BOOL fRevertSucceeded;
  726. __MPC_PARAMCHECK_BEGIN(hr)
  727. __MPC_PARAMCHECK_POINTER_AND_SET(ppSessions,NULL);
  728. __MPC_PARAMCHECK_END();
  729. // If Unsolicited RA is done from one session to another on the same machine,
  730. // we need to RevertToSelf() before we do anything, this is because on the Expert end we do
  731. // an impersonation before calling this method. While this is correct when the expert
  732. // and novice are on two different machines, in case of a single machine, by the time the
  733. // novice side code is called there is an extra impersonation, which should not be there
  734. // we need to undo this by doing RevertToSelf()
  735. fRevertSucceeded = RevertToSelf();
  736. __MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckAccessRights());
  737. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
  738. // Transfer the SessionInfoTable to the IPCHCollection.
  739. __MPC_EXIT_IF_METHOD_FAILS(hr, CSAFRemoteConnectionData::Populate( pColl ));
  740. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppSessions ));
  741. hr = S_OK;
  742. __HCP_FUNC_CLEANUP;
  743. __HCP_FUNC_EXIT(hr);
  744. }
  745. /////////////////////////////////////////////////////////////////////////////
  746. /////////////////////////////////////////////////////////////////////////////
  747. /////////////////////////////////////////////////////////////////////////////
  748. CPCHRemoteHelpContents::CPCHRemoteHelpContents()
  749. {
  750. // Taxonomy::Instance m_data;
  751. // Taxonomy::Settings m_ts;
  752. // MPC::wstring m_strDir;
  753. //
  754. // Taxonomy::Updater m_updater;
  755. // JetBlue::SessionHandle m_handle;
  756. m_db = NULL; // JetBlue::Database* m_db;
  757. }
  758. CPCHRemoteHelpContents::~CPCHRemoteHelpContents()
  759. {
  760. DetachFromDatabase();
  761. }
  762. HRESULT CPCHRemoteHelpContents::AttachToDatabase()
  763. {
  764. __HCP_FUNC_ENTRY( "CPCHRemoteHelpContents::AttachToDatabase" );
  765. HRESULT hr;
  766. if(m_db == NULL)
  767. {
  768. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ts.GetDatabase( m_handle, m_db, /*fReadOnly*/true ));
  769. __MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.Init( m_ts, m_db ));
  770. }
  771. hr = S_OK;
  772. __HCP_FUNC_CLEANUP;
  773. __HCP_FUNC_EXIT(hr);
  774. }
  775. void CPCHRemoteHelpContents::DetachFromDatabase()
  776. {
  777. (void)m_updater.Close();
  778. m_handle.Release();
  779. m_db = NULL;
  780. }
  781. ////////////////////////////////////////////////////////////////////////////////
  782. HRESULT CPCHRemoteHelpContents::Init( /*[in]*/ const Taxonomy::Instance& data )
  783. {
  784. __HCP_FUNC_ENTRY( "CPCHRemoteHelpContents::Init" );
  785. HRESULT hr;
  786. m_data = data;
  787. m_ts = data.m_ths;
  788. m_strDir = m_data.m_strHelpFiles; m_strDir += L"\\";
  789. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SubstituteEnvVariables( m_strDir ));
  790. hr = S_OK;
  791. __HCP_FUNC_CLEANUP;
  792. __HCP_FUNC_EXIT(hr);
  793. }
  794. STDMETHODIMP CPCHRemoteHelpContents::get_SKU( /*[out, retval]*/ BSTR *pVal )
  795. {
  796. __HCP_BEGIN_PROPERTY_GET("CPCHRemoteHelpContents::get_SKU",hr,pVal);
  797. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_data.m_ths.GetSKU(), pVal ));
  798. __HCP_END_PROPERTY(hr);
  799. }
  800. STDMETHODIMP CPCHRemoteHelpContents::get_Language( /*[out, retval]*/ long *pVal )
  801. {
  802. __HCP_BEGIN_PROPERTY_GET2("CPCHRemoteHelpContents::get_Language",hr,pVal,m_data.m_ths.GetLanguage());
  803. __HCP_END_PROPERTY(hr);
  804. }
  805. STDMETHODIMP CPCHRemoteHelpContents::get_ListOfFiles( /*[out, retval]*/ VARIANT *pVal )
  806. {
  807. __HCP_FUNC_ENTRY( "CPCHRemoteHelpContents::get_ListOfFiles" );
  808. HRESULT hr;
  809. MPC::SmartLock<_ThreadModel> lock( this );
  810. MPC::WStringList lstFiles;
  811. __MPC_PARAMCHECK_BEGIN(hr)
  812. __MPC_PARAMCHECK_NOTNULL(pVal);
  813. __MPC_PARAMCHECK_END();
  814. __MPC_EXIT_IF_METHOD_FAILS(hr, AttachToDatabase());
  815. __MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.ListAllTheHelpFiles( lstFiles ));
  816. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertListToSafeArray( lstFiles, *pVal, VT_BSTR ));
  817. hr = S_OK;
  818. __HCP_FUNC_CLEANUP;
  819. DetachFromDatabase();
  820. __HCP_FUNC_EXIT(hr);
  821. }
  822. STDMETHODIMP CPCHRemoteHelpContents::GetDatabase( /*[out, retval]*/ IUnknown* *pVal )
  823. {
  824. __HCP_FUNC_ENTRY( "CPCHRemoteHelpContents::GetDatabase" );
  825. HRESULT hr;
  826. MPC::SmartLock<_ThreadModel> lock( this );
  827. CComPtr<IStream> stream;
  828. MPC::wstring strDataArchive;
  829. __MPC_PARAMCHECK_BEGIN(hr)
  830. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  831. __MPC_PARAMCHECK_END();
  832. {
  833. Taxonomy::LockingHandle handle;
  834. Taxonomy::InstalledInstanceIter it;
  835. bool fFound;
  836. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
  837. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_ts, fFound, it ));
  838. if(!fFound)
  839. {
  840. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  841. }
  842. __MPC_EXIT_IF_METHOD_FAILS(hr, it->m_inst.GetFileName( strDataArchive ));
  843. }
  844. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForRead( strDataArchive.c_str(), &stream ));
  845. *pVal = stream.Detach();
  846. hr = S_OK;
  847. __HCP_FUNC_CLEANUP;
  848. __HCP_FUNC_EXIT(hr);
  849. }
  850. STDMETHODIMP CPCHRemoteHelpContents::GetFile( /*[in]*/ BSTR bstrFileName, /*[out, retval]*/ IUnknown* *pVal )
  851. {
  852. __HCP_FUNC_ENTRY( "CPCHRemoteHelpContents::GetFile" );
  853. HRESULT hr;
  854. MPC::SmartLock<_ThreadModel> lock( this );
  855. MPC::wstring strHelpFile;
  856. MPC::wstring strFileName;
  857. CComPtr<IStream> stream;
  858. __MPC_PARAMCHECK_BEGIN(hr)
  859. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrFileName);
  860. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  861. __MPC_PARAMCHECK_END();
  862. //
  863. // Canonicalize bstrFileName.
  864. //
  865. if(FAILED(hr = MPC::GetCanonialPathName( strFileName, bstrFileName )))
  866. {
  867. __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  868. }
  869. strHelpFile = m_strDir;
  870. strHelpFile += strFileName;
  871. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForRead( strHelpFile.c_str(), &stream ));
  872. *pVal = stream.Detach();
  873. hr = S_OK;
  874. __HCP_FUNC_CLEANUP;
  875. __HCP_FUNC_EXIT(hr);
  876. }