Source code of Windows XP (NT5)
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.

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