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.

801 lines
22 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // password.cpp: implementation of the CPasswordPolicy class
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "password.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. #define KeyMinAge L"MinimumPasswordAge"
  12. #define KeyMaxAge L"MaximumPasswordAge"
  13. #define KeyMinLength L"MinimumPasswordLength"
  14. #define KeyHistory L"PasswordHistorySize"
  15. #define KeyComplexity L"PasswordComplexity"
  16. #define KeyClearText L"ClearTextPassword"
  17. #define KeyForceLogoff L"ForceLogoffWhenHourExpire"
  18. #define KeyEnableAdmin L"EnableAdminAccount"
  19. #define KeyEnableGuest L"EnableGuestAccount"
  20. #define KeyLSAAnonLookup L"LSAAnonymousNameLookup"
  21. /*
  22. Routine Description:
  23. Name:
  24. CPasswordPolicy::CPasswordPolicy
  25. Functionality:
  26. This is the constructor. Pass along the parameters to the base class
  27. Virtual:
  28. No (you know that, constructor won't be virtual!)
  29. Arguments:
  30. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  31. by the caller who constructs this instance.
  32. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  33. Passed along by the caller. Must not be NULL.
  34. pCtx - Pointer to WMI context object (COM interface). Passed along
  35. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  36. Return Value:
  37. None as any constructor
  38. Notes:
  39. if you create any local members, think about initialize them here
  40. */
  41. CPasswordPolicy::CPasswordPolicy (
  42. IN ISceKeyChain * pKeyChain,
  43. IN IWbemServices * pNamespace,
  44. IN IWbemContext * pCtx
  45. )
  46. :
  47. CGenericClass(pKeyChain, pNamespace, pCtx)
  48. {
  49. }
  50. /*
  51. Routine Description:
  52. Name:
  53. CPasswordPolicy::~CPasswordPolicy
  54. Functionality:
  55. Destructor. Necessary as good C++ discipline since we have virtual functions.
  56. Virtual:
  57. Yes.
  58. Arguments:
  59. none as any destructor
  60. Return Value:
  61. None as any destructor
  62. Notes:
  63. if you create any local members, think about whether
  64. there is any need for a non-trivial destructor
  65. */
  66. CPasswordPolicy::~CPasswordPolicy ()
  67. {
  68. }
  69. /*
  70. Routine Description:
  71. Name:
  72. CRGroups::CreateObject
  73. Functionality:
  74. Create WMI objects (Sce_PasswordPolicy). Depending on parameter atAction,
  75. this creation may mean:
  76. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  77. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  78. (c) Delete an instance (atAction == ACTIONTYPE_DELETE)
  79. Virtual:
  80. Yes.
  81. Arguments:
  82. pHandler - COM interface pointer for notifying WMI for creation result.
  83. atAction - Get single instance ACTIONTYPE_GET
  84. Get several instances ACTIONTYPE_QUERY
  85. Delete a single instance ACTIONTYPE_DELETE
  86. Return Value:
  87. Success: it must return success code (use SUCCEEDED to test). It is
  88. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  89. not directly passed back via parameters.
  90. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  91. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  92. situations, this may not be an error depending on caller's intention.
  93. Notes:
  94. */
  95. HRESULT
  96. CPasswordPolicy::CreateObject (
  97. IN IWbemObjectSink * pHandler,
  98. IN ACTIONTYPE atAction
  99. )
  100. {
  101. //
  102. // we know how to:
  103. // Get single instance ACTIONTYPE_GET
  104. // Delete a single instance ACTIONTYPE_DELETE
  105. // Get several instances ACTIONTYPE_QUERY
  106. //
  107. if ( ACTIONTYPE_GET != atAction &&
  108. ACTIONTYPE_DELETE != atAction &&
  109. ACTIONTYPE_QUERY != atAction )
  110. {
  111. return WBEM_E_NOT_SUPPORTED;
  112. }
  113. //
  114. // We must have the pStorePath property because that is where
  115. // our instance is stored.
  116. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  117. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  118. //
  119. CComVariant varStorePath;
  120. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  121. if (SUCCEEDED(hr) && hr != WBEM_S_FALSE && varStorePath.vt == VT_BSTR)
  122. {
  123. //
  124. // Prepare a store (for persistence) for this store path (file)
  125. //
  126. CSceStore SceStore;
  127. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  128. if ( SUCCEEDED(hr) )
  129. {
  130. //
  131. // make sure the store (just a file) really exists. The raw path
  132. // may contain env variables, so we need the expanded path
  133. //
  134. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  135. if ( dwAttrib != -1 )
  136. {
  137. if ( ACTIONTYPE_DELETE == atAction )
  138. {
  139. hr = DeleteInstance(pHandler, &SceStore);
  140. }
  141. else
  142. {
  143. hr = ConstructInstance(pHandler, &SceStore, varStorePath.bstrVal,atAction);
  144. }
  145. }
  146. else
  147. {
  148. hr = WBEM_E_NOT_FOUND;
  149. }
  150. }
  151. }
  152. return hr;
  153. }
  154. /*
  155. Routine Description:
  156. Name:
  157. CPasswordPolicy::PutInst
  158. Functionality:
  159. Put an instance as instructed by WMI. Since this class implements Sce_PasswordPolicy,
  160. which is persistence oriented, this will cause the Sce_PasswordPolicy object's property
  161. information to be saved in our store.
  162. Virtual:
  163. Yes.
  164. Arguments:
  165. pInst - COM interface pointer to the WMI class (Sce_PasswordPolicy) object.
  166. pHandler - COM interface pointer for notifying WMI of any events.
  167. pCtx - COM interface pointer. This interface is just something we pass around.
  168. WMI may mandate it (not now) in the future. But we never construct
  169. such an interface and so, we just pass around for various WMI API's
  170. Return Value:
  171. Success: it must return success code (use SUCCEEDED to test). It is
  172. not guaranteed to return WBEM_NO_ERROR.
  173. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  174. the instance.
  175. Notes:
  176. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  177. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  178. to test for the result of retrieving a property.
  179. */
  180. HRESULT
  181. CPasswordPolicy::PutInst (
  182. IN IWbemClassObject * pInst,
  183. IN IWbemObjectSink * pHandler,
  184. IN IWbemContext * pCtx
  185. )
  186. {
  187. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  188. //
  189. // These are all password policy's properties.
  190. // SCE_NO_VALUE means the property is not set.
  191. //
  192. DWORD dwMinAge = SCE_NO_VALUE;
  193. DWORD dwMaxAge = SCE_NO_VALUE;
  194. DWORD dwMinLen = SCE_NO_VALUE;
  195. DWORD dwHistory = SCE_NO_VALUE;
  196. DWORD dwComplexity = SCE_NO_VALUE;
  197. DWORD dwClear = SCE_NO_VALUE;
  198. DWORD dwForce = SCE_NO_VALUE;
  199. DWORD dwLSAPol = SCE_NO_VALUE;
  200. DWORD dwAdmin = SCE_NO_VALUE;
  201. DWORD dwGuest = SCE_NO_VALUE;
  202. //
  203. // CScePropertyMgr helps us to access WMI object's properties
  204. // create an instance and attach the WMI object to it.
  205. // This will always succeed.
  206. //
  207. CScePropertyMgr ScePropMgr;
  208. ScePropMgr.Attach(pInst);
  209. //
  210. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  211. // a "goto CleanUp;" with hr set to the return value from
  212. // the function (macro parameter)
  213. //
  214. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pMinAge, &dwMinAge));
  215. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pMaxAge, &dwMaxAge));
  216. //
  217. // check dependency
  218. //
  219. if ( dwMinAge != SCE_NO_VALUE && dwMaxAge != SCE_NO_VALUE )
  220. {
  221. if ( dwMinAge >= dwMaxAge )
  222. {
  223. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  224. }
  225. if ( dwMinAge > 999 || dwMaxAge > 999 )
  226. {
  227. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  228. }
  229. }
  230. else if (dwMinAge != SCE_NO_VALUE || dwMaxAge != SCE_NO_VALUE )
  231. {
  232. hr = WBEM_E_ILLEGAL_NULL;
  233. }
  234. if ( FAILED(hr) )
  235. {
  236. goto CleanUp;
  237. }
  238. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pMinLength, &dwMinLen));
  239. //
  240. // check validity of the minimum length property
  241. //
  242. if ( dwMinLen != SCE_NO_VALUE && dwMinLen > 14 )
  243. {
  244. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  245. goto CleanUp;
  246. }
  247. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pHistory, &dwHistory));
  248. //
  249. // check validity of the history property
  250. //
  251. if ( dwHistory != SCE_NO_VALUE && dwHistory > 24 )
  252. {
  253. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  254. goto CleanUp;
  255. }
  256. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pComplexity, &dwComplexity));
  257. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pStoreClearText, &dwClear));
  258. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pForceLogoff, &dwForce));
  259. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pLSAPol, &dwLSAPol));
  260. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pEnableAdmin, &dwAdmin));
  261. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pEnableGuest, &dwGuest));
  262. //
  263. // this set of braces allow us to define the store instance closer to where it is used
  264. //
  265. {
  266. //
  267. // Attach the WMI object instance to the store and let the store know that
  268. // it's store is given by the pStorePath property of the instance.
  269. //
  270. CSceStore SceStore;
  271. SceStore.SetPersistProperties(pInst, pStorePath);
  272. //
  273. // now save the info to file
  274. //
  275. hr = SaveSettingsToStore(&SceStore,
  276. dwMinAge,
  277. dwMaxAge,
  278. dwMinLen,
  279. dwHistory,
  280. dwComplexity,
  281. dwClear,
  282. dwForce,
  283. dwLSAPol,
  284. dwAdmin,
  285. dwGuest
  286. );
  287. }
  288. CleanUp:
  289. return hr;
  290. }
  291. /*
  292. Routine Description:
  293. Name:
  294. CRGroups::ConstructInstance
  295. Functionality:
  296. This is private function to create an instance of Sce_PasswordPolicy.
  297. Virtual:
  298. No.
  299. Arguments:
  300. pHandler - COM interface pointer for notifying WMI of any events.
  301. pSceStore - Pointer to our store. It must have been appropriately set up.
  302. wszLogStorePath - store path, a key property of Sce_PasswordPolicy class.
  303. atAction - whether it's querying or a single instance fetching.
  304. Return Value:
  305. Success: it must return success code (use SUCCEEDED to test). It is
  306. not guaranteed to return WBEM_NO_ERROR.
  307. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  308. Notes:
  309. */
  310. HRESULT
  311. CPasswordPolicy::ConstructInstance (
  312. IN IWbemObjectSink * pHandler,
  313. IN CSceStore * pSceStore,
  314. IN LPWSTR wszLogStorePath,
  315. IN ACTIONTYPE atAction
  316. )
  317. {
  318. //
  319. // make sure that we have a valid store
  320. //
  321. if ( pSceStore == NULL ||
  322. pSceStore->GetStoreType() < SCE_INF_FORMAT ||
  323. pSceStore->GetStoreType() > SCE_JET_ANALYSIS_REQUIRED )
  324. {
  325. return WBEM_E_INVALID_PARAMETER;
  326. }
  327. //
  328. // ask SCE to read a gigantic structure out from the store. Only SCE
  329. // knows now to release the memory. Don't just delete it! Use our CSceStore
  330. // to do the releasing (FreeSecurityProfileInfo)
  331. //
  332. PSCE_PROFILE_INFO pInfo=NULL;
  333. HRESULT hr = pSceStore->GetSecurityProfileInfo(
  334. AREA_SECURITY_POLICY,
  335. &pInfo,
  336. NULL
  337. );
  338. if (FAILED(hr))
  339. {
  340. return hr;
  341. }
  342. //
  343. // If one of the following properties are missing from the store,
  344. // we won't construct the wmi object for it.
  345. //
  346. if (pInfo->MinimumPasswordAge == SCE_NO_VALUE &&
  347. pInfo->MaximumPasswordAge == SCE_NO_VALUE &&
  348. pInfo->MinimumPasswordLength == SCE_NO_VALUE &&
  349. pInfo->PasswordHistorySize == SCE_NO_VALUE &&
  350. pInfo->PasswordComplexity == SCE_NO_VALUE &&
  351. pInfo->ClearTextPassword == SCE_NO_VALUE &&
  352. pInfo->ForceLogoffWhenHourExpire == SCE_NO_VALUE &&
  353. pInfo->LSAAnonymousNameLookup == SCE_NO_VALUE )
  354. {
  355. pSceStore->FreeSecurityProfileInfo(pInfo);
  356. return WBEM_E_NOT_FOUND;
  357. }
  358. CComBSTR bstrLogOut;
  359. LPCWSTR pszExpandedPath = pSceStore->GetExpandedPath();
  360. CComPtr<IWbemClassObject> srpObj;
  361. //
  362. // CScePropertyMgr helps us to access WMI object's properties.
  363. //
  364. CScePropertyMgr ScePropMgr;
  365. //
  366. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  367. // a "goto CleanUp;" with hr set to the return value from
  368. // the function (macro parameter)
  369. //
  370. if ( ACTIONTYPE_QUERY == atAction )
  371. {
  372. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut));
  373. pszExpandedPath = bstrLogOut;
  374. }
  375. SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj));
  376. //
  377. // attach the WMI object to the property mgr.
  378. // This will always succeed.
  379. //
  380. ScePropMgr.Attach(srpObj);
  381. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pStorePath, pszExpandedPath));
  382. if (pInfo->MinimumPasswordAge != SCE_NO_VALUE ) {
  383. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pMinAge, pInfo->MinimumPasswordAge));
  384. }
  385. if (pInfo->MaximumPasswordAge != SCE_NO_VALUE ) {
  386. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pMaxAge, pInfo->MaximumPasswordAge));
  387. }
  388. if (pInfo->MinimumPasswordLength != SCE_NO_VALUE ) {
  389. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pMinLength, pInfo->MinimumPasswordLength));
  390. }
  391. if (pInfo->PasswordHistorySize != SCE_NO_VALUE ) {
  392. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pHistory, pInfo->PasswordHistorySize));
  393. }
  394. if (pInfo->PasswordComplexity != SCE_NO_VALUE ) {
  395. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pComplexity, (pInfo->PasswordComplexity==1)? true : false));
  396. }
  397. if (pInfo->ClearTextPassword != SCE_NO_VALUE ) {
  398. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pStoreClearText, (pInfo->ClearTextPassword==1)? true : false));
  399. }
  400. if (pInfo->ForceLogoffWhenHourExpire != SCE_NO_VALUE ) {
  401. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pForceLogoff, (pInfo->ForceLogoffWhenHourExpire==1)? true : false));
  402. }
  403. if (pInfo->LSAAnonymousNameLookup != SCE_NO_VALUE ) {
  404. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pLSAPol, (pInfo->LSAAnonymousNameLookup==1)? true : false));
  405. }
  406. //
  407. // do the necessary gestures to WMI.
  408. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  409. // at this point. Consult WMI team for detail if you suspect problems with
  410. // the use of WBEM_STATUS_REQUIREMENTS
  411. //
  412. if ( ACTIONTYPE_QUERY == atAction ) {
  413. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_FALSE, NULL, NULL);
  414. } else {
  415. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_OK, NULL, NULL);
  416. }
  417. //
  418. // pass the new instance to WMI
  419. //
  420. hr = pHandler->Indicate(1, &srpObj);
  421. CleanUp:
  422. pSceStore->FreeSecurityProfileInfo(pInfo);
  423. return hr;
  424. }
  425. /*
  426. Routine Description:
  427. Name:
  428. CPasswordPolicy::DeleteInstance
  429. Functionality:
  430. remove an instance of Sce_PasswordPolicy from the specified store.
  431. Virtual:
  432. No.
  433. Arguments:
  434. pHandler - COM interface pointer for notifying WMI of any events.
  435. pSceStore - Pointer to our store. It must have been appropriately set up.
  436. Return Value:
  437. Success: WBEM_NO_ERROR.
  438. Failure: WBEM_E_INVALID_PARAMETER.
  439. Notes:
  440. */
  441. HRESULT
  442. CPasswordPolicy::DeleteInstance (
  443. IN IWbemObjectSink * pHandler,
  444. IN CSceStore * pSceStore
  445. )
  446. {
  447. //
  448. // make sure that we have a valid store
  449. //
  450. if ( pSceStore == NULL || pSceStore->GetStoreType() < SCE_INF_FORMAT ||
  451. pSceStore->GetStoreType() > SCE_JET_ANALYSIS_REQUIRED )
  452. {
  453. return WBEM_E_INVALID_PARAMETER;
  454. }
  455. HRESULT hr=WBEM_S_NO_ERROR;
  456. //
  457. // a SCE_NO_VALUE will cause that property to be delete by SaveSettingsToStore
  458. //
  459. hr = SaveSettingsToStore(pSceStore,
  460. SCE_NO_VALUE,
  461. SCE_NO_VALUE,
  462. SCE_NO_VALUE,
  463. SCE_NO_VALUE,
  464. SCE_NO_VALUE,
  465. SCE_NO_VALUE,
  466. SCE_NO_VALUE,
  467. SCE_NO_VALUE,
  468. SCE_NO_VALUE,
  469. SCE_NO_VALUE
  470. );
  471. return hr;
  472. }
  473. /*
  474. Routine Description:
  475. Name:
  476. CPasswordPolicy::SaveSettingsToStore
  477. Functionality:
  478. With all the properties of a Sce_PasswordPolicy, this function just saves
  479. the instance properties to our store.
  480. Virtual:
  481. No.
  482. Arguments:
  483. pSceStore - the store.
  484. dwMinAge - a corresponding key property of Sce_PasswordPolicy class.
  485. dwMaxAge - another corresponding property of the Sce_PasswordPolicy class.
  486. dwMinLen - another corresponding property of the Sce_PasswordPolicy class.
  487. dwHistory - another corresponding property of the Sce_PasswordPolicy class.
  488. dwComplexity, - another corresponding property of the Sce_PasswordPolicy class.
  489. dwClear - another corresponding property of the Sce_PasswordPolicy class.
  490. dwForce - another corresponding property of the Sce_PasswordPolicy class.
  491. dwLSAPol - another corresponding property of the Sce_PasswordPolicy class.
  492. dwAdmin - another corresponding property of the Sce_PasswordPolicy class.
  493. dwGuest - another corresponding property of the Sce_PasswordPolicy class.
  494. Return Value:
  495. Success: it must return success code (use SUCCEEDED to test). It is
  496. not guaranteed to return WBEM_NO_ERROR.
  497. Failure: Various errors may occurs. Any error indicates the failure to save the instance.
  498. Notes:
  499. */
  500. HRESULT
  501. CPasswordPolicy::SaveSettingsToStore (
  502. IN CSceStore * pSceStore,
  503. IN DWORD dwMinAge,
  504. IN DWORD dwMaxAge,
  505. IN DWORD dwMinLen,
  506. IN DWORD dwHistory,
  507. IN DWORD dwComplexity,
  508. IN DWORD dwClear,
  509. IN DWORD dwForce,
  510. IN DWORD dwLSAPol,
  511. IN DWORD dwAdmin,
  512. IN DWORD dwGuest
  513. )
  514. {
  515. //
  516. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  517. // a "goto CleanUp;" with hr set to the return value from
  518. // the function (macro parameter)
  519. //
  520. DWORD dwDump;
  521. //
  522. // For a new .inf file. Write an empty buffer to the file
  523. // will creates the file with right header/signature/unicode format
  524. // this is harmless for existing files.
  525. // For database store, this is a no-op.
  526. //
  527. HRESULT hr = WBEM_NO_ERROR;
  528. SCE_PROV_IfErrorGotoCleanup(pSceStore->WriteSecurityProfileInfo(AreaBogus,
  529. (PSCE_PROFILE_INFO)&dwDump,
  530. NULL, false));
  531. //
  532. // MinAge
  533. //
  534. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyMinAge, dwMinAge));
  535. //
  536. // MaxAge
  537. //
  538. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyMaxAge, dwMaxAge));
  539. //
  540. // MinLength
  541. //
  542. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyMinLength, dwMinLen));
  543. //
  544. // History
  545. //
  546. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyHistory, dwHistory));
  547. //
  548. // Complexity
  549. //
  550. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyComplexity, dwComplexity));
  551. //
  552. // Cleartext
  553. //
  554. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyClearText, dwClear));
  555. //
  556. // Force logoff
  557. //
  558. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyForceLogoff, dwForce));
  559. //
  560. // LSA Anonymous Lookup
  561. //
  562. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyLSAAnonLookup, dwLSAPol));
  563. //
  564. // disable admin
  565. //
  566. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyEnableAdmin, dwAdmin));
  567. //
  568. // disable guest
  569. //
  570. SCE_PROV_IfErrorGotoCleanup(pSceStore->SavePropertyToStore(szSystemAccess, KeyEnableGuest, dwGuest));
  571. CleanUp:
  572. return hr;
  573. }