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.

692 lines
21 KiB

  1. // AccessChecker.cpp : Implementation of CAccessChecker
  2. #include "stdafx.h"
  3. #include "WorkObj.h"
  4. #include "Checker.h"
  5. #include <lm.h>
  6. #include <dsgetdc.h>
  7. #include <iads.h>
  8. #include <comdef.h>
  9. //#include <adshlp.h>
  10. #include "treg.hpp"
  11. #include "BkupRstr.hpp"
  12. #include "UString.hpp"
  13. #include "EaLen.hpp"
  14. #include "IsAdmin.hpp"
  15. #include <ntsecapi.h>
  16. #include <winerror.h>
  17. #include "sidflags.h"
  18. #include "rebootU.h"
  19. #include "ResStr.h"
  20. #include "Win2KErr.h"
  21. //#import "\bin\NetEnum.tlb" no_namespace
  22. #import "NetEnum.tlb" no_namespace
  23. // Win2k function
  24. typedef HRESULT (CALLBACK * DSGETDCNAME)(LPWSTR, LPWSTR, GUID*, LPWSTR, DWORD, PDOMAIN_CONTROLLER_INFO*);
  25. typedef HRESULT (CALLBACK * ADSGETOBJECT)(LPWSTR, REFIID, void**);
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CAccessChecker
  28. STDMETHODIMP CAccessChecker::IsAdmin(BSTR user, BSTR server, BOOL * pbIsAdmin)
  29. {
  30. HRESULT hr = 0;
  31. // initialize output variable
  32. (*pbIsAdmin) = FALSE;
  33. if ( ! user || ! *user )
  34. {
  35. // check the currently logged in account
  36. // if ( ! server || ! *server )
  37. // {
  38. // hr = IsAdminLocal();
  39. // }
  40. // else
  41. // {
  42. // hr = IsAdminRemote((WCHAR*)server);
  43. // }
  44. // removing explicit administrator check
  45. hr = S_OK;
  46. if ( hr == ERROR_SUCCESS )
  47. {
  48. (*pbIsAdmin) = TRUE;
  49. }
  50. else if ( hr == ERROR_ACCESS_DENIED )
  51. {
  52. (*pbIsAdmin) = FALSE;
  53. hr = S_OK;
  54. }
  55. else
  56. {
  57. hr = HRESULT_FROM_WIN32(hr);
  58. }
  59. }
  60. else
  61. {
  62. hr = E_NOTIMPL;
  63. }
  64. return hr;
  65. }
  66. STDMETHODIMP CAccessChecker::GetOsVersion(BSTR server, DWORD * pdwVerMaj, DWORD * pdwVerMin, DWORD * pdwVerSP)
  67. {
  68. // This function looksup the OS version on the server specified and returns it.
  69. // CAUTION : This function always returns 0 for the ServicePack.
  70. WKSTA_INFO_100 * pInfo;
  71. long rc = NetWkstaGetInfo(server,100,(LPBYTE*)&pInfo);
  72. if ( ! rc )
  73. {
  74. *pdwVerMaj = pInfo->wki100_ver_major;
  75. *pdwVerMin = pInfo->wki100_ver_minor;
  76. *pdwVerSP = 0;
  77. NetApiBufferFree(pInfo);
  78. }
  79. else
  80. return HRESULT_FROM_WIN32(rc);
  81. return S_OK;
  82. }
  83. STDMETHODIMP CAccessChecker::IsNativeMode(BSTR Domain, BOOL * pbIsNativeMode)
  84. {
  85. ADSGETOBJECT ADsGetObject;
  86. HMODULE hMod = LoadLibrary(L"activeds.dll");
  87. if ( hMod == NULL )
  88. {
  89. return HRESULT_FROM_WIN32(GetLastError());
  90. }
  91. ADsGetObject = (ADSGETOBJECT)GetProcAddress(hMod, "ADsGetObject");
  92. if (!ADsGetObject)
  93. return HRESULT_FROM_WIN32(GetLastError());
  94. IADs * pDomain;
  95. HRESULT hr;
  96. VARIANT var;
  97. _bstr_t sDom( L"LDAP://" );
  98. sDom += Domain;
  99. hr = ADsGetObject(sDom, IID_IADs, (void **) &pDomain);
  100. if (SUCCEEDED(hr))
  101. {
  102. VariantClear(&var);
  103. //Get the ntMixedDomain attribute
  104. hr = pDomain->Get(L"ntMixedDomain", &var);
  105. if (SUCCEEDED(hr))
  106. {
  107. hr = E_FAIL;
  108. //Type should be VT_I4.
  109. if (var.vt==VT_I4)
  110. {
  111. //Zero means native mode.
  112. if (var.lVal == 0)
  113. {
  114. hr = S_OK;
  115. *pbIsNativeMode = true;
  116. }
  117. //One means mixed mode.
  118. else if(var.lVal == 1)
  119. {
  120. hr = S_OK;
  121. *pbIsNativeMode = false;
  122. }
  123. }
  124. }
  125. VariantClear(&var);
  126. pDomain->Release();
  127. }
  128. return hr;
  129. }
  130. STDMETHODIMP CAccessChecker::CanUseAddSidHistory(BSTR srcDomain, BSTR tgtDomain, long * pbCanUseIt)
  131. {
  132. DOMAIN_CONTROLLER_INFO * pSrcDomCtrlInfo = NULL;
  133. DOMAIN_CONTROLLER_INFO * pTgtDomCtrlInfo = NULL;
  134. DWORD rc = 0; // OS return code
  135. WKSTA_INFO_100 * pInfo = NULL;
  136. TRegKey sysKey, regComputer;
  137. DWORD rval;
  138. BSTR bstrSourceMachine = NULL;
  139. BSTR bstrTargetMachine = NULL;
  140. // initialize the return FieldMask
  141. * pbCanUseIt = F_WORKS;
  142. // Load DsGetDcName dynamically
  143. DSGETDCNAME DsGetDcName;
  144. HMODULE hPro = LoadLibrary(L"NetApi32.dll");
  145. DsGetDcName = (DSGETDCNAME)GetProcAddress(hPro, "DsGetDcNameW");
  146. if (DsGetDcName == NULL)
  147. {
  148. return HRESULT_FROM_WIN32(GetLastError());
  149. }
  150. rc = DsGetDcName(
  151. NULL ,// LPCTSTR ComputerName ?
  152. srcDomain ,// LPCTSTR DomainName
  153. NULL ,// GUID *DomainGuid ?
  154. NULL ,// LPCTSTR SiteName ?
  155. DS_PDC_REQUIRED ,// ULONG Flags ?
  156. &pSrcDomCtrlInfo // PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  157. );
  158. if( rc != NO_ERROR ) goto ret_exit;
  159. rc = DsGetDcName(
  160. NULL ,// LPCTSTR ComputerName ?
  161. tgtDomain ,// LPCTSTR DomainName
  162. NULL ,// GUID *DomainGuid ?
  163. NULL ,// LPCTSTR SiteName ?
  164. 0 ,// ULONG Flags ?
  165. &pTgtDomCtrlInfo // PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  166. );
  167. if( rc != NO_ERROR ) goto ret_exit;
  168. bstrSourceMachine = ::SysAllocString( pSrcDomCtrlInfo->DomainControllerName );
  169. bstrTargetMachine = ::SysAllocString( pTgtDomCtrlInfo->DomainControllerName );
  170. if (GetBkupRstrPriv(bstrSourceMachine))
  171. {
  172. rc = regComputer.Connect( HKEY_LOCAL_MACHINE, bstrSourceMachine );
  173. }
  174. else
  175. {
  176. rc = GetLastError();
  177. }
  178. // Check if the target domain is a Win2k native mode domain.
  179. if ( !rc )
  180. {
  181. rc = NetWkstaGetInfo(bstrTargetMachine,100,(LPBYTE*)&pInfo);
  182. if ( ! rc )
  183. {
  184. if ( pInfo->wki100_ver_major < 5 )
  185. {
  186. // cannot add Sid history to non Win2k Domains
  187. *pbCanUseIt |= F_WRONGOS;
  188. }
  189. else{
  190. BOOL isNative = false;
  191. if(SUCCEEDED(IsNativeMode( _bstr_t(pInfo->wki100_langroup), &isNative))){
  192. if( isNative == false ) *pbCanUseIt |= F_WRONGOS;
  193. }
  194. }
  195. }
  196. else
  197. {
  198. rc = GetLastError();
  199. }
  200. // Check the registry to see if the TcpipClientSupport key is there
  201. if ( ! rc )
  202. {
  203. rc = sysKey.OpenRead(L"System\\CurrentControlSet\\Control\\Lsa",&regComputer);
  204. }
  205. if ( ! rc )
  206. {
  207. rc = sysKey.ValueGetDWORD(L"TcpipClientSupport",&rval);
  208. if ( !rc )
  209. {
  210. if ( rval != 1 )
  211. {
  212. *pbCanUseIt |= F_NO_REG_KEY;
  213. }
  214. }
  215. else
  216. {
  217. // DWORD value not found
  218. *pbCanUseIt |= F_NO_REG_KEY;
  219. rc = 0;
  220. }
  221. }
  222. }
  223. if ( !rc )
  224. {
  225. // Check auditing on the source domain.
  226. rc = DetectAuditing(bstrSourceMachine);
  227. if ( rc == -1 )
  228. {
  229. rc = 0;
  230. *pbCanUseIt |= F_NO_AUDITING_SOURCE;
  231. }
  232. }
  233. if ( !rc )
  234. {
  235. // Check auditing on the target domain.
  236. rc = DetectAuditing(bstrTargetMachine);
  237. if ( rc == -1 )
  238. {
  239. rc = 0;
  240. *pbCanUseIt |= F_NO_AUDITING_TARGET;
  241. }
  242. }
  243. if (!rc )
  244. {
  245. LOCALGROUP_INFO_0 * pInfo = NULL;
  246. WCHAR groupName[LEN_Account];
  247. wsprintf(groupName,L"%ls$$$",(WCHAR*)srcDomain);
  248. rc = NetLocalGroupGetInfo(bstrSourceMachine,groupName,0,(BYTE**)&pInfo);
  249. if ( rc == NERR_GroupNotFound )
  250. {
  251. rc = 0;
  252. *pbCanUseIt |= F_NO_LOCAL_GROUP;
  253. }
  254. else
  255. {
  256. NetApiBufferFree(pInfo);
  257. }
  258. }
  259. ret_exit:
  260. if ( pInfo ) NetApiBufferFree(pInfo);
  261. if ( pSrcDomCtrlInfo ) NetApiBufferFree( pSrcDomCtrlInfo );
  262. if ( pTgtDomCtrlInfo ) NetApiBufferFree( pTgtDomCtrlInfo );
  263. if ( bstrSourceMachine ) ::SysFreeString(bstrSourceMachine);
  264. if ( bstrTargetMachine ) ::SysFreeString(bstrTargetMachine);
  265. return HRESULT_FROM_WIN32(rc);
  266. }
  267. //------------------------------------------------------------------------------------------
  268. // AddLocalGroup : Given the source domain, and source domain controller names, this
  269. // function creates the local group SOURCEDOMAIN$$$ in the source domain.
  270. // This local group must exist in the source domain for the DsAddSidHistory
  271. // API to work.
  272. //
  273. //------------------------------------------------------------------------------------------
  274. STDMETHODIMP CAccessChecker::AddLocalGroup(BSTR srcDomain, BSTR sourceDC)
  275. {
  276. DWORD rc = 0;
  277. LOCALGROUP_INFO_1 groupInfo;
  278. WCHAR name[LEN_Account];
  279. WCHAR comment[LEN_Account];
  280. DWORD parmErr;
  281. swprintf(name,L"%ls$$$",(WCHAR*)srcDomain);
  282. groupInfo.lgrpi1_name = name;
  283. wcscpy(comment, (WCHAR*)GET_BSTR(IDS_DOM_LOC_GRP_COMMENT));
  284. groupInfo.lgrpi1_comment = comment;
  285. rc = NetLocalGroupAdd(sourceDC,1,(LPBYTE)&groupInfo,&parmErr);
  286. return HRESULT_FROM_WIN32(rc);
  287. }
  288. //------------------------------------------------------------------------------------------
  289. // IsInSameForest : Given the source and the target domains this function tells us if
  290. // both the domains are in the same forest. This function enumerates all
  291. // the domains in the Forest of the source domain and compares them to
  292. // the target domain name. If there is a match then we know we are in same
  293. // forest.
  294. //------------------------------------------------------------------------------------------
  295. STDMETHODIMP CAccessChecker::IsInSameForest(BSTR srcDomain, BSTR tgtDomain, BOOL * pbIsSame)
  296. {
  297. // Initialize the return value
  298. *pbIsSame = FALSE;
  299. // Load the ADSI function dynamically
  300. ADSGETOBJECT ADsGetObject;
  301. HMODULE hMod = LoadLibrary(L"activeds.dll");
  302. if ( hMod == NULL )
  303. {
  304. return HRESULT_FROM_WIN32(GetLastError());
  305. }
  306. ADsGetObject = (ADSGETOBJECT)GetProcAddress(hMod, "ADsGetObject");
  307. if (!ADsGetObject)
  308. return HRESULT_FROM_WIN32(GetLastError());
  309. // we are going to look up the Schema naming context of both domains.
  310. // if they are the same then these two domains are in same forest.
  311. IADs * pAds = NULL;
  312. HRESULT hr = S_OK;
  313. WCHAR sPath[LEN_Path];
  314. _variant_t var;
  315. _bstr_t srcSchema, tgtSchema;
  316. // Get the schemaNamingContext for the source domain.
  317. wsprintf(sPath, L"LDAP://%s/rootDSE", (WCHAR*) srcDomain);
  318. hr = ADsGetObject(sPath, IID_IADs, (void**) &pAds);
  319. if ( SUCCEEDED(hr) )
  320. hr = pAds->Get(L"schemaNamingContext", &var);
  321. if ( SUCCEEDED(hr) )
  322. srcSchema = var;
  323. else
  324. srcSchema = L"";
  325. if ( pAds )
  326. {
  327. pAds->Release();
  328. pAds = NULL;
  329. }
  330. if (SUCCEEDED(hr))
  331. {
  332. // Now do the same for the target domain.
  333. wsprintf(sPath, L"LDAP://%s/rootDSE", (WCHAR*) tgtDomain);
  334. hr = ADsGetObject(sPath, IID_IADs, (void**) &pAds);
  335. if ( SUCCEEDED(hr) )
  336. hr = pAds->Get(L"schemaNamingContext", &var);
  337. if ( SUCCEEDED(hr) )
  338. tgtSchema = var;
  339. else
  340. {
  341. if ( hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN) )
  342. {
  343. // for NT 4 domains, we always get this error
  344. DOMAIN_CONTROLLER_INFO * pDomCtrl;
  345. DSGETDCNAME DsGetDcName;
  346. HMODULE hPro = LoadLibrary(L"NetApi32.dll");
  347. DWORD rc;
  348. DsGetDcName = (DSGETDCNAME)GetProcAddress(hPro, "DsGetDcNameW");
  349. if ( DsGetDcName )
  350. {
  351. rc = DsGetDcName(
  352. NULL ,// LPCTSTR ComputerName ?
  353. tgtDomain ,// LPCTSTR DomainName
  354. NULL ,// GUID *DomainGuid ?
  355. NULL ,// LPCTSTR SiteName ?
  356. 0 ,// ULONG Flags ?
  357. &pDomCtrl // PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  358. );
  359. if ( ! rc )
  360. {
  361. WKSTA_INFO_100 * pInfo = NULL;
  362. WCHAR server[100];
  363. UStrCpy(server,pDomCtrl->DomainControllerName);
  364. rc = NetWkstaGetInfo(server,100,(LPBYTE*)&pInfo);
  365. if ( ! rc )
  366. {
  367. if ( pInfo->wki100_ver_major < 5 )
  368. {
  369. (*pbIsSame) = FALSE;
  370. hr = 0;
  371. }
  372. NetApiBufferFree(pInfo);
  373. }
  374. else
  375. hr = HRESULT_FROM_WIN32(rc); // the return code from NetWkstaGetInfo may be more descriptive
  376. NetApiBufferFree(pDomCtrl);
  377. }
  378. }
  379. if ( hPro )
  380. FreeLibrary(hPro);
  381. }
  382. tgtSchema = L"";
  383. }
  384. if ( pAds )
  385. {
  386. pAds->Release();
  387. pAds = NULL;
  388. }
  389. *pbIsSame = (srcSchema == tgtSchema);
  390. }
  391. else
  392. {
  393. if ( hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN) )
  394. {
  395. // for NT 4 domains, we always get this error
  396. DOMAIN_CONTROLLER_INFO * pDomCtrl;
  397. DSGETDCNAME DsGetDcName;
  398. HMODULE hPro = LoadLibrary(L"NetApi32.dll");
  399. DWORD rc;
  400. DsGetDcName = (DSGETDCNAME)GetProcAddress(hPro, "DsGetDcNameW");
  401. if ( DsGetDcName )
  402. {
  403. rc = DsGetDcName(
  404. NULL ,// LPCTSTR ComputerName ?
  405. srcDomain ,// LPCTSTR DomainName
  406. NULL ,// GUID *DomainGuid ?
  407. NULL ,// LPCTSTR SiteName ?
  408. 0 ,// ULONG Flags ?
  409. &pDomCtrl // PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  410. );
  411. if ( ! rc )
  412. {
  413. WKSTA_INFO_100 * pInfo = NULL;
  414. WCHAR server[100];
  415. UStrCpy(server,pDomCtrl->DomainControllerName);
  416. rc = NetWkstaGetInfo(server,100,(LPBYTE*)&pInfo);
  417. if ( ! rc )
  418. {
  419. if ( pInfo->wki100_ver_major < 5 )
  420. {
  421. (*pbIsSame) = FALSE;
  422. hr = 0;
  423. }
  424. NetApiBufferFree(pInfo);
  425. }
  426. else
  427. hr = HRESULT_FROM_WIN32(rc); // the return code from NetWkstaGetInfo may be more descriptive
  428. NetApiBufferFree(pDomCtrl);
  429. }
  430. }
  431. if ( hPro )
  432. FreeLibrary(hPro);
  433. }
  434. }
  435. if ( hMod )
  436. FreeLibrary(hMod);
  437. return hr;
  438. }
  439. STDMETHODIMP
  440. CAccessChecker::GetPasswordPolicy(
  441. BSTR domain, /*[out]*/
  442. LONG * dwPasswordLength /*[out]*/
  443. )
  444. {
  445. HRESULT hr = S_OK;
  446. // initialize output parameter
  447. (*dwPasswordLength) = 0;
  448. ADSGETOBJECT ADsGetObject;
  449. HMODULE hMod = LoadLibrary(L"activeds.dll");
  450. if ( hMod == NULL )
  451. {
  452. return HRESULT_FROM_WIN32(GetLastError());
  453. }
  454. ADsGetObject = (ADSGETOBJECT)GetProcAddress(hMod, "ADsGetObject");
  455. if (!ADsGetObject)
  456. return HRESULT_FROM_WIN32(GetLastError());
  457. IADsDomain * pDomain;
  458. _bstr_t sDom( L"WinNT://" );
  459. sDom += domain;
  460. hr = ADsGetObject(sDom, IID_IADsDomain, (void **) &pDomain);
  461. if (SUCCEEDED(hr))
  462. {
  463. //Get the ntMixedDomain attribute
  464. hr = pDomain->get_MinPasswordLength(dwPasswordLength);
  465. pDomain->Release();
  466. }
  467. return hr;
  468. }
  469. STDMETHODIMP CAccessChecker::EnableAuditing(BSTR sDC)
  470. {
  471. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  472. DWORD wszStringLength;
  473. LSA_UNICODE_STRING lsaszServer;
  474. NTSTATUS ntsResult;
  475. LSA_HANDLE hPolicy;
  476. long rc = 0;
  477. // Object attributes are reserved, so initalize to zeroes.
  478. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  479. //Initialize an LSA_UNICODE_STRING structure to the server name.
  480. wszStringLength = wcslen((WCHAR*)sDC);
  481. lsaszServer.Buffer = (WCHAR*)sDC;
  482. lsaszServer.Length = (USHORT)wszStringLength * sizeof(WCHAR);
  483. lsaszServer.MaximumLength=(USHORT)wszStringLength * sizeof(WCHAR);
  484. // Attempt to open the policy.
  485. ntsResult = LsaOpenPolicy(
  486. &lsaszServer,
  487. &ObjectAttributes,
  488. POLICY_VIEW_AUDIT_INFORMATION | POLICY_VIEW_LOCAL_INFORMATION | POLICY_SET_AUDIT_REQUIREMENTS ,
  489. &hPolicy //recieves the policy handle
  490. );
  491. if ( !ntsResult )
  492. {
  493. // Ask for audit policy information
  494. PPOLICY_AUDIT_EVENTS_INFO info;
  495. ntsResult = LsaQueryInformationPolicy(hPolicy, PolicyAuditEventsInformation, (PVOID *)&info);
  496. if ( !ntsResult )
  497. {
  498. // turn on the audit mode.
  499. info->AuditingMode = TRUE;
  500. // turn on the success/failure for the Account management events
  501. info->EventAuditingOptions[AuditCategoryAccountManagement] = POLICY_AUDIT_EVENT_SUCCESS | POLICY_AUDIT_EVENT_FAILURE;
  502. ntsResult = LsaSetInformationPolicy(hPolicy, PolicyAuditEventsInformation, (PVOID) info);
  503. if ( ntsResult )
  504. rc = LsaNtStatusToWinError(ntsResult);
  505. // be a good boy and cleanup after yourself.
  506. LsaFreeMemory((PVOID) info);
  507. }
  508. else
  509. rc = LsaNtStatusToWinError(ntsResult);
  510. //Freeing the policy object handle
  511. ntsResult = LsaClose(hPolicy);
  512. }
  513. else
  514. rc = LsaNtStatusToWinError(ntsResult);
  515. // long rc = LsaNtStatusToWinError(ntsResult);
  516. return HRESULT_FROM_WIN32(rc);
  517. }
  518. long CAccessChecker::DetectAuditing(BSTR sDC)
  519. {
  520. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  521. DWORD wszStringLength;
  522. LSA_UNICODE_STRING lsaszServer;
  523. NTSTATUS ntsResult;
  524. LSA_HANDLE hPolicy;
  525. long rc = 0;
  526. // Object attributes are reserved, so initalize to zeroes.
  527. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  528. //Initialize an LSA_UNICODE_STRING structure to the server name.
  529. wszStringLength = wcslen((WCHAR*)sDC);
  530. lsaszServer.Buffer = (WCHAR*)sDC;
  531. lsaszServer.Length = (USHORT)wszStringLength * sizeof(WCHAR);
  532. lsaszServer.MaximumLength=(USHORT)wszStringLength * sizeof(WCHAR);
  533. // Attempt to open the policy.
  534. ntsResult = LsaOpenPolicy(
  535. &lsaszServer,
  536. &ObjectAttributes,
  537. POLICY_VIEW_AUDIT_INFORMATION | POLICY_VIEW_LOCAL_INFORMATION,
  538. &hPolicy //recieves the policy handle
  539. );
  540. if ( !ntsResult )
  541. {
  542. // Ask for audit policy information
  543. PPOLICY_AUDIT_EVENTS_INFO info;
  544. ntsResult = LsaQueryInformationPolicy(hPolicy, PolicyAuditEventsInformation, (PVOID *)&info);
  545. if ( !ntsResult )
  546. {
  547. // check if the over all auditing is turned on
  548. if (!info->AuditingMode)
  549. rc = -1;
  550. // Check if the account management event auditing is on
  551. if (info->EventAuditingOptions[AuditCategoryAccountManagement] != (POLICY_AUDIT_EVENT_SUCCESS | POLICY_AUDIT_EVENT_FAILURE))
  552. rc = -1;
  553. LsaFreeMemory((PVOID) info);
  554. }
  555. else
  556. rc = LsaNtStatusToWinError(ntsResult);
  557. //Freeing the policy object handle
  558. ntsResult = LsaClose(hPolicy);
  559. }
  560. else
  561. rc = LsaNtStatusToWinError(ntsResult);
  562. return rc;
  563. }
  564. STDMETHODIMP CAccessChecker::AddRegKey(BSTR srcDc,LONG bReboot)
  565. {
  566. // This function will add the necessary registry key and then reboot the
  567. // PDC for a given domain
  568. TRegKey sysKey, regComputer;
  569. DOMAIN_CONTROLLER_INFO * pSrcDomCtrlInfo = NULL;
  570. DWORD rc = 0; // OS return code
  571. // BSTR bstrSourceMachine = NULL;
  572. _bstr_t sDC;
  573. if (GetBkupRstrPriv(srcDc))
  574. {
  575. rc = regComputer.Connect( HKEY_LOCAL_MACHINE, (WCHAR*)srcDc );
  576. }
  577. else
  578. {
  579. rc = GetLastError();
  580. }
  581. // Add the TcpipClientSupport DWORD value
  582. if ( ! rc )
  583. {
  584. rc = sysKey.Open(L"System\\CurrentControlSet\\Control\\Lsa",&regComputer);
  585. }
  586. if ( ! rc )
  587. {
  588. rc = sysKey.ValueSetDWORD(L"TcpipClientSupport",1);
  589. }
  590. if ( !rc && bReboot)
  591. {
  592. // Computer will shutdown and restart in 10 seconds.
  593. rc = ComputerShutDown((WCHAR*) srcDc, GET_STRING(IDS_RegKeyRebootMessage), 10, TRUE, FALSE);
  594. }
  595. if ( pSrcDomCtrlInfo ) NetApiBufferFree(pSrcDomCtrlInfo);
  596. return HRESULT_FROM_WIN32(rc);
  597. }