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.

1405 lines
40 KiB

  1. #include "stdafx.h"
  2. #include "hydraoc.h"
  3. #include "subcomp.h"
  4. #include "secupgrd.h"
  5. #include "lscsp.h"
  6. #include <SHlWapi.h>
  7. #include "reglic.h"
  8. #include "cryptkey.h"
  9. #define MSLICENSING_REG_KEY _T("SOFTWARE\\Microsoft\\MSLicensing")
  10. typedef DWORD (*PSETENTRIESINACL)(
  11. ULONG cCountOfExplicitEntries, // number of entries
  12. PEXPLICIT_ACCESS pListOfExplicitEntries, // buffer
  13. PACL OldAcl, // original ACL
  14. PACL *NewAcl // new ACL
  15. );
  16. BOOL
  17. AddACLToObjectSecurityDescriptor(
  18. HANDLE hObject,
  19. SE_OBJECT_TYPE ObjectType
  20. )
  21. {
  22. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  23. SID_IDENTIFIER_AUTHORITY CreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  24. PSID pAdminSid = NULL;
  25. PSID pSystemSid = NULL;
  26. PSID pPowerUsersSid = NULL;
  27. PSID pCreatorSid = NULL;
  28. PSID pUsersSid = NULL;
  29. PACL pNewDACL;
  30. DWORD dwError;
  31. BOOL bSuccess;
  32. DWORD i;
  33. PALLOCATEANDINITIALIZESID_FN pAllocateAndInitializeSid = NULL;
  34. PSETENTRIESINACL pSetEntriesInAcl = NULL;
  35. HMODULE pAdvApi32 = NULL;
  36. PFREESID_FN pFreeSid = NULL;
  37. PSETSECURITYINFO_FN pSetSecurityInfo;
  38. pAdvApi32 = LoadLibrary(ADVAPI_32_DLL);
  39. if (!pAdvApi32) {
  40. return(FALSE);
  41. }
  42. pAllocateAndInitializeSid = (PALLOCATEANDINITIALIZESID_FN)
  43. GetProcAddress(pAdvApi32,
  44. ALLOCATE_AND_INITITIALIZE_SID);
  45. if (pAllocateAndInitializeSid == NULL)
  46. {
  47. goto ErrorCleanup;
  48. }
  49. #ifdef UNICODE
  50. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>(GetProcAddress( pAdvApi32, "SetEntriesInAclW" ));
  51. #else
  52. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>(GetProcAddress( pAdvApi32, "SetEntriesInAclA" ));
  53. #endif
  54. if (!pSetEntriesInAcl) {
  55. FreeLibrary( pAdvApi32 );
  56. return(FALSE);
  57. }
  58. EXPLICIT_ACCESS ExplicitAccess[5];
  59. //
  60. // Create SIDs - Admins and System
  61. //
  62. bSuccess = pAllocateAndInitializeSid( &NtAuthority,
  63. 2,
  64. SECURITY_BUILTIN_DOMAIN_RID,
  65. DOMAIN_ALIAS_RID_ADMINS,
  66. 0, 0, 0, 0, 0, 0,
  67. &pAdminSid);
  68. bSuccess = bSuccess && pAllocateAndInitializeSid( &NtAuthority,
  69. 1,
  70. SECURITY_LOCAL_SYSTEM_RID,
  71. 0, 0, 0, 0, 0, 0, 0,
  72. &pSystemSid);
  73. bSuccess = bSuccess && pAllocateAndInitializeSid( &NtAuthority,
  74. 2,
  75. SECURITY_BUILTIN_DOMAIN_RID,
  76. DOMAIN_ALIAS_RID_POWER_USERS,
  77. 0, 0, 0, 0, 0, 0,
  78. &pPowerUsersSid);
  79. bSuccess = bSuccess && pAllocateAndInitializeSid( &CreatorAuthority,
  80. 1,
  81. SECURITY_CREATOR_OWNER_RID,
  82. 0, 0, 0, 0, 0, 0, 0,
  83. &pCreatorSid);
  84. bSuccess = bSuccess && pAllocateAndInitializeSid(&NtAuthority,
  85. 2,
  86. SECURITY_BUILTIN_DOMAIN_RID,
  87. DOMAIN_ALIAS_RID_USERS,
  88. 0, 0, 0, 0, 0, 0,
  89. &pUsersSid);
  90. if (bSuccess) {
  91. //
  92. // Initialize Access structures describing the ACEs we want:
  93. // System Full Control
  94. // Admins Full Control
  95. //
  96. // We'll take advantage of the fact that the unlocked private keys is
  97. // the same as the device parameters key and they are a superset of the
  98. // locked private keys.
  99. //
  100. // When we create the DACL for the private key we'll specify a subset of
  101. // the ExplicitAccess array.
  102. //
  103. for (i = 0; i < 5; i++) {
  104. ExplicitAccess[i].grfAccessMode = SET_ACCESS;
  105. ExplicitAccess[i].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  106. ExplicitAccess[i].Trustee.pMultipleTrustee = NULL;
  107. ExplicitAccess[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  108. ExplicitAccess[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  109. ExplicitAccess[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  110. }
  111. ExplicitAccess[0].grfAccessPermissions = KEY_ALL_ACCESS;
  112. ExplicitAccess[0].Trustee.ptstrName = (LPTSTR)pAdminSid;
  113. ExplicitAccess[1].grfAccessPermissions = KEY_ALL_ACCESS;
  114. ExplicitAccess[1].Trustee.ptstrName = (LPTSTR)pSystemSid;
  115. ExplicitAccess[2].grfAccessPermissions = KEY_ALL_ACCESS;
  116. ExplicitAccess[2].Trustee.ptstrName = (LPTSTR)pCreatorSid;
  117. ExplicitAccess[3].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
  118. ExplicitAccess[3].Trustee.ptstrName = (LPTSTR)pPowerUsersSid;
  119. ExplicitAccess[4].grfAccessPermissions = GENERIC_READ;
  120. ExplicitAccess[4].Trustee.ptstrName = (LPTSTR)pUsersSid;
  121. dwError = (DWORD)pSetEntriesInAcl( 5,
  122. ExplicitAccess,
  123. NULL,
  124. &pNewDACL );
  125. pSetSecurityInfo = (PSETSECURITYINFO_FN)GetProcAddress(pAdvApi32,SET_SECURITY_INFO);
  126. if (pSetSecurityInfo == NULL)
  127. {
  128. OutputDebugString(_T("AddSidToObjectsSecurityDescriptor: Can't get proc SetSecurityInfo"));
  129. goto ErrorCleanup;
  130. }
  131. dwError = pSetSecurityInfo(
  132. hObject,
  133. ObjectType,
  134. DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
  135. NULL,
  136. NULL,
  137. pNewDACL,
  138. NULL
  139. );
  140. }
  141. ErrorCleanup:
  142. pFreeSid = (PFREESID_FN)
  143. GetProcAddress(pAdvApi32,
  144. FREE_SID);
  145. if(pAdminSid)
  146. pFreeSid(pAdminSid);
  147. if(pSystemSid)
  148. pFreeSid(pSystemSid);
  149. if(pPowerUsersSid)
  150. pFreeSid(pPowerUsersSid);
  151. if(pCreatorSid)
  152. pFreeSid(pCreatorSid);
  153. if(pUsersSid)
  154. pFreeSid(pUsersSid);
  155. if(pNewDACL)
  156. LocalFree(pNewDACL);
  157. if(pAdvApi32)
  158. FreeLibrary( pAdvApi32 );
  159. return bSuccess;
  160. }
  161. BOOL
  162. AddACLToStoreObjectSecurityDescriptor(
  163. HANDLE hObject,
  164. SE_OBJECT_TYPE ObjectType
  165. )
  166. {
  167. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  168. SID_IDENTIFIER_AUTHORITY CreatorAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  169. PSID pAdminSid = NULL;
  170. PSID pSystemSid = NULL;
  171. PSID pPowerUsersSid = NULL;
  172. PSID pCreatorSid = NULL;
  173. PSID pUsersSid = NULL;
  174. PACL pNewDACL;
  175. DWORD dwError;
  176. BOOL bSuccess;
  177. DWORD i;
  178. PALLOCATEANDINITIALIZESID_FN pAllocateAndInitializeSid = NULL;
  179. PSETENTRIESINACL pSetEntriesInAcl = NULL;
  180. HMODULE pAdvApi32 = NULL;
  181. PFREESID_FN pFreeSid = NULL;
  182. PSETSECURITYINFO_FN pSetSecurityInfo;
  183. EXPLICIT_ACCESS ExplicitAccess[6];
  184. pAdvApi32 = LoadLibrary(ADVAPI_32_DLL);
  185. if (!pAdvApi32) {
  186. return(FALSE);
  187. }
  188. pAllocateAndInitializeSid = (PALLOCATEANDINITIALIZESID_FN)
  189. GetProcAddress(pAdvApi32,
  190. ALLOCATE_AND_INITITIALIZE_SID);
  191. if (pAllocateAndInitializeSid == NULL)
  192. {
  193. goto ErrorCleanup;
  194. }
  195. #ifdef UNICODE
  196. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>(GetProcAddress( pAdvApi32, "SetEntriesInAclW" ));
  197. #else
  198. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>(GetProcAddress( pAdvApi32, "SetEntriesInAclA" ));
  199. #endif
  200. if (!pSetEntriesInAcl) {
  201. FreeLibrary( pAdvApi32 );
  202. return(FALSE);
  203. }
  204. //
  205. // Create SIDs - Admins and System
  206. //
  207. bSuccess = pAllocateAndInitializeSid( &NtAuthority,
  208. 2,
  209. SECURITY_BUILTIN_DOMAIN_RID,
  210. DOMAIN_ALIAS_RID_ADMINS,
  211. 0, 0, 0, 0, 0, 0,
  212. &pAdminSid);
  213. bSuccess = bSuccess && pAllocateAndInitializeSid( &NtAuthority,
  214. 1,
  215. SECURITY_LOCAL_SYSTEM_RID,
  216. 0, 0, 0, 0, 0, 0, 0,
  217. &pSystemSid);
  218. bSuccess = bSuccess && pAllocateAndInitializeSid( &NtAuthority,
  219. 2,
  220. SECURITY_BUILTIN_DOMAIN_RID,
  221. DOMAIN_ALIAS_RID_POWER_USERS,
  222. 0, 0, 0, 0, 0, 0,
  223. &pPowerUsersSid);
  224. bSuccess = bSuccess && pAllocateAndInitializeSid( &CreatorAuthority,
  225. 1,
  226. SECURITY_CREATOR_OWNER_RID,
  227. 0, 0, 0, 0, 0, 0, 0,
  228. &pCreatorSid);
  229. bSuccess = bSuccess && pAllocateAndInitializeSid(&NtAuthority,
  230. 2,
  231. SECURITY_BUILTIN_DOMAIN_RID,
  232. DOMAIN_ALIAS_RID_USERS,
  233. 0, 0, 0, 0, 0, 0,
  234. &pUsersSid);
  235. if (bSuccess) {
  236. //
  237. // Initialize Access structures describing the ACEs we want:
  238. // System Full Control
  239. // Admins Full Control
  240. //
  241. // We'll take advantage of the fact that the unlocked private keys is
  242. // the same as the device parameters key and they are a superset of the
  243. // locked private keys.
  244. //
  245. // When we create the DACL for the private key we'll specify a subset of
  246. // the ExplicitAccess array.
  247. //
  248. for (i = 0; i < 6; i++) {
  249. ExplicitAccess[i].grfAccessMode = SET_ACCESS;
  250. ExplicitAccess[i].Trustee.pMultipleTrustee = NULL;
  251. ExplicitAccess[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  252. ExplicitAccess[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  253. ExplicitAccess[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  254. }
  255. ExplicitAccess[0].grfAccessPermissions = KEY_ALL_ACCESS;
  256. ExplicitAccess[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  257. ExplicitAccess[0].Trustee.ptstrName = (LPTSTR)pAdminSid;
  258. ExplicitAccess[1].grfAccessPermissions = KEY_ALL_ACCESS;
  259. ExplicitAccess[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  260. ExplicitAccess[1].Trustee.ptstrName = (LPTSTR)pSystemSid;
  261. ExplicitAccess[2].grfAccessPermissions = KEY_ALL_ACCESS;
  262. ExplicitAccess[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  263. ExplicitAccess[2].Trustee.ptstrName = (LPTSTR)pCreatorSid;
  264. ExplicitAccess[3].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
  265. ExplicitAccess[3].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  266. ExplicitAccess[3].Trustee.ptstrName = (LPTSTR)pPowerUsersSid;
  267. ExplicitAccess[4].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE| KEY_CREATE_SUB_KEY |KEY_SET_VALUE;
  268. ExplicitAccess[4].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  269. ExplicitAccess[4].Trustee.ptstrName = (LPTSTR)pUsersSid;
  270. ExplicitAccess[5].grfAccessPermissions = DELETE;
  271. ExplicitAccess[5].grfInheritance = INHERIT_ONLY_ACE | SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  272. ExplicitAccess[5].Trustee.ptstrName = (LPTSTR)pUsersSid;
  273. dwError = (DWORD)pSetEntriesInAcl( 6,
  274. ExplicitAccess,
  275. NULL,
  276. &pNewDACL );
  277. pSetSecurityInfo = (PSETSECURITYINFO_FN)GetProcAddress(pAdvApi32,SET_SECURITY_INFO);
  278. if (pSetSecurityInfo == NULL)
  279. {
  280. OutputDebugString(_T("AddSidToObjectsSecurityDescriptor: Can't get proc SetSecurityInfo"));
  281. goto ErrorCleanup;
  282. }
  283. dwError = pSetSecurityInfo(
  284. hObject,
  285. ObjectType,
  286. DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
  287. NULL,
  288. NULL,
  289. pNewDACL,
  290. NULL
  291. );
  292. }
  293. ErrorCleanup:
  294. pFreeSid = (PFREESID_FN)
  295. GetProcAddress(pAdvApi32,
  296. FREE_SID);
  297. if(pAdminSid)
  298. pFreeSid(pAdminSid);
  299. if(pSystemSid)
  300. pFreeSid(pSystemSid);
  301. if(pPowerUsersSid)
  302. pFreeSid(pPowerUsersSid);
  303. if(pCreatorSid)
  304. pFreeSid(pCreatorSid);
  305. if(pUsersSid)
  306. pFreeSid(pUsersSid);
  307. if(pNewDACL)
  308. LocalFree(pNewDACL);
  309. if(pAdvApi32)
  310. FreeLibrary( pAdvApi32 );
  311. return bSuccess;
  312. }
  313. BOOL CreateRegAddAcl(VOID)
  314. {
  315. BOOL fRet = FALSE;
  316. DWORD dwDisposition, dwError = NO_ERROR;
  317. HKEY hKey = NULL, hKeyStore = NULL;
  318. dwError = RegCreateKeyEx(
  319. HKEY_LOCAL_MACHINE,
  320. MSLICENSING_REG_KEY,
  321. 0,
  322. NULL,
  323. REG_OPTION_NON_VOLATILE,
  324. KEY_ALL_ACCESS,
  325. NULL,
  326. &hKey,
  327. &dwDisposition
  328. );
  329. if (dwError != ERROR_SUCCESS) {
  330. return FALSE;
  331. }
  332. fRet = AddACLToObjectSecurityDescriptor(
  333. hKey,
  334. SE_REGISTRY_KEY
  335. );
  336. if (!fRet) {
  337. goto cleanup;
  338. }
  339. dwError = RegCreateKeyEx(
  340. hKey,
  341. MSLICENSING_STORE_SUBKEY,
  342. 0,
  343. NULL,
  344. REG_OPTION_NON_VOLATILE,
  345. KEY_ALL_ACCESS,
  346. NULL,
  347. &hKeyStore,
  348. &dwDisposition
  349. );
  350. if (dwError != ERROR_SUCCESS) {
  351. fRet = FALSE;
  352. goto cleanup;
  353. }
  354. fRet = AddACLToStoreObjectSecurityDescriptor(
  355. hKeyStore,
  356. SE_REGISTRY_KEY
  357. );
  358. cleanup:
  359. if (NULL != hKey)
  360. {
  361. RegCloseKey( hKey );
  362. }
  363. if (NULL != hKeyStore)
  364. {
  365. RegCloseKey( hKeyStore );
  366. }
  367. return fRet;
  368. }
  369. BOOL
  370. CreateAndWriteHWID(VOID)
  371. {
  372. BOOL fRet = FALSE;
  373. DWORD dwDisposition, dwError = NO_ERROR;
  374. HKEY hKey = NULL;
  375. HWID hwid;
  376. // Write HWID to registry
  377. dwError = RegCreateKeyEx(
  378. HKEY_LOCAL_MACHINE,
  379. MSLICENSING_HWID_KEY,
  380. 0,
  381. NULL,
  382. REG_OPTION_NON_VOLATILE,
  383. KEY_ALL_ACCESS,
  384. NULL,
  385. &hKey,
  386. &dwDisposition
  387. );
  388. if (dwError != ERROR_SUCCESS) {
  389. goto cleanup;
  390. }
  391. // generate HWID
  392. if (LICENSE_STATUS_OK == GenerateClientHWID(&hwid))
  393. {
  394. dwError = RegSetValueEx(hKey,
  395. MSLICENSING_HWID_VALUE,
  396. 0,
  397. REG_BINARY,
  398. (LPBYTE)&hwid,
  399. sizeof(HWID));
  400. if (dwError != ERROR_SUCCESS) {
  401. goto cleanup;
  402. }
  403. }
  404. fRet = TRUE;
  405. cleanup:
  406. if (NULL != hKey)
  407. {
  408. RegCloseKey( hKey );
  409. }
  410. return fRet;
  411. }
  412. BOOL SetupMSLicensingKey()
  413. {
  414. OSVERSIONINFOA OsVer;
  415. memset(&OsVer, 0x0, sizeof(OSVERSIONINFOA));
  416. OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  417. GetVersionExA(&OsVer);
  418. if (VER_PLATFORM_WIN32_NT == OsVer.dwPlatformId) //It should be Windows NT
  419. {
  420. if(CreateRegAddAcl())
  421. {
  422. // generate and write the HWID
  423. if (CreateAndWriteHWID())
  424. {
  425. return TRUE;
  426. }
  427. }
  428. }
  429. return FALSE;
  430. }
  431. LPCTSTR pszSysPrepBackupCmd[] = { _T("sessmgr.exe -unregserver") };
  432. DWORD numSysPrepBackupCmd = sizeof(pszSysPrepBackupCmd) / sizeof(pszSysPrepBackupCmd[0]);
  433. LPCTSTR pszSysPrepRestoreCmd[] = { _T("sessmgr.exe -service") };
  434. DWORD numSysPrepRestoreCmd = sizeof(pszSysPrepRestoreCmd) / sizeof(pszSysPrepRestoreCmd[0]);
  435. class CNameSIDList : public list<CNameSID>
  436. {
  437. public:
  438. BOOL Save(HKEY hKey);
  439. BOOL LoadAndDelete(HKEY hKey);
  440. BOOL Find(PSID pSid, LPCWSTR *pwszName);
  441. void AddIfNotExist(CNameSID &NameSID);
  442. };
  443. DWORD
  444. BackupTSCustomSercurity();
  445. DWORD
  446. RestoreTSCustomSercurity();
  447. DWORD
  448. GetLocalSIDs(
  449. IN PSECURITY_DESCRIPTOR pSD,
  450. IN OUT CNameSIDList &NameSIDList);
  451. DWORD
  452. RenewLocalSIDs(
  453. IN OUT PSECURITY_DESCRIPTOR &pSD,
  454. IN OUT CNameSIDList &NameSIDList);
  455. DWORD
  456. ResetTSPublicPrivateKeys();
  457. BOOL
  458. CNameSIDList::Save(HKEY hKey)
  459. {
  460. BOOL bResult = FALSE;
  461. CNameSIDList::iterator it;
  462. //
  463. //calc the size of the buffer we need
  464. //
  465. DWORD dwBufSize = 0;
  466. LPCWSTR wszTmp1,wszTmp2;
  467. for(it=begin();it!=end(); it++)
  468. {
  469. wszTmp1 = (*it).GetName();
  470. wszTmp2 = (*it).GetTextSID();
  471. if(wszTmp1 && wszTmp2)
  472. {
  473. dwBufSize += (wcslen(wszTmp1)+wcslen(wszTmp2)+2)*sizeof(WCHAR);
  474. }
  475. }
  476. //
  477. //for second terminating 0.
  478. //
  479. dwBufSize += sizeof(WCHAR);
  480. //
  481. //Allocate buffer (this will also zeroinit it).
  482. //
  483. LPWSTR wszBuf = (LPWSTR)LocalAlloc(LPTR,dwBufSize);
  484. DWORD dwPos = 0;
  485. if(wszBuf)
  486. {
  487. //
  488. //Fill buffer with data
  489. //
  490. for(it=begin();it!=end(); it++)
  491. {
  492. wszTmp1 = (*it).GetName();
  493. wszTmp2 = (*it).GetTextSID();
  494. if(wszTmp1 && wszTmp2)
  495. {
  496. wcscpy(wszBuf+dwPos,wszTmp1);
  497. dwPos += wcslen(wszTmp1)+1;
  498. wcscpy(wszBuf+dwPos,wszTmp2);
  499. dwPos += wcslen(wszTmp2)+1;
  500. }
  501. }
  502. //
  503. //Save data in the registry
  504. //
  505. if(dwPos && RegSetValueExW(hKey,L"BackupSids",0,REG_MULTI_SZ,
  506. (CONST BYTE *)wszBuf,dwBufSize)==ERROR_SUCCESS)
  507. {
  508. bResult = TRUE;
  509. }
  510. LocalFree(wszBuf);
  511. }
  512. return bResult;
  513. }
  514. BOOL
  515. CNameSIDList::LoadAndDelete(HKEY hKey)
  516. {
  517. BOOL bResult = FALSE;
  518. DWORD err;
  519. DWORD ValueSize = 0;
  520. DWORD ValueType = 0;
  521. err = RegQueryValueExW( hKey, L"BackupSids", NULL, &ValueType, NULL, &ValueSize );
  522. if(err == ERROR_SUCCESS && ValueType == REG_MULTI_SZ && ValueSize)
  523. {
  524. LPWSTR wszBuf = (LPWSTR)LocalAlloc(LPTR,ValueSize);
  525. if ( wszBuf )
  526. {
  527. err = RegQueryValueExW( hKey, L"BackupSids", NULL, &ValueType,
  528. (BYTE *) wszBuf, &ValueSize );
  529. RegDeleteValueW(hKey,L"BackupSids");
  530. if(err == ERROR_SUCCESS )
  531. {
  532. LPCWSTR wszTmp1,wszTmp2;
  533. DWORD dwPos = 0,dwMaxPos = ValueSize/sizeof(WCHAR);
  534. while(dwPos < dwMaxPos)
  535. {
  536. wszTmp1 = wszBuf + dwPos;
  537. dwPos += wcslen(wszTmp1) + 1;
  538. wszTmp2 = wszBuf + dwPos;
  539. dwPos += wcslen(wszTmp2) + 1;
  540. PSID pSid;
  541. if(ConvertStringSidToSidW(wszTmp2,&pSid))
  542. {
  543. CNameSID NameSID(wszTmp1,pSid);
  544. push_back(NameSID);
  545. LocalFree(pSid);
  546. }
  547. }
  548. bResult = TRUE;
  549. }
  550. LocalFree(wszBuf);
  551. }
  552. }
  553. return bResult;
  554. }
  555. BOOL
  556. CNameSIDList::Find(PSID pSid, LPCWSTR *pwszName)
  557. {
  558. *pwszName = NULL;
  559. CNameSIDList::iterator it;
  560. for(it=begin();it!=end(); it++)
  561. {
  562. if(EqualSid(pSid,(*it).GetSID()))
  563. {
  564. *pwszName = (*it).GetName();
  565. return TRUE;
  566. }
  567. }
  568. return FALSE;
  569. }
  570. void
  571. CNameSIDList::AddIfNotExist(CNameSID &NameSID)
  572. {
  573. LPCWSTR wszName;
  574. if(!Find(NameSID.GetSID(),&wszName))
  575. {
  576. push_back(NameSID);
  577. }
  578. }
  579. VOID
  580. RunSysPrepCommands( LPCTSTR pszCmds )
  581. {
  582. STARTUPINFO startupinfo;
  583. PROCESS_INFORMATION process_information;
  584. BOOL bSuccess;
  585. DWORD dwErr;
  586. TCHAR pszCommand[ MAX_PATH * 2 + 1];
  587. try {
  588. //
  589. // CreateProcessW() will fail if lpCommandLine is a const string
  590. // AV if it is actually point to LPCTSTR.
  591. //
  592. lstrcpy( pszCommand, pszCmds );
  593. ZeroMemory( &startupinfo, sizeof(startupinfo) );
  594. startupinfo.cb = sizeof(startupinfo);
  595. startupinfo.dwFlags = STARTF_USESHOWWINDOW;
  596. startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
  597. LOGMESSAGE1(_T("Running command %s."), pszCmds);
  598. bSuccess = CreateProcess( NULL,
  599. pszCommand,
  600. NULL,
  601. NULL,
  602. FALSE,
  603. CREATE_DEFAULT_ERROR_MODE,
  604. NULL,
  605. NULL,
  606. &startupinfo,
  607. &process_information );
  608. if ( !bSuccess )
  609. {
  610. LOGMESSAGE1(_T("ERROR: failed to spawn %s process."), pszCommand);
  611. }
  612. else
  613. {
  614. dwErr = WaitForSingleObject( process_information.hProcess, RUNONCE_DEFAULTWAIT );
  615. if ( dwErr != NO_ERROR )
  616. {
  617. LOGMESSAGE1(_T("ERROR: process %s failed to complete in time."), pszCommand);
  618. }
  619. else
  620. {
  621. LOGMESSAGE1(_T("INFO: process %s completed successfully."), pszCommand);
  622. }
  623. CloseHandle( process_information.hProcess );
  624. CloseHandle( process_information.hThread );
  625. }
  626. }
  627. catch(...) {
  628. LOGMESSAGE0(_T("Command caused exception.") );
  629. }
  630. return;
  631. }
  632. __declspec( dllexport )
  633. VOID
  634. SysPrepBackup( void )
  635. {
  636. DWORD dwIndex;
  637. TCHAR szLogFile[MAX_PATH + 1];
  638. ZeroMemory(szLogFile, sizeof(szLogFile));
  639. ExpandEnvironmentStrings(LOGFILE, szLogFile, MAX_PATH);
  640. LOGMESSAGEINIT(szLogFile, MODULENAME);
  641. LOGMESSAGE0( _T("Entering SysPrepBackup") );
  642. for(dwIndex = 0; dwIndex < numSysPrepBackupCmd; dwIndex++ )
  643. {
  644. RunSysPrepCommands( pszSysPrepBackupCmd[dwIndex] );
  645. }
  646. DWORD err = BackupTSCustomSercurity();
  647. if(err != ERROR_SUCCESS)
  648. {
  649. LOGMESSAGE1(_T("ERROR: BackupTSCustomSercurity() FAILED: %d"),err );
  650. }
  651. LOGMESSAGE0( _T("SysPrepBackup completed") );
  652. }
  653. __declspec( dllexport )
  654. VOID
  655. SysPrepRestore( void )
  656. {
  657. DWORD dwIndex;
  658. TCHAR szLogFile[MAX_PATH + 1];
  659. ZeroMemory( szLogFile, sizeof(szLogFile) );
  660. ExpandEnvironmentStrings(LOGFILE, szLogFile, MAX_PATH);
  661. LOGMESSAGEINIT(szLogFile, MODULENAME);
  662. LOGMESSAGE0( _T("Entering SysPrepRestore") );
  663. for(dwIndex = 0; dwIndex < numSysPrepRestoreCmd; dwIndex++ )
  664. {
  665. RunSysPrepCommands( pszSysPrepRestoreCmd[dwIndex] );
  666. }
  667. DWORD err = RestoreTSCustomSercurity();
  668. if(err != ERROR_SUCCESS)
  669. {
  670. LOGMESSAGE1(_T("ERROR: RestoreTSCustomSercurity() FAILED: %d"),err );
  671. }
  672. err = ResetTSPublicPrivateKeys();
  673. if(err != ERROR_SUCCESS)
  674. {
  675. LOGMESSAGE1(_T("ERROR: ResetTSPublicPrivateKeys() FAILED: %d"),err );
  676. }
  677. //
  678. // This can be done at SysPrep time instead of SysRestore time; however, sysprep
  679. // might support back out sysprep so we delay deleting licensing key at restore time,
  680. // also, to keep it consistent with ResetTSPublicPrivateKey().
  681. //
  682. err = SHDeleteKey( HKEY_LOCAL_MACHINE, MSLICENSING_REG_KEY );
  683. if(err != ERROR_SUCCESS)
  684. {
  685. LOGMESSAGE1(_T("ERROR: Deleting MSLicensing key FAILED: %d"),err );
  686. }
  687. err = SetupMSLicensingKey();
  688. if(err != ERROR_SUCCESS)
  689. {
  690. LOGMESSAGE1(_T("ERROR: SetupMSLicensingKey() FAILED: %d"),err );
  691. }
  692. LOGMESSAGE0( _T("SysPrepRestore completed") );
  693. }
  694. //*************************************************************
  695. //
  696. // BackupTSCustomSercurity()
  697. //
  698. // Purpose: Creates a list of all local SIDs and
  699. // corresponding names included in WinStation's
  700. // security descriptors, and saves it
  701. // in the registry.
  702. //
  703. // Parameters: NONE
  704. //
  705. // Return: error code if fails, ERROR_SUCCESS otherwise
  706. //
  707. // Comments:
  708. //
  709. // History: Date Author Comment
  710. // 03/13/01 skuzin Created
  711. //
  712. //*************************************************************
  713. DWORD
  714. BackupTSCustomSercurity()
  715. {
  716. HKEY hKey;
  717. DWORD err;
  718. //
  719. //Open "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations" key
  720. //
  721. err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  722. _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"),
  723. 0,KEY_READ|KEY_WRITE, &hKey );
  724. if(err != ERROR_SUCCESS)
  725. {
  726. LOGMESSAGE1(_T("ERROR: BackupTSCustomSercurity - RegOpenKeyEx FAILED: %d"),err );
  727. return err;
  728. }
  729. CNameAndSDList NameSDList; //List of security descriptors
  730. CNameSIDList NameSIDList; //List of local SIDs
  731. err=EnumWinStationSecurityDescriptors( hKey, &NameSDList);
  732. if(err == ERROR_SUCCESS)
  733. {
  734. CNameAndSDList::iterator it;
  735. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  736. {
  737. //
  738. //If SD was not customized in most cases it is NULL
  739. //
  740. if((*it).m_pSD)
  741. {
  742. err = GetLocalSIDs((*it).m_pSD, NameSIDList);
  743. if(err != ERROR_SUCCESS)
  744. {
  745. LOGMESSAGE2(_T("ERROR: GetLocalSIDs for %s FAILED: %d"), (*it).m_pName, err );
  746. break;
  747. }
  748. }
  749. }
  750. if(err == ERROR_SUCCESS)
  751. {
  752. if(!NameSIDList.Save(hKey))
  753. {
  754. LOGMESSAGE0(_T("ERROR: BackupTSCustomSercurity - NameSIDList.Save FAILED"));
  755. err = ERROR_FILE_NOT_FOUND;
  756. }
  757. }
  758. }
  759. else
  760. {
  761. LOGMESSAGE1(_T("ERROR: RestoreTSCustomSercurity - ")
  762. _T("EnumWinStationSecurityDescriptors FAILED: %d"),err );
  763. }
  764. RegCloseKey(hKey);
  765. return err;
  766. }
  767. //*************************************************************
  768. //
  769. // RestoreTSCustomSercurity()
  770. //
  771. // Purpose: Gets a list of local SIDs and corresponding names
  772. // (saved by BackupTSCustomSercurity)
  773. // from the registry and updates all WinStation's
  774. // security descriptors with new SID for each
  775. // local account.
  776. //
  777. // Parameters: NONE
  778. //
  779. // Return: error code if fails, ERROR_SUCCESS otherwise
  780. //
  781. // Comments:
  782. //
  783. // History: Date Author Comment
  784. // 03/13/01 skuzin Created
  785. //
  786. //*************************************************************
  787. DWORD
  788. RestoreTSCustomSercurity()
  789. {
  790. HKEY hKey;
  791. DWORD err;
  792. //
  793. //Open "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations" key
  794. //
  795. err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  796. _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"),
  797. 0,KEY_READ|KEY_WRITE, &hKey );
  798. if(err != ERROR_SUCCESS)
  799. {
  800. LOGMESSAGE1(_T("ERROR: RestoreTSCustomSercurity - RegOpenKeyEx FAILED: %d"),err );
  801. return err;
  802. }
  803. CNameAndSDList NameSDList; //List of security descriptors
  804. CNameSIDList NameSIDList; //List of local SIDs
  805. //Now load
  806. if(!NameSIDList.LoadAndDelete(hKey))
  807. {
  808. LOGMESSAGE0(_T("ERROR: RestoreTSCustomSercurity - NameSIDList.LoadAndDelete FAILED"));
  809. RegCloseKey(hKey);
  810. return ERROR_FILE_NOT_FOUND;
  811. }
  812. err=EnumWinStationSecurityDescriptors( hKey, &NameSDList);
  813. if(err == ERROR_SUCCESS)
  814. {
  815. CNameAndSDList::iterator it;
  816. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  817. {
  818. //
  819. //If SD was not customized in most cases it is NULL
  820. //
  821. if((*it).m_pSD)
  822. {
  823. err = RenewLocalSIDs((*it).m_pSD, NameSIDList);
  824. if(err == ERROR_SUCCESS)
  825. {
  826. err = SetWinStationSecurity( hKey, (*it).m_pName, (*it).m_pSD );
  827. if(err !=ERROR_SUCCESS)
  828. {
  829. LOGMESSAGE2(_T("ERROR: SetWinStationSecurity for %s FAILED: %d"),
  830. (*it).m_pName, err );
  831. break;
  832. }
  833. }
  834. else
  835. {
  836. LOGMESSAGE2(_T("ERROR: RenewLocalSIDs for %s FAILED: %d"),
  837. (*it).m_pName, err );
  838. break;
  839. }
  840. }
  841. }
  842. }
  843. else
  844. {
  845. LOGMESSAGE1(_T("ERROR: RestoreTSCustomSercurity - ")
  846. _T("EnumWinStationSecurityDescriptors FAILED: %d"),err );
  847. }
  848. RegCloseKey(hKey);
  849. return err;
  850. }
  851. //*************************************************************
  852. //
  853. // GetLocalSIDs()
  854. //
  855. // Purpose: Gets local SIDs from a security descriptor
  856. // and puts them in the list
  857. //
  858. // Parameters:
  859. // IN PSECURITY_DESCRIPTOR pSD,
  860. // IN OUT CNameSIDList &NameSIDList
  861. //
  862. // Return: error code if fails, ERROR_SUCCESS otherwise
  863. //
  864. // Comments:
  865. //
  866. // History: Date Author Comment
  867. // 03/13/01 skuzin Created
  868. //
  869. //*************************************************************
  870. DWORD
  871. GetLocalSIDs(
  872. IN PSECURITY_DESCRIPTOR pSD,
  873. IN OUT CNameSIDList &NameSIDList)
  874. {
  875. PACL pDacl;
  876. PACL pSacl;
  877. DWORD dwResult;
  878. DWORD cEntries = 0;
  879. dwResult = GetDacl(pSD,&pDacl);
  880. if(dwResult != ERROR_SUCCESS)
  881. {
  882. return dwResult;
  883. }
  884. dwResult = GetSacl(pSD,&pSacl);
  885. if(dwResult != ERROR_SUCCESS)
  886. {
  887. return dwResult;
  888. }
  889. DWORD dwCompNameSize = MAX_COMPUTERNAME_LENGTH + 1;
  890. WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  891. if(!GetComputerNameW(wszComputerName, &dwCompNameSize))
  892. {
  893. return GetLastError();
  894. }
  895. ACL_SIZE_INFORMATION asiAclSize;
  896. DWORD dwBufLength=sizeof(asiAclSize);
  897. ACCESS_ALLOWED_ACE *pAllowedAce;
  898. SYSTEM_AUDIT_ACE *pSystemAce;
  899. DWORD dwAcl_i;
  900. LPWSTR wszName;
  901. SID_NAME_USE eUse;
  902. if(pDacl)
  903. {
  904. if (GetAclInformation(pDacl,
  905. (LPVOID)&asiAclSize,
  906. (DWORD)dwBufLength,
  907. (ACL_INFORMATION_CLASS)AclSizeInformation))
  908. {
  909. for (dwAcl_i = 0; dwAcl_i < asiAclSize.AceCount; dwAcl_i++)
  910. {
  911. if(GetAce( pDacl, dwAcl_i, (LPVOID *)&pAllowedAce))
  912. {
  913. if(LookupSid((PSID)&(pAllowedAce->SidStart),&wszName,&eUse))
  914. {
  915. if(IsLocal(wszComputerName, wszName))
  916. {
  917. NameSIDList.AddIfNotExist(CNameSID(wszName,
  918. (PSID)&(pAllowedAce->SidStart)));
  919. }
  920. LocalFree(wszName);
  921. }
  922. }
  923. }
  924. }
  925. }
  926. if(pSacl)
  927. {
  928. if (GetAclInformation(pSacl,
  929. (LPVOID)&asiAclSize,
  930. (DWORD)dwBufLength,
  931. (ACL_INFORMATION_CLASS)AclSizeInformation))
  932. {
  933. for (dwAcl_i = 0; dwAcl_i < asiAclSize.AceCount; dwAcl_i++)
  934. {
  935. if(GetAce( pSacl, dwAcl_i, (LPVOID *)&pSystemAce))
  936. {
  937. if(LookupSid((PSID)&(pSystemAce->SidStart),&wszName,&eUse))
  938. {
  939. if(IsLocal(wszComputerName, wszName))
  940. {
  941. NameSIDList.AddIfNotExist(CNameSID(wszName,
  942. (PSID)&(pSystemAce->SidStart)));
  943. }
  944. LocalFree(wszName);
  945. }
  946. }
  947. }
  948. }
  949. }
  950. return ERROR_SUCCESS;
  951. }
  952. //*************************************************************
  953. //
  954. // RenewLocalSIDs()
  955. //
  956. // Purpose: Replaces all the local SIDs in a security
  957. // descriptor with the new ones.
  958. //
  959. // Parameters:
  960. // IN OUT PSECURITY_DESCRIPTOR &pSD,
  961. // IN OUT CNameSIDList &NameSIDList
  962. //
  963. // Return: error code if fails, ERROR_SUCCESS otherwise
  964. //
  965. // Comments:
  966. //
  967. // History: Date Author Comment
  968. // 03/13/01 skuzin Created
  969. //
  970. //*************************************************************
  971. DWORD
  972. RenewLocalSIDs(
  973. IN OUT PSECURITY_DESCRIPTOR &pSD,
  974. IN OUT CNameSIDList &NameSIDList)
  975. {
  976. PSECURITY_DESCRIPTOR pAbsoluteSD = NULL;
  977. PACL pDacl = NULL;
  978. PACL pSacl = NULL;
  979. PSID pOwner = NULL;
  980. PSID pPrimaryGroup = NULL;
  981. DWORD dwResult;
  982. dwResult = GetAbsoluteSD(
  983. pSD,
  984. &pAbsoluteSD,
  985. &pDacl,
  986. &pSacl,
  987. &pOwner,
  988. &pPrimaryGroup);
  989. if(dwResult != ERROR_SUCCESS)
  990. {
  991. return dwResult;
  992. }
  993. ULONG cEntries;
  994. PEXPLICIT_ACCESS_W pListOfEntries;
  995. LPCWSTR wszName;
  996. PACL pNewDacl = NULL, pNewSacl = NULL;
  997. __try
  998. {
  999. if(pDacl)
  1000. {
  1001. dwResult = GetExplicitEntriesFromAclW(pDacl, &cEntries, &pListOfEntries);
  1002. if(dwResult != ERROR_SUCCESS)
  1003. {
  1004. return dwResult;
  1005. }
  1006. for(ULONG i=0;i<cEntries;i++)
  1007. {
  1008. if(pListOfEntries[i].Trustee.TrusteeForm == TRUSTEE_IS_SID &&
  1009. NameSIDList.Find((PSID)pListOfEntries[i].Trustee.ptstrName, &wszName))
  1010. {
  1011. pListOfEntries[i].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1012. pListOfEntries[i].Trustee.ptstrName = const_cast<LPWSTR>(wszName);
  1013. }
  1014. }
  1015. dwResult = SetEntriesInAclW(cEntries,pListOfEntries,NULL,&pNewDacl);
  1016. LocalFree(pListOfEntries);
  1017. if(dwResult != ERROR_SUCCESS)
  1018. {
  1019. return dwResult;
  1020. }
  1021. if(!SetSecurityDescriptorDacl(pAbsoluteSD,TRUE,pNewDacl,FALSE))
  1022. {
  1023. return GetLastError();
  1024. }
  1025. }
  1026. if(pSacl)
  1027. {
  1028. dwResult = GetExplicitEntriesFromAclW(pSacl, &cEntries, &pListOfEntries);
  1029. if(dwResult != ERROR_SUCCESS)
  1030. {
  1031. return dwResult;
  1032. }
  1033. for(ULONG i=0;i<cEntries;i++)
  1034. {
  1035. if(pListOfEntries[i].Trustee.TrusteeForm == TRUSTEE_IS_SID &&
  1036. NameSIDList.Find((PSID)pListOfEntries[i].Trustee.ptstrName, &wszName))
  1037. {
  1038. pListOfEntries[i].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1039. pListOfEntries[i].Trustee.ptstrName = const_cast<LPWSTR>(wszName);
  1040. }
  1041. }
  1042. dwResult = SetEntriesInAclW(cEntries,pListOfEntries,NULL,&pNewSacl);
  1043. LocalFree(pListOfEntries);
  1044. if(dwResult != ERROR_SUCCESS)
  1045. {
  1046. return dwResult;
  1047. }
  1048. if(!SetSecurityDescriptorSacl(pAbsoluteSD,TRUE,pNewSacl,FALSE))
  1049. {
  1050. return GetLastError();
  1051. }
  1052. }
  1053. PSECURITY_DESCRIPTOR pTmpSD;
  1054. dwResult = GetSelfRelativeSD(pAbsoluteSD,&pTmpSD);
  1055. if(dwResult != ERROR_SUCCESS)
  1056. {
  1057. return dwResult;
  1058. }
  1059. LocalFree(pSD);
  1060. pSD = pTmpSD;
  1061. }
  1062. __finally
  1063. {
  1064. if(pAbsoluteSD)
  1065. {
  1066. LocalFree(pAbsoluteSD);
  1067. }
  1068. if(pDacl)
  1069. {
  1070. LocalFree(pDacl);
  1071. }
  1072. if(pSacl)
  1073. {
  1074. LocalFree(pSacl);
  1075. }
  1076. if(pOwner)
  1077. {
  1078. LocalFree(pOwner);
  1079. }
  1080. if(pPrimaryGroup)
  1081. {
  1082. LocalFree(pPrimaryGroup);
  1083. }
  1084. if(pNewDacl)
  1085. {
  1086. LocalFree(pNewDacl);
  1087. }
  1088. if(pNewSacl)
  1089. {
  1090. LocalFree(pNewSacl);
  1091. }
  1092. }
  1093. return ERROR_SUCCESS;
  1094. }
  1095. //*************************************************************
  1096. //
  1097. // ResetTSPublicPrivateKeys()
  1098. //
  1099. // Purpose: Deletes keys from LSA secret, so that sysprep'd
  1100. // machines don't share the same keys
  1101. //
  1102. // Parameters: NONE
  1103. //
  1104. // Return: error code if fails, ERROR_SUCCESS otherwise
  1105. //
  1106. // Comments:
  1107. //
  1108. // History: Date Author Comment
  1109. // 06/12/01 robleit Created
  1110. //
  1111. //*************************************************************
  1112. DWORD
  1113. ResetTSPublicPrivateKeys()
  1114. {
  1115. LSA_HANDLE
  1116. PolicyHandle;
  1117. UNICODE_STRING
  1118. SecretKeyName;
  1119. DWORD
  1120. Status;
  1121. LOGMESSAGE0(_T("INFO: Starting ResetTSPublicPrivateKeys.") );
  1122. Status = OpenPolicy( NULL, POLICY_CREATE_SECRET, &PolicyHandle );
  1123. if( ERROR_SUCCESS != Status )
  1124. {
  1125. return LsaNtStatusToWinError(Status);
  1126. }
  1127. SecretKeyName.Buffer = PRIVATE_KEY_NAME;
  1128. SecretKeyName.Length = sizeof(PRIVATE_KEY_NAME) - sizeof(WCHAR);
  1129. SecretKeyName.MaximumLength = sizeof(PRIVATE_KEY_NAME) ;
  1130. Status = LsaStorePrivateData(
  1131. PolicyHandle,
  1132. &SecretKeyName,
  1133. NULL
  1134. );
  1135. if (Status != STATUS_SUCCESS)
  1136. {
  1137. LOGMESSAGE1(_T("ERROR: ResetTSPublicPrivateKeys() FAILED to delete private key: %d"),Status );
  1138. }
  1139. SecretKeyName.Buffer = X509_CERT_PRIVATE_KEY_NAME;
  1140. SecretKeyName.Length = sizeof(X509_CERT_PRIVATE_KEY_NAME) - sizeof(WCHAR);
  1141. SecretKeyName.MaximumLength = sizeof(X509_CERT_PRIVATE_KEY_NAME);
  1142. Status = LsaStorePrivateData(
  1143. PolicyHandle,
  1144. &SecretKeyName,
  1145. NULL
  1146. );
  1147. if (Status != STATUS_SUCCESS)
  1148. {
  1149. LOGMESSAGE1(_T("WARNING: ResetTSPublicPrivateKeys() FAILED to delete X509 private key: %d"),Status );
  1150. }
  1151. SecretKeyName.Buffer = X509_CERT_PUBLIC_KEY_NAME;
  1152. SecretKeyName.Length = sizeof(X509_CERT_PUBLIC_KEY_NAME) - sizeof(WCHAR);
  1153. SecretKeyName.MaximumLength = sizeof(X509_CERT_PUBLIC_KEY_NAME);
  1154. Status = LsaStorePrivateData(
  1155. PolicyHandle,
  1156. &SecretKeyName,
  1157. NULL
  1158. );
  1159. if (Status != STATUS_SUCCESS)
  1160. {
  1161. LOGMESSAGE1(_T("WARNING: ResetTSPublicPrivateKeys() FAILED to delete X509 public key: %d"),Status );
  1162. }
  1163. LsaClose( PolicyHandle );
  1164. Status = LsaNtStatusToWinError( Status );
  1165. return Status;
  1166. }