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.

737 lines
19 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : protstor.c //
  3. // DESCRIPTION : Code for storing keys in the protected store: //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // Dec 4 1996 jeffspel Created //
  7. // Apr 21 1997 jeffspel Changes for NT 5 tree //
  8. // Jul 28 1997 jeffspel Added ability to delete a persisted key //
  9. // May 5 2000 dbarlow Modify error return handling //
  10. // //
  11. // Copyright (C) 1996 - 2000, Microsoft Corporation //
  12. // All Rights Reserved //
  13. /////////////////////////////////////////////////////////////////////////////
  14. #include "precomp.h"
  15. #include "wincrypt.h"
  16. #include "pstore.h"
  17. #include "protstor.h"
  18. #include "ntagum.h"
  19. #define CRYPTO_KEY_TYPE_STRING L"Cryptographic Keys"
  20. static GUID l_DefTypeGuid
  21. = { 0x4d1fa410, 0x6fd9, 0x11d0,
  22. { 0x8C, 0x58, 0x00, 0xC0, 0x4F, 0xD9, 0x12, 0x6B } };
  23. #define CRYPTO_SIG_SUBTYPE_STRING L"RSA Signature Keys"
  24. static GUID l_DefSigGuid
  25. = { 0x4d1fa411, 0x6fd9, 0x11D0,
  26. { 0x8C, 0x58, 0x00, 0xC0, 0x4F, 0xD9, 0x12, 0x6B } };
  27. #define CRYPTO_EXCH_SUBTYPE_STRING L"RSA Exchange Keys"
  28. static GUID l_DefExchGuid
  29. = { 0x4d1fa412, 0x6fd9, 0x11D0,
  30. { 0x8C, 0x58, 0x00, 0xC0, 0x4F, 0xD9, 0x12, 0x6B } };
  31. static GUID l_SysProv = MS_BASE_PSTPROVIDER_ID;
  32. void
  33. FreePSInfo(
  34. PSTORE_INFO *pPStore)
  35. {
  36. IPStore *pIPS;
  37. if (NULL != pPStore)
  38. {
  39. pIPS = (IPStore*)pPStore->pProv;
  40. if (NULL != pIPS)
  41. pIPS->Release();
  42. if (NULL != pPStore->hInst)
  43. FreeLibrary(pPStore->hInst);
  44. if (NULL != pPStore->szPrompt)
  45. _nt_free(pPStore->szPrompt, pPStore->cbPrompt);
  46. _nt_free(pPStore, sizeof(PSTORE_INFO));
  47. }
  48. }
  49. BOOL
  50. CheckPStoreAvailability(
  51. PSTORE_INFO *pPStore)
  52. {
  53. BOOL fRet = FALSE;
  54. if (S_OK != PStoreCreateInstance((IPStore**)(&pPStore->pProv),
  55. &l_SysProv, NULL, 0))
  56. goto ErrorExit;
  57. memcpy(&pPStore->SigType, &l_DefTypeGuid, sizeof(GUID));
  58. memcpy(&pPStore->SigSubtype, &l_DefSigGuid, sizeof(GUID));
  59. memcpy(&pPStore->ExchType, &l_DefTypeGuid, sizeof(GUID));
  60. memcpy(&pPStore->ExchSubtype, &l_DefExchGuid, sizeof(GUID));
  61. fRet = TRUE;
  62. ErrorExit:
  63. return fRet;
  64. }
  65. DWORD
  66. CreateNewPSKeyset(
  67. PSTORE_INFO *pPStore,
  68. DWORD dwFlags)
  69. {
  70. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  71. PST_ACCESSRULE rgRules[2];
  72. PST_ACCESSRULESET Rules;
  73. PST_TYPEINFO Info;
  74. PST_PROMPTINFO PromptInfo = {NULL, NULL};
  75. HRESULT hr;
  76. IPStore *pIPS = (IPStore*)pPStore->pProv;
  77. DWORD dwRegLoc = PST_KEY_CURRENT_USER;
  78. if (dwFlags & CRYPT_MACHINE_KEYSET)
  79. dwRegLoc = PST_KEY_LOCAL_MACHINE;
  80. // if type is not available the create it
  81. memset(&Info, 0, sizeof(Info));
  82. Info.cbSize = sizeof(PST_TYPEINFO);
  83. Info.szDisplayName = CRYPTO_KEY_TYPE_STRING;
  84. hr = pIPS->CreateType(dwRegLoc, &pPStore->SigType, &Info, 0);
  85. if ((S_OK != hr) && (PST_E_TYPE_EXISTS != hr))
  86. {
  87. dwReturn = (DWORD)hr;
  88. goto ErrorExit;
  89. }
  90. // make same rules for read, write access
  91. rgRules[0].cbSize = sizeof(PST_ACCESSRULE);
  92. rgRules[0].AccessModeFlags = PST_READ;
  93. rgRules[0].cClauses = 0;
  94. rgRules[0].rgClauses = NULL;
  95. rgRules[1].cbSize = sizeof(PST_ACCESSRULE);
  96. rgRules[1].AccessModeFlags = PST_WRITE;
  97. rgRules[1].cClauses = 0;
  98. rgRules[1].rgClauses = NULL;
  99. Rules.cbSize = sizeof(PST_ACCESSRULESET);
  100. Rules.cRules = 2;
  101. Rules.rgRules = rgRules;
  102. // create the signature subtype
  103. Info.szDisplayName = CRYPTO_SIG_SUBTYPE_STRING;
  104. PromptInfo.szPrompt = L"";
  105. hr = pIPS->CreateSubtype(dwRegLoc, &pPStore->SigType,
  106. &pPStore->SigSubtype, &Info, &Rules, 0);
  107. if ((S_OK != hr) && (PST_E_TYPE_EXISTS != hr))
  108. {
  109. dwReturn = (DWORD)hr;
  110. goto ErrorExit;
  111. }
  112. // create the exchange subtype
  113. Info.szDisplayName = CRYPTO_EXCH_SUBTYPE_STRING;
  114. hr = pIPS->CreateSubtype(dwRegLoc, &pPStore->SigType,
  115. &pPStore->ExchSubtype, &Info, &Rules, 0);
  116. if ((S_OK != hr) && (PST_E_TYPE_EXISTS != hr))
  117. {
  118. dwReturn = (DWORD)hr;
  119. goto ErrorExit;
  120. }
  121. dwReturn = ERROR_SUCCESS;
  122. ErrorExit:
  123. return dwReturn;
  124. }
  125. DWORD
  126. GetKeysetTypeAndSubType(
  127. PNTAGUserList pUser)
  128. {
  129. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  130. BYTE *pb1 = NULL;
  131. DWORD cb1;
  132. BYTE *pb2 = NULL;
  133. DWORD cb2;
  134. DWORD dwSts;
  135. memcpy(&pUser->pPStore->SigType, &l_DefTypeGuid, sizeof(GUID));
  136. memcpy(&pUser->pPStore->SigSubtype, &l_DefSigGuid, sizeof(GUID));
  137. memcpy(&pUser->pPStore->ExchType, &l_DefTypeGuid, sizeof(GUID));
  138. memcpy(&pUser->pPStore->ExchSubtype, &l_DefExchGuid, sizeof(GUID));
  139. // look in registry and see if the type and subtype Guids are there
  140. dwSts = ReadRegValue(pUser->hKeys, "SigTypeSubtype", &pb1, &cb1, TRUE);
  141. if (ERROR_SUCCESS != dwSts)
  142. {
  143. dwReturn = dwSts;
  144. goto ErrorExit;
  145. }
  146. dwSts = ReadRegValue(pUser->hKeys, "ExchTypeSubtype", &pb2, &cb2, TRUE);
  147. if (ERROR_SUCCESS != dwSts)
  148. {
  149. dwReturn = dwSts;
  150. goto ErrorExit;
  151. }
  152. if (pb1)
  153. {
  154. memcpy(&pUser->pPStore->SigType, pb1, sizeof(GUID));
  155. memcpy(&pUser->pPStore->SigSubtype, pb1 + sizeof(GUID), sizeof(GUID));
  156. }
  157. if (pb2)
  158. {
  159. memcpy(&pUser->pPStore->ExchType, pb2, sizeof(GUID));
  160. memcpy(&pUser->pPStore->ExchSubtype, pb2 + sizeof(GUID), sizeof(GUID));
  161. }
  162. dwReturn = ERROR_SUCCESS;
  163. ErrorExit:
  164. if (pb1)
  165. _nt_free(pb1, cb1);
  166. if (pb2)
  167. _nt_free(pb2, cb2);
  168. return dwReturn;
  169. }
  170. DWORD
  171. SetUIPrompt(
  172. PNTAGUserList pUser,
  173. LPWSTR szPrompt)
  174. {
  175. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  176. DWORD cb = 0;
  177. LPWSTR sz = NULL;
  178. // check if sig or exch keys are loaded and if so error
  179. if (NULL == pUser->pPStore)
  180. {
  181. dwReturn = (DWORD)NTE_BAD_KEYSET;
  182. goto ErrorExit;
  183. }
  184. if (NULL != szPrompt)
  185. {
  186. cb = (lstrlenW(szPrompt) + 1) * sizeof(WCHAR);
  187. sz = (LPWSTR)_nt_malloc(cb);
  188. if (NULL == sz)
  189. {
  190. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  191. goto ErrorExit;
  192. }
  193. lstrcpyW(sz, szPrompt);
  194. }
  195. if (pUser->pPStore->szPrompt)
  196. _nt_free(pUser->pPStore->szPrompt, pUser->pPStore->cbPrompt);
  197. pUser->pPStore->cbPrompt = cb;
  198. pUser->pPStore->szPrompt = sz;
  199. dwReturn = ERROR_SUCCESS;
  200. ErrorExit:
  201. return dwReturn;
  202. }
  203. /*static*/ DWORD
  204. PickleKey(
  205. BOOL fExportable,
  206. size_t cbPriv,
  207. PBYTE pbPriv,
  208. PBYTE *ppbData,
  209. PDWORD pcbData)
  210. {
  211. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  212. if (NULL != pbPriv)
  213. {
  214. // alloc the appropriate amount of space
  215. *pcbData = cbPriv + sizeof(DWORD) + sizeof(BOOL);
  216. *ppbData = (PBYTE)_nt_malloc(*pcbData);
  217. if (NULL == *ppbData)
  218. {
  219. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  220. goto ErrorExit;
  221. }
  222. // copy exportable info into buffer
  223. memcpy(*ppbData, &fExportable, sizeof(BOOL));
  224. // copy length of keying material into buffer
  225. memcpy(*ppbData + sizeof(BOOL), &cbPriv, sizeof(DWORD));
  226. // copy keying material into buffer
  227. memcpy(*ppbData + sizeof(DWORD) + sizeof(BOOL), pbPriv, cbPriv);
  228. }
  229. dwReturn = ERROR_SUCCESS;
  230. ErrorExit:
  231. return dwReturn;
  232. }
  233. /*static*/ DWORD
  234. UnpickleKey(
  235. PBYTE pbData,
  236. BOOL *pfExportable,
  237. DWORD *pcbPriv,
  238. PBYTE *ppbPriv)
  239. {
  240. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  241. if (NULL != pbData)
  242. {
  243. // pull out the exportable info
  244. memcpy(pfExportable, pbData, sizeof(BOOL));
  245. // pull out the length of the key material
  246. memcpy(pcbPriv, pbData + sizeof(BOOL), sizeof(DWORD));
  247. // free the current key material memory
  248. if (NULL != *ppbPriv)
  249. _nt_free(*ppbPriv, *pcbPriv);
  250. // alloc new memory for the key material
  251. *ppbPriv = (PBYTE)_nt_malloc(*pcbPriv);
  252. if (NULL == *ppbPriv)
  253. {
  254. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  255. goto ErrorExit;
  256. }
  257. // copy key material
  258. memcpy(*ppbPriv, pbData + sizeof(DWORD) + sizeof(BOOL), *pcbPriv);
  259. }
  260. dwReturn = ERROR_SUCCESS;
  261. ErrorExit:
  262. return dwReturn;
  263. }
  264. /*static*/ DWORD
  265. RestoreKeyFromProtectedStorage(
  266. PNTAGUserList pUser,
  267. LPWSTR szKeyName,
  268. BYTE **ppbKey,
  269. DWORD *pcbKey,
  270. LPWSTR szPrompt,
  271. BOOL fSigKey,
  272. BOOL fMachineKeySet,
  273. BOOL *pfUIOnKey)
  274. {
  275. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  276. HRESULT hr;
  277. DWORD cb;
  278. BYTE *pb = NULL;
  279. GUID *pType;
  280. GUID *pSubtype;
  281. BOOL *pf;
  282. PST_PROMPTINFO PromptInfo;
  283. IPStore *pIPS = (IPStore*)(pUser->pPStore->pProv);
  284. DWORD dwRegLoc = PST_KEY_CURRENT_USER;
  285. DWORD dwSts;
  286. *pfUIOnKey = FALSE;
  287. if (fMachineKeySet)
  288. dwRegLoc = PST_KEY_LOCAL_MACHINE;
  289. memset(&PromptInfo, 0, sizeof(PromptInfo));
  290. PromptInfo.cbSize = sizeof(PST_PROMPTINFO);
  291. if (fSigKey)
  292. {
  293. if (0 == pUser->ContInfo.ContLens.cbSigPub)
  294. {
  295. dwReturn = ERROR_SUCCESS;
  296. goto ErrorExit;
  297. }
  298. pType = &pUser->pPStore->SigType;
  299. pSubtype = &pUser->pPStore->SigSubtype;
  300. pf = &pUser->ContInfo.fSigExportable;
  301. }
  302. else
  303. {
  304. if (0 == pUser->ContInfo.ContLens.cbExchPub)
  305. {
  306. dwReturn = ERROR_SUCCESS;
  307. goto ErrorExit;
  308. }
  309. pType = &pUser->pPStore->ExchType;
  310. pSubtype = &pUser->pPStore->ExchSubtype;
  311. pf = &pUser->ContInfo.fExchExportable;
  312. }
  313. // read the item from secure storage
  314. PromptInfo.hwndApp = NULL;
  315. if (NULL == pUser->pPStore->szPrompt)
  316. PromptInfo.szPrompt = szPrompt;
  317. else
  318. PromptInfo.szPrompt = pUser->pPStore->szPrompt;
  319. hr = pIPS->ReadItem(dwRegLoc, pType, pSubtype, szKeyName, &cb,
  320. &pb, &PromptInfo,
  321. PST_PROMPT_QUERY | PST_NO_UI_MIGRATION);
  322. if (S_OK != hr)
  323. {
  324. // this function returns PST_E_ITEM_EXISTS if there is UI on the item
  325. if (PST_E_ITEM_EXISTS == hr)
  326. *pfUIOnKey = TRUE;
  327. else
  328. {
  329. dwReturn = (DWORD)hr;
  330. goto ErrorExit;
  331. }
  332. }
  333. dwSts = UnpickleKey(pb, pf, pcbKey, ppbKey);
  334. if (ERROR_SUCCESS != dwSts)
  335. {
  336. dwReturn = dwSts;
  337. goto ErrorExit;
  338. }
  339. dwReturn = ERROR_SUCCESS;
  340. ErrorExit:
  341. if (pb)
  342. CoTaskMemFree(pb);
  343. return dwReturn;
  344. }
  345. /*static*/ DWORD
  346. MakeUnicodeKeysetName(
  347. BYTE *pszName,
  348. LPWSTR *ppszWName)
  349. {
  350. // ?BUGBUG? -- We don't really do this, do we?
  351. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  352. long i;
  353. DWORD cb;
  354. cb = (DWORD)lstrlenA((LPSTR)pszName);
  355. *ppszWName = (LPWSTR)_nt_malloc((cb + 1) * sizeof(WCHAR));
  356. if (NULL == *ppszWName)
  357. {
  358. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  359. goto ErrorExit;
  360. }
  361. for (i=0;i<(long)cb;i++)
  362. (*ppszWName)[i] = (WCHAR)(pszName[i]);
  363. dwReturn = ERROR_SUCCESS;
  364. ErrorExit:
  365. return dwReturn;
  366. }
  367. DWORD
  368. RestoreKeysetFromProtectedStorage(
  369. PNTAGUserList pUser,
  370. LPWSTR szPrompt,
  371. BYTE **ppbKey,
  372. DWORD *pcbKey,
  373. BOOL fSigKey,
  374. BOOL fMachineKeySet,
  375. BOOL *pfUIOnKey)
  376. {
  377. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  378. LPWSTR pszWName = NULL;
  379. DWORD dwSts;
  380. // convert the keyset name to unicode
  381. dwSts = MakeUnicodeKeysetName((BYTE*)pUser->ContInfo.pszUserName,
  382. &pszWName);
  383. if (ERROR_SUCCESS != dwSts)
  384. {
  385. dwReturn = dwSts;
  386. goto ErrorExit;
  387. }
  388. // restore the signature key
  389. dwSts = RestoreKeyFromProtectedStorage(pUser, pszWName, ppbKey, pcbKey,
  390. szPrompt, fSigKey, fMachineKeySet,
  391. pfUIOnKey);
  392. if (ERROR_SUCCESS != dwSts)
  393. {
  394. dwReturn = dwSts;
  395. goto ErrorExit;
  396. }
  397. dwReturn = ERROR_SUCCESS;
  398. ErrorExit:
  399. if (pszWName)
  400. _nt_free(pszWName, (wcslen(pszWName) + 1) * sizeof(WCHAR));
  401. return dwReturn;
  402. }
  403. void
  404. RemoveKeysetFromMemory(
  405. PNTAGUserList pUser)
  406. {
  407. pUser->ContInfo.fSigExportable = FALSE;
  408. if (pUser->pSigPrivKey)
  409. {
  410. _nt_free(pUser->pSigPrivKey, pUser->SigPrivLen);
  411. pUser->SigPrivLen = 0;
  412. pUser->pSigPrivKey = NULL;
  413. }
  414. pUser->ContInfo.fExchExportable = FALSE;
  415. if (pUser->pExchPrivKey)
  416. {
  417. _nt_free(pUser->pExchPrivKey, pUser->ExchPrivLen);
  418. pUser->ExchPrivLen = 0;
  419. pUser->pExchPrivKey = NULL;
  420. }
  421. }
  422. DWORD
  423. SaveKeyToProtectedStorage(
  424. PNTAGUserList pUser,
  425. DWORD dwFlags,
  426. LPWSTR szPrompt,
  427. BOOL fSigKey,
  428. BOOL fMachineKeySet)
  429. {
  430. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  431. HRESULT hr;
  432. PBYTE pb = NULL;
  433. DWORD cb;
  434. GUID *pType;
  435. GUID *pSubtype;
  436. BOOL f;
  437. BYTE *pbKey = NULL;
  438. size_t cbKey;
  439. LPWSTR pszWName = NULL;
  440. LPSTR szKeyName;
  441. PST_PROMPTINFO PromptInfo;
  442. IPStore *pIPS = (IPStore*)(pUser->pPStore->pProv);
  443. DWORD dwRegLoc = PST_KEY_CURRENT_USER;
  444. DWORD dwConfirm = PST_CF_NONE;
  445. DWORD dwSts;
  446. if (fMachineKeySet)
  447. dwRegLoc = PST_KEY_LOCAL_MACHINE;
  448. memset(&PromptInfo, 0, sizeof(PromptInfo));
  449. PromptInfo.cbSize = sizeof(PST_PROMPTINFO);
  450. if (fSigKey)
  451. {
  452. pType = &pUser->pPStore->SigType;
  453. pSubtype = &pUser->pPStore->SigSubtype;
  454. f = pUser->ContInfo.fSigExportable;
  455. cbKey = pUser->SigPrivLen;
  456. pbKey = pUser->pSigPrivKey;
  457. szKeyName = "SPbK";
  458. if (dwFlags & CRYPT_USER_PROTECTED)
  459. dwConfirm = PST_CF_DEFAULT;
  460. }
  461. else
  462. {
  463. pType = &pUser->pPStore->ExchType;
  464. pSubtype = &pUser->pPStore->ExchSubtype;
  465. f = pUser->ContInfo.fExchExportable;
  466. cbKey = pUser->ExchPrivLen;
  467. pbKey = pUser->pExchPrivKey;
  468. szKeyName = "EPbK";
  469. if (dwFlags & CRYPT_USER_PROTECTED)
  470. dwConfirm = PST_CF_DEFAULT;
  471. }
  472. // format the signature key and exportable info
  473. dwSts = PickleKey(f, cbKey, pbKey, &pb, &cb);
  474. if (ERROR_SUCCESS != dwSts)
  475. {
  476. dwReturn = dwSts;
  477. goto ErrorExit;
  478. }
  479. if (pb)
  480. {
  481. // make a unicode version of the keyset name
  482. dwSts = MakeUnicodeKeysetName((BYTE*)pUser->ContInfo.pszUserName,
  483. &pszWName);
  484. if (ERROR_SUCCESS != dwSts)
  485. {
  486. dwReturn = dwSts;
  487. goto ErrorExit;
  488. }
  489. PromptInfo.hwndApp = NULL;
  490. if (NULL == pUser->pPStore->szPrompt)
  491. PromptInfo.szPrompt = szPrompt;
  492. else
  493. PromptInfo.szPrompt = pUser->pPStore->szPrompt;
  494. hr = pIPS->WriteItem(dwRegLoc, pType, pSubtype, pszWName,
  495. cb, pb, &PromptInfo, dwConfirm, 0);
  496. if (S_OK != hr)
  497. {
  498. dwReturn = (DWORD)hr;
  499. goto ErrorExit;
  500. }
  501. }
  502. dwReturn = ERROR_SUCCESS;
  503. ErrorExit:
  504. if (pb)
  505. _nt_free(pb, cb);
  506. if (pszWName)
  507. _nt_free(pszWName, (wcslen(pszWName) + 1) * sizeof(WCHAR));
  508. return dwReturn;
  509. }
  510. DWORD
  511. DeleteKeyFromProtectedStorage(
  512. NTAGUserList *pUser,
  513. PCSP_STRINGS pStrings,
  514. DWORD dwKeySpec,
  515. BOOL fMachineKeySet,
  516. BOOL fMigration)
  517. {
  518. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  519. LPWSTR szWUserName = NULL;
  520. PST_PROMPTINFO PromptInfo;
  521. IPStore *pIPS;
  522. DWORD dwRegLoc = PST_KEY_CURRENT_USER;
  523. DWORD dwSts;
  524. memset(&PromptInfo, 0, sizeof(PromptInfo));
  525. PromptInfo.cbSize = sizeof(PST_PROMPTINFO);
  526. PromptInfo.hwndApp = NULL;
  527. if (fMachineKeySet)
  528. dwRegLoc = PST_KEY_LOCAL_MACHINE;
  529. // make a unicode name
  530. dwSts = MakeUnicodeKeysetName((BYTE*)pUser->ContInfo.pszUserName,
  531. &szWUserName);
  532. if (ERROR_SUCCESS != dwSts)
  533. {
  534. dwReturn = dwSts;
  535. goto ErrorExit;
  536. }
  537. pIPS = (IPStore*)(pUser->pPStore->pProv);
  538. if (AT_SIGNATURE == dwKeySpec)
  539. {
  540. if (fMigration)
  541. PromptInfo.szPrompt = pStrings->pwszDeleteMigrSig;
  542. else
  543. PromptInfo.szPrompt = pStrings->pwszDeleteSig;
  544. pIPS->DeleteItem(dwRegLoc,
  545. &pUser->pPStore->SigType,
  546. &pUser->pPStore->SigSubtype,
  547. szWUserName,
  548. &PromptInfo,
  549. PST_NO_UI_MIGRATION);
  550. }
  551. else
  552. {
  553. if (fMigration)
  554. PromptInfo.szPrompt = pStrings->pwszDeleteMigrExch;
  555. else
  556. PromptInfo.szPrompt = pStrings->pwszDeleteExch;
  557. pIPS->DeleteItem(dwRegLoc,
  558. &pUser->pPStore->ExchType,
  559. &pUser->pPStore->ExchSubtype,
  560. szWUserName,
  561. &PromptInfo,
  562. PST_NO_UI_MIGRATION);
  563. }
  564. dwReturn = ERROR_SUCCESS;
  565. ErrorExit:
  566. if (szWUserName)
  567. _nt_free(szWUserName, (wcslen(szWUserName) + 1) * sizeof(WCHAR));
  568. return dwReturn;
  569. }
  570. DWORD
  571. DeleteFromProtectedStorage(
  572. CONST char *pszUserID,
  573. PCSP_STRINGS pStrings,
  574. HKEY hRegKey,
  575. BOOL fMachineKeySet)
  576. {
  577. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  578. NTAGUserList User;
  579. DWORD dwSts;
  580. // set up the User List structure
  581. memset(&User, 0, sizeof(User));
  582. User.ContInfo.pszUserName = (LPSTR)pszUserID;
  583. User.hKeys = hRegKey;
  584. User.pPStore = (PSTORE_INFO*)_nt_malloc(sizeof(PSTORE_INFO));
  585. if (NULL == User.pPStore)
  586. {
  587. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  588. goto ErrorExit;
  589. }
  590. if (!CheckPStoreAvailability(User.pPStore))
  591. {
  592. dwReturn = (DWORD)NTE_FAIL;
  593. goto ErrorExit;
  594. }
  595. // get type and subtypes
  596. dwSts = GetKeysetTypeAndSubType(&User);
  597. if (ERROR_SUCCESS != dwSts)
  598. {
  599. dwReturn = dwSts;
  600. goto ErrorExit;
  601. }
  602. // delete each key
  603. dwSts = DeleteKeyFromProtectedStorage(&User, pStrings, AT_SIGNATURE,
  604. fMachineKeySet, FALSE);
  605. if (ERROR_SUCCESS != dwSts)
  606. {
  607. dwReturn = dwSts;
  608. goto ErrorExit;
  609. }
  610. dwSts = DeleteKeyFromProtectedStorage(&User, pStrings, AT_KEYEXCHANGE,
  611. fMachineKeySet, FALSE);
  612. if (ERROR_SUCCESS != dwSts)
  613. {
  614. dwReturn = dwSts;
  615. goto ErrorExit;
  616. }
  617. dwReturn = ERROR_SUCCESS;
  618. ErrorExit:
  619. if (User.pPStore)
  620. FreePSInfo(User.pPStore);
  621. return dwReturn;
  622. }