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.

1949 lines
45 KiB

  1. /*
  2. File: Prov.cpp
  3. Title: Protected Storage Base Provider
  4. Author: Matt Thomlinson
  5. Date: 10/22/96
  6. Protected storage is an area to safely store user belongings.
  7. This storage is available on both NT and Win95, and offers finer
  8. granularity over access than do NT ACLs.
  9. The PStore architecture resembles the CryptoAPI provider architecture.
  10. The PStore server, PStoreS, takes requests and forwards them to any one
  11. of a number of providers, of which PSBase is a single instance. (The
  12. server exports some basic functionality to ease the pain of provider
  13. writers, like impersonating the caller and checking access rules.) The
  14. server gets requests through LPC from a client (PStoreC.dll),
  15. which wraps a number of operations into a COM object.
  16. The base provider supports user storage, where items are stored under
  17. the namespace of which user called protected storage, and local machine
  18. storage, a global area that can be accessed by everyone.
  19. Rules can be set on subtypes describing under what conditions accesses
  20. are allowed. Rules can specify callers be Authenticode signed, callers
  21. simply be unmodified from access to access, and normal (arbitrary) NT Acls
  22. be satisfied.
  23. In addition, items stored in the user namespace have user authentication
  24. by default, where the user gets to specify what type of user
  25. confirmation they want to see appear. This confirmation could be
  26. no confirmation, an ok/cancel dialog, a password, a retinal scan, a
  27. fingerprint, etc.
  28. The base provider stores items in the registry, DES-encrypted with a
  29. key derived from the user password. Items are also integrity-protected
  30. by a keyed MAC.
  31. Interoperability and transport issues are solved by adding a provider
  32. supporting the PFX interchange format.
  33. The base provider is slightly more special than all other providers, since
  34. the server stores bootstrap configuration data here. (The base provider
  35. is guaranteed to always be present). The configuration data includes
  36. what other providers are ok to be loaded.
  37. */
  38. #include <pch.cpp>
  39. #pragma hdrstop
  40. #include "provif.h"
  41. #include "provui.h"
  42. #include "storage.h"
  43. #include "passwd.h"
  44. // sfield: legacy migration hack
  45. #include "migrate.h"
  46. BOOL g_fAllowCachePW = TRUE;
  47. // fwd (secure.cpp)
  48. BOOL FIsEncryptionPermitted();
  49. HINSTANCE g_hInst = NULL;
  50. BOOL g_fImagesIntegrid = FALSE;
  51. DISPIF_CALLBACKS g_sCallbacks;
  52. BOOL g_fCallbacksInitialized = FALSE;
  53. PRIVATE_CALLBACKS g_sPrivateCallbacks;
  54. CUAList* g_pCUAList = NULL;
  55. COpenItemList* g_pCOpenItemList = NULL;
  56. CCryptProvList* g_pCProvList = NULL;
  57. extern CRITICAL_SECTION g_csUIInitialized;
  58. /////////////////////////////////////////////////////////////////////////
  59. // Very important to hook DllMain, do caller authentication
  60. BOOL WINAPI DllMain (HMODULE hInst,
  61. ULONG ul_reason_for_call,
  62. LPVOID lpReserved)
  63. {
  64. switch( ul_reason_for_call )
  65. {
  66. case DLL_PROCESS_ATTACH:
  67. {
  68. g_hInst = hInst;
  69. InitializeCriticalSection( &g_csUIInitialized );
  70. //
  71. // just hard-code image verification succeeded.
  72. //
  73. g_fImagesIntegrid = TRUE;
  74. // set up global lists
  75. g_pCUAList = new CUAList;
  76. if(g_pCUAList)
  77. {
  78. if(!g_pCUAList->Initialize())
  79. {
  80. delete g_pCUAList;
  81. g_pCUAList = NULL;
  82. }
  83. }
  84. g_pCOpenItemList = new COpenItemList;
  85. if(g_pCOpenItemList)
  86. {
  87. if(!g_pCOpenItemList->Initialize())
  88. {
  89. delete g_pCOpenItemList;
  90. g_pCOpenItemList = NULL;
  91. }
  92. }
  93. g_pCProvList = new CCryptProvList;
  94. if(g_pCProvList)
  95. {
  96. if(!g_pCProvList->Initialize())
  97. {
  98. delete g_pCProvList;
  99. g_pCProvList = NULL;
  100. }
  101. }
  102. DisableThreadLibraryCalls(hInst);
  103. // call EncryptionPermitted routine once to initialize globals
  104. FIsEncryptionPermitted();
  105. FInitProtectAPIGlobals();
  106. break;
  107. }
  108. case DLL_PROCESS_DETACH:
  109. // tear down global lists
  110. if(g_pCUAList)
  111. {
  112. delete g_pCUAList;
  113. g_pCUAList = NULL;
  114. }
  115. if(g_pCOpenItemList)
  116. {
  117. delete g_pCOpenItemList;
  118. g_pCOpenItemList = NULL;
  119. }
  120. if(g_pCProvList)
  121. {
  122. delete g_pCProvList;
  123. g_pCProvList = NULL;
  124. }
  125. ReleaseUI();
  126. DeleteCriticalSection( &g_csUIInitialized );
  127. break;
  128. default:
  129. break;
  130. }
  131. return TRUE;
  132. }
  133. HRESULT SPProviderInitialize(
  134. DISPIF_CALLBACKS *psCallbacks)
  135. {
  136. // only allow one initialization (security check)
  137. if (g_fCallbacksInitialized)
  138. return PST_E_FAIL;
  139. if( psCallbacks->cbSize < sizeof(DISPIF_CALLBACKS) )
  140. return PST_E_FAIL;
  141. // tuck these callback fxns for later use
  142. CopyMemory(&g_sCallbacks, psCallbacks, sizeof(DISPIF_CALLBACKS));
  143. // now, get the private callbacks from the server
  144. DWORD cbPrivateCallbacks = sizeof(g_sPrivateCallbacks);
  145. if(!g_sCallbacks.pfnFGetServerParam(
  146. NULL,
  147. SS_SERVERPARAM_CALLBACKS,
  148. &g_sPrivateCallbacks,
  149. &cbPrivateCallbacks
  150. ))
  151. return PST_E_FAIL;
  152. if(g_sPrivateCallbacks.cbSize != sizeof(g_sPrivateCallbacks))
  153. return PST_E_FAIL;
  154. g_fCallbacksInitialized = TRUE;
  155. return PST_E_OK;
  156. }
  157. HRESULT SPAcquireContext(
  158. /* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
  159. /* [in] */ DWORD dwFlags)
  160. {
  161. HRESULT dwRet = PST_E_FAIL;
  162. BOOL fExisted = FALSE;
  163. LPWSTR szUser = NULL;
  164. HKEY hUserKey = NULL;
  165. BOOL fUserExisted;
  166. if(!InitUI())
  167. return FALSE;
  168. if (0 != dwFlags)
  169. {
  170. dwRet = PST_E_BAD_FLAGS;
  171. goto Ret;
  172. }
  173. // get current user
  174. if (!g_sCallbacks.pfnFGetUser(
  175. phPSTProv,
  176. &szUser))
  177. goto Ret;
  178. //
  179. // migrate password data. This doesn't do anything internally if migration
  180. // already took place.
  181. //
  182. MigrateData(phPSTProv, TRUE);
  183. // One-Time WinPW Init Code
  184. if (!BPMasterKeyExists(
  185. szUser,
  186. WSZ_PASSWORD_WINDOWS))
  187. {
  188. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  189. // Init the Users' Windows password entry
  190. if (!FMyGetWinPassword(
  191. phPSTProv,
  192. szUser,
  193. rgbPwd
  194. ))
  195. goto Ret;
  196. if (!FCheckPWConfirm(
  197. szUser,
  198. WSZ_PASSWORD_WINDOWS,
  199. rgbPwd))
  200. goto Ret;
  201. //
  202. // newly created key: data migration is not necessary.
  203. // specify that only the migration flag need be updated
  204. //
  205. MigrateData(phPSTProv, FALSE);
  206. }
  207. dwRet = PST_E_OK;
  208. Ret:
  209. if (hUserKey)
  210. RegCloseKey(hUserKey);
  211. if (szUser)
  212. SSFree(szUser);
  213. return dwRet;
  214. }
  215. HRESULT SPReleaseContext(
  216. /* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
  217. /* [in] */ DWORD dwFlags)
  218. {
  219. return PST_E_OK;
  220. }
  221. HRESULT SPGetProvInfo(
  222. PPST_PROVIDERINFO* ppPSTInfo,
  223. DWORD dwFlags)
  224. {
  225. HRESULT hr = PST_E_FAIL;
  226. if (0 != dwFlags)
  227. return PST_E_BAD_FLAGS;
  228. // Note: not linked to a specific context (hPSTProv)
  229. // Note: caller not verified -- give this info to anyone
  230. PPST_PROVIDERINFO pPSTInfo;
  231. if (NULL == (pPSTInfo = (PST_PROVIDERINFO*)SSAlloc(sizeof(PST_PROVIDERINFO))) )
  232. return PST_E_FAIL;
  233. ZeroMemory(pPSTInfo, sizeof(PST_PROVIDERINFO));
  234. pPSTInfo->cbSize = sizeof(PST_PROVIDERINFO);
  235. GUID guidBaseProvider = MS_BASE_PSTPROVIDER_ID;
  236. CopyMemory(&pPSTInfo->ID, &guidBaseProvider, sizeof(pPSTInfo->ID));
  237. pPSTInfo->Capabilities = PST_PC_ROAMABLE;
  238. if (NULL == (pPSTInfo->szProviderName = (LPWSTR)SSAlloc(sizeof(MS_BASE_PSTPROVIDER_NAME))) )
  239. goto Ret;
  240. wcscpy(pPSTInfo->szProviderName, MS_BASE_PSTPROVIDER_NAME);
  241. hr = PST_E_OK;
  242. Ret:
  243. if (hr != PST_E_OK)
  244. {
  245. if (pPSTInfo->szProviderName)
  246. SSFree(pPSTInfo->szProviderName);
  247. SSFree(pPSTInfo);
  248. pPSTInfo = NULL;
  249. }
  250. // in either case, return pPSTInfo
  251. *ppPSTInfo = pPSTInfo;
  252. return hr;
  253. }
  254. HRESULT SPGetProvParam(
  255. /* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
  256. /* [in] */ DWORD dwParam,
  257. /* [out] */ DWORD __RPC_FAR *pcbData,
  258. /* [size_is][size_is][out] */
  259. BYTE __RPC_FAR *__RPC_FAR *ppbData,
  260. /* [in] */ DWORD dwFlags)
  261. {
  262. if( pcbData )
  263. *pcbData = 0;
  264. switch(dwParam)
  265. {
  266. case PST_PP_FLUSH_PW_CACHE:
  267. {
  268. return PST_E_OK;
  269. }
  270. default:
  271. {
  272. return PST_E_NYI;
  273. }
  274. }
  275. }
  276. HRESULT SPSetProvParam(
  277. /* [in] */ PST_PROVIDER_HANDLE* phPSTProv,
  278. /* [in] */ DWORD dwParam,
  279. /* [in] */ DWORD cbData,
  280. /* [in] */ BYTE* pbData,
  281. /* [in] */ DWORD dwFlags)
  282. {
  283. HRESULT hr = PST_E_OK;
  284. switch(dwParam)
  285. {
  286. case PST_PP_FLUSH_PW_CACHE:
  287. {
  288. if(g_pCUAList)
  289. {
  290. g_pCUAList->Reset();
  291. hr = PST_E_OK;
  292. }
  293. else
  294. hr = PST_E_FAIL;
  295. break;
  296. }
  297. default:
  298. {
  299. hr = PST_E_NYI;
  300. break;
  301. }
  302. }
  303. return hr;
  304. }
  305. HRESULT SPEnumTypes(
  306. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  307. /* [in] */ PST_KEY Key,
  308. /* [out] */ GUID *pguidType,
  309. /* [in] */ DWORD dwIndex,
  310. /* [in] */ DWORD dwFlags)
  311. {
  312. HRESULT dwRet = PST_E_FAIL;
  313. LPWSTR szUser = NULL;
  314. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  315. {
  316. dwRet = ERROR_INVALID_PARAMETER;
  317. goto Ret;
  318. }
  319. if (dwFlags)
  320. {
  321. dwRet = PST_E_BAD_FLAGS;
  322. goto Ret;
  323. }
  324. // get current user
  325. if (!FGetCurrentUser(
  326. phPSTProv,
  327. &szUser,
  328. Key))
  329. {
  330. dwRet = (DWORD)PST_E_FAIL;
  331. goto Ret;
  332. }
  333. if (PST_E_OK != (dwRet =
  334. BPEnumTypes(
  335. szUser,
  336. dwIndex,
  337. pguidType)) )
  338. goto Ret;
  339. dwRet = PST_E_OK;
  340. Ret:
  341. if (szUser)
  342. SSFree(szUser);
  343. return dwRet;
  344. }
  345. HRESULT SPGetTypeInfo(
  346. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  347. /* [in] */ PST_KEY Key,
  348. /* [in] */ const GUID *pguidType,
  349. /* [in] */ PPST_TYPEINFO *ppinfoType,
  350. /* [in] */ DWORD dwFlags)
  351. {
  352. PST_TYPEINFO infoType = {sizeof(PST_TYPEINFO)};
  353. *ppinfoType = NULL;
  354. LPWSTR szUser = NULL;
  355. HRESULT dwRet = PST_E_FAIL;
  356. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  357. {
  358. dwRet = ERROR_INVALID_PARAMETER;
  359. goto Ret;
  360. }
  361. if (dwFlags)
  362. {
  363. dwRet = PST_E_BAD_FLAGS;
  364. goto Ret;
  365. }
  366. // get current user
  367. if (!FGetCurrentUser(
  368. phPSTProv,
  369. &szUser,
  370. Key))
  371. {
  372. dwRet = (DWORD)PST_E_FAIL;
  373. goto Ret;
  374. }
  375. if (PST_E_OK != (dwRet =
  376. BPGetTypeName(
  377. szUser,
  378. pguidType,
  379. &infoType.szDisplayName)) )
  380. goto Ret;
  381. dwRet = PST_E_OK;
  382. Ret:
  383. if (dwRet == PST_E_OK)
  384. {
  385. *ppinfoType = (PPST_TYPEINFO)SSAlloc(sizeof(PST_TYPEINFO));
  386. if(NULL != *ppinfoType)
  387. {
  388. CopyMemory(*ppinfoType, &infoType, sizeof(PST_TYPEINFO));
  389. }
  390. }
  391. if (szUser)
  392. SSFree(szUser);
  393. return dwRet;
  394. }
  395. HRESULT SPEnumSubtypes(
  396. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  397. /* [in] */ PST_KEY Key,
  398. /* [in] */ const GUID *pguidType,
  399. /* [out] */ GUID *pguidSubtype,
  400. /* [in] */ DWORD dwIndex,
  401. /* [in] */ DWORD dwFlags)
  402. {
  403. HRESULT dwRet = PST_E_FAIL;
  404. LPWSTR szUser = NULL;
  405. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  406. {
  407. dwRet = ERROR_INVALID_PARAMETER;
  408. goto Ret;
  409. }
  410. if (dwFlags)
  411. {
  412. dwRet = PST_E_BAD_FLAGS;
  413. goto Ret;
  414. }
  415. // get current user
  416. if (!FGetCurrentUser(
  417. phPSTProv,
  418. &szUser,
  419. Key))
  420. {
  421. dwRet = (DWORD)PST_E_FAIL;
  422. goto Ret;
  423. }
  424. if (PST_E_OK != (dwRet =
  425. BPEnumSubtypes(
  426. szUser,
  427. dwIndex,
  428. pguidType,
  429. pguidSubtype)) )
  430. goto Ret;
  431. dwRet = PST_E_OK;
  432. Ret:
  433. if (szUser)
  434. SSFree(szUser);
  435. return dwRet;
  436. }
  437. HRESULT SPGetSubtypeInfo(
  438. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  439. /* [in] */ PST_KEY Key,
  440. /* [in] */ const GUID *pguidType,
  441. /* [in] */ const GUID *pguidSubtype,
  442. /* [in] */ PPST_TYPEINFO *ppinfoSubtype,
  443. /* [in] */ DWORD dwFlags)
  444. {
  445. *ppinfoSubtype = NULL;
  446. PST_TYPEINFO infoSubtype = {sizeof(PST_TYPEINFO)};
  447. LPWSTR szUser = NULL;
  448. HRESULT dwRet = PST_E_FAIL;
  449. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  450. {
  451. dwRet = ERROR_INVALID_PARAMETER;
  452. goto Ret;
  453. }
  454. if (dwFlags)
  455. {
  456. dwRet = PST_E_BAD_FLAGS;
  457. goto Ret;
  458. }
  459. // get current user
  460. if (!FGetCurrentUser(
  461. phPSTProv,
  462. &szUser,
  463. Key))
  464. {
  465. dwRet = (DWORD)PST_E_FAIL;
  466. goto Ret;
  467. }
  468. if (PST_E_OK != (dwRet =
  469. BPGetSubtypeName(
  470. szUser,
  471. pguidType,
  472. pguidSubtype,
  473. &infoSubtype.szDisplayName)) )
  474. goto Ret;
  475. dwRet = PST_E_OK;
  476. Ret:
  477. if (dwRet == PST_E_OK)
  478. {
  479. *ppinfoSubtype = (PPST_TYPEINFO)SSAlloc(sizeof(PST_TYPEINFO));
  480. if(NULL != *ppinfoSubtype)
  481. {
  482. CopyMemory(*ppinfoSubtype, &infoSubtype, sizeof(PST_TYPEINFO));
  483. }
  484. }
  485. if (szUser)
  486. SSFree(szUser);
  487. return dwRet;
  488. }
  489. HRESULT SPEnumItems(
  490. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  491. /* [in] */ PST_KEY Key,
  492. /* [in] */ const GUID *pguidType,
  493. /* [in] */ const GUID *pguidSubtype,
  494. /* [out] */ LPWSTR *ppszItemName,
  495. /* [in] */ DWORD dwIndex,
  496. /* [in] */ DWORD dwFlags)
  497. {
  498. HRESULT dwRet = PST_E_FAIL;
  499. LPWSTR szUser = NULL;
  500. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  501. {
  502. dwRet = ERROR_INVALID_PARAMETER;
  503. goto Ret;
  504. }
  505. if (dwFlags)
  506. {
  507. dwRet = PST_E_BAD_FLAGS;
  508. goto Ret;
  509. }
  510. // get current user
  511. if (!FGetCurrentUser(
  512. phPSTProv,
  513. &szUser,
  514. Key))
  515. {
  516. dwRet = (DWORD)PST_E_FAIL;
  517. goto Ret;
  518. }
  519. if (PST_E_OK != (dwRet =
  520. BPEnumItems(
  521. szUser,
  522. pguidType,
  523. pguidSubtype,
  524. dwIndex,
  525. ppszItemName)) )
  526. goto Ret;
  527. dwRet = PST_E_OK;
  528. Ret:
  529. if (szUser)
  530. SSFree(szUser);
  531. return dwRet;
  532. }
  533. HRESULT SPCreateType(
  534. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  535. /* [in] */ PST_KEY Key,
  536. /* [in] */ const GUID *pguidType,
  537. /* [in] */ PPST_TYPEINFO pinfoType,
  538. /* [in] */ DWORD dwFlags)
  539. {
  540. HRESULT dwRet = PST_E_FAIL;
  541. LPWSTR szUser = NULL;
  542. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  543. {
  544. dwRet = ERROR_INVALID_PARAMETER;
  545. goto Ret;
  546. }
  547. if (dwFlags)
  548. {
  549. dwRet = PST_E_BAD_FLAGS;
  550. goto Ret;
  551. }
  552. // Check for invalid "" input
  553. if (pinfoType == NULL ||
  554. pinfoType->szDisplayName == NULL ||
  555. (wcslen(pinfoType->szDisplayName) == 0)
  556. )
  557. {
  558. dwRet = ERROR_INVALID_PARAMETER;
  559. goto Ret;
  560. }
  561. if (!FGetCurrentUser(
  562. phPSTProv,
  563. &szUser,
  564. Key))
  565. {
  566. dwRet = (DWORD)PST_E_FAIL;
  567. goto Ret;
  568. }
  569. // if fail or already exist, fail!
  570. if (PST_E_OK != (dwRet =
  571. BPCreateType(
  572. szUser,
  573. pguidType,
  574. pinfoType)) )
  575. goto Ret;
  576. dwRet = PST_E_OK;
  577. Ret:
  578. // if creation didn't happen, item shouldn't exist
  579. if ((dwRet != PST_E_OK) && (dwRet != PST_E_TYPE_EXISTS))
  580. BPDeleteType(szUser, pguidType);
  581. if (szUser)
  582. SSFree(szUser);
  583. return dwRet;
  584. }
  585. HRESULT SPDeleteType(
  586. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  587. /* [in] */ PST_KEY Key,
  588. /* [in] */ const GUID __RPC_FAR *pguidType,
  589. /* [in] */ DWORD dwFlags)
  590. {
  591. HRESULT dwRet = PST_E_FAIL;
  592. LPWSTR szUser = NULL;
  593. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  594. {
  595. dwRet = ERROR_INVALID_PARAMETER;
  596. goto Ret;
  597. }
  598. if (dwFlags)
  599. {
  600. dwRet = PST_E_BAD_FLAGS;
  601. goto Ret;
  602. }
  603. if (!FGetCurrentUser(
  604. phPSTProv,
  605. &szUser,
  606. Key))
  607. {
  608. dwRet = (DWORD)PST_E_FAIL;
  609. goto Ret;
  610. }
  611. // if fail or not empty, fail!
  612. if (PST_E_OK != (dwRet =
  613. BPDeleteType(
  614. szUser,
  615. pguidType)) )
  616. goto Ret;
  617. dwRet = PST_E_OK;
  618. Ret:
  619. if (szUser)
  620. SSFree(szUser);
  621. return dwRet;
  622. }
  623. HRESULT SPCreateSubtype(
  624. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  625. /* [in] */ PST_KEY Key,
  626. /* [in] */ const GUID *pguidType,
  627. /* [in] */ const GUID *pguidSubtype,
  628. /* [in] */ PPST_TYPEINFO pinfoSubtype,
  629. /* [in] */ PPST_ACCESSRULESET psRules,
  630. /* [in] */ DWORD dwFlags)
  631. {
  632. HRESULT dwRet = PST_E_FAIL;
  633. LPWSTR szUser = NULL;
  634. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  635. {
  636. dwRet = ERROR_INVALID_PARAMETER;
  637. goto Ret;
  638. }
  639. if (dwFlags != 0)
  640. {
  641. dwRet = PST_E_BAD_FLAGS;
  642. goto Ret;
  643. }
  644. // NULL Rules
  645. if (psRules == NULL)
  646. {
  647. dwRet = PST_E_INVALID_RULESET;
  648. goto Ret;
  649. }
  650. if (pinfoSubtype == NULL)
  651. {
  652. dwRet = ERROR_INVALID_PARAMETER;
  653. goto Ret;
  654. }
  655. // Check for invalid "" input
  656. if (pinfoSubtype->szDisplayName == NULL || wcslen(pinfoSubtype->szDisplayName) == 0)
  657. {
  658. dwRet = ERROR_INVALID_PARAMETER;
  659. goto Ret;
  660. }
  661. if (!FGetCurrentUser(
  662. phPSTProv,
  663. &szUser,
  664. Key))
  665. {
  666. dwRet = (DWORD)PST_E_FAIL;
  667. goto Ret;
  668. }
  669. // if fail or already exist, fail!
  670. if (PST_E_OK != (dwRet =
  671. BPCreateSubtype(
  672. szUser,
  673. pguidType,
  674. pguidSubtype,
  675. pinfoSubtype)) )
  676. goto Ret;
  677. dwRet = PST_E_OK;
  678. Ret:
  679. // if creation didn't happen, item shouldn't exist
  680. if ((dwRet != PST_E_OK) && (dwRet != PST_E_TYPE_EXISTS))
  681. BPDeleteSubtype(szUser, pguidType, pguidSubtype);
  682. if (szUser)
  683. SSFree(szUser);
  684. return dwRet;
  685. }
  686. HRESULT SPDeleteSubtype(
  687. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  688. /* [in] */ PST_KEY Key,
  689. /* [in] */ const GUID __RPC_FAR *pguidType,
  690. /* [in] */ const GUID __RPC_FAR *pguidSubtype,
  691. /* [in] */ DWORD dwFlags)
  692. {
  693. HRESULT dwRet = PST_E_FAIL;
  694. LPWSTR szUser = NULL;
  695. PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
  696. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  697. {
  698. dwRet = ERROR_INVALID_PARAMETER;
  699. goto Ret;
  700. }
  701. if (dwFlags)
  702. {
  703. dwRet = PST_E_BAD_FLAGS;
  704. goto Ret;
  705. }
  706. // get current user
  707. if (!FGetCurrentUser(
  708. phPSTProv,
  709. &szUser,
  710. Key))
  711. {
  712. dwRet = (DWORD)PST_E_FAIL;
  713. goto Ret;
  714. }
  715. // if fail or not empty, fail!
  716. if (PST_E_OK != (dwRet =
  717. BPDeleteSubtype(
  718. szUser,
  719. pguidType,
  720. pguidSubtype)) )
  721. goto Ret;
  722. dwRet = PST_E_OK;
  723. Ret:
  724. if (szUser)
  725. SSFree(szUser);
  726. return dwRet;
  727. }
  728. HRESULT SPWriteItem(
  729. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  730. /* [in] */ PST_KEY Key,
  731. /* [in] */ const GUID *pguidType,
  732. /* [in] */ const GUID *pguidSubtype,
  733. /* [in] */ LPCWSTR szItemName,
  734. /* [in] */ DWORD cbData,
  735. /* [size_is][in] */ BYTE *pbData,
  736. /* [in] */ PPST_PROMPTINFO psPrompt,
  737. /* [in] */ DWORD dwDefaultConfirmationStyle,
  738. /* [in] */ DWORD dwFlags)
  739. {
  740. HRESULT dwRet = PST_E_FAIL;
  741. // assume we've made no change
  742. BOOL fExisted = TRUE;
  743. LPWSTR szUser = NULL;
  744. PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
  745. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  746. LPWSTR szMasterKey = NULL;
  747. LPWSTR szType=NULL, szSubtype=NULL;
  748. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  749. {
  750. dwRet = ERROR_INVALID_PARAMETER;
  751. goto Ret;
  752. }
  753. if ((dwFlags & ~(PST_UNRESTRICTED_ITEMDATA | PST_NO_OVERWRITE
  754. )) != 0)
  755. {
  756. dwRet = PST_E_BAD_FLAGS;
  757. goto Ret;
  758. }
  759. if ((dwDefaultConfirmationStyle & ~( PST_CF_DEFAULT |
  760. PST_CF_NONE
  761. )) != 0)
  762. {
  763. dwRet = PST_E_BAD_FLAGS;
  764. goto Ret;
  765. }
  766. if (psPrompt == NULL)
  767. {
  768. dwRet = ERROR_INVALID_PARAMETER;
  769. goto Ret;
  770. }
  771. // Disable UI on write item.
  772. dwDefaultConfirmationStyle = PST_CF_NONE;
  773. if(psPrompt != NULL)
  774. {
  775. psPrompt->dwPromptFlags = 0;
  776. }
  777. // Check for invalid "" input
  778. if (wcslen(szItemName) == 0)
  779. {
  780. dwRet = ERROR_INVALID_PARAMETER;
  781. goto Ret;
  782. }
  783. // get current user
  784. if (!FGetCurrentUser(
  785. phPSTProv,
  786. &szUser,
  787. Key))
  788. {
  789. dwRet = (DWORD)PST_E_FAIL;
  790. goto Ret;
  791. }
  792. if (dwFlags & PST_UNRESTRICTED_ITEMDATA)
  793. {
  794. // store insecure data stream
  795. if (PST_E_OK != (dwRet =
  796. BPSetInsecureItemData(
  797. szUser,
  798. pguidType,
  799. pguidSubtype,
  800. szItemName,
  801. pbData,
  802. cbData)) )
  803. goto Ret;
  804. dwRet = PST_E_OK;
  805. goto Ret;
  806. }
  807. // ELSE: secure stream
  808. {
  809. POPENITEM_LIST_ITEM pli;
  810. OPENITEM_LIST_ITEM li;
  811. if(NULL == g_pCOpenItemList)
  812. {
  813. dwRet = PST_E_FAIL;
  814. goto Ret;
  815. }
  816. CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
  817. g_pCOpenItemList->LockList();
  818. // get opened (cached) item
  819. pli = g_pCOpenItemList->SearchList(&li);
  820. if ((pli != NULL) && (pli->ModeFlags & PST_WRITE) )
  821. {
  822. // Error if cached (it must exist) and "No Overwrite" specified
  823. if (dwFlags & PST_NO_OVERWRITE)
  824. {
  825. g_pCOpenItemList->UnlockList();
  826. dwRet = PST_E_ITEM_EXISTS;
  827. goto Ret;
  828. }
  829. // found cached item; pull real pwd
  830. CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
  831. szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
  832. if( szMasterKey )
  833. wcscpy(szMasterKey, pli->szMasterKey);
  834. //
  835. // unlock list.
  836. //
  837. g_pCOpenItemList->UnlockList();
  838. if( szMasterKey == NULL ) {
  839. dwRet = E_OUTOFMEMORY;
  840. goto Ret;
  841. }
  842. // PST_PF_ALWAYS_SHOW always forces UI
  843. if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
  844. {
  845. // retrieve names of type, subtype
  846. if (PST_E_OK != (dwRet =
  847. BPGetTypeName(
  848. szUser,
  849. pguidType,
  850. &szType)) )
  851. goto Ret;
  852. if (PST_E_OK != (dwRet =
  853. BPGetSubtypeName(
  854. szUser,
  855. pguidType,
  856. pguidSubtype,
  857. &szSubtype)) )
  858. goto Ret;
  859. if (PST_E_OK != (dwRet =
  860. ShowOKCancelUI(
  861. phPSTProv,
  862. szUser,
  863. Key,
  864. szType,
  865. szSubtype,
  866. szItemName,
  867. psPrompt,
  868. g_PromptWriteItem)) )
  869. goto Ret;
  870. }
  871. }
  872. else
  873. {
  874. //
  875. // unlock list.
  876. //
  877. g_pCOpenItemList->UnlockList();
  878. // not cached; do actual work
  879. // if fail or already exist
  880. if (PST_E_OK != (dwRet =
  881. BPCreateItem(
  882. szUser,
  883. pguidType,
  884. pguidSubtype,
  885. szItemName)) )
  886. {
  887. // on "No Overwrite", hr has right error code
  888. if (dwFlags & PST_NO_OVERWRITE)
  889. goto Ret;
  890. // else swallow overwrite error
  891. if (dwRet != PST_E_ITEM_EXISTS)
  892. goto Ret;
  893. }
  894. fExisted = (dwRet == PST_E_ITEM_EXISTS);
  895. // retrieve names of type, subtype
  896. if (PST_E_OK != (dwRet =
  897. BPGetTypeName(
  898. szUser,
  899. pguidType,
  900. &szType)) )
  901. goto Ret;
  902. if (PST_E_OK != (dwRet =
  903. BPGetSubtypeName(
  904. szUser,
  905. pguidType,
  906. pguidSubtype,
  907. &szSubtype)) )
  908. goto Ret;
  909. // does ALL user confirm work
  910. if (PST_E_OK != (dwRet =
  911. GetUserConfirmBuf(
  912. phPSTProv,
  913. szUser,
  914. Key,
  915. szType,
  916. pguidType,
  917. szSubtype,
  918. pguidSubtype,
  919. szItemName,
  920. psPrompt,
  921. g_PromptWriteItem,
  922. dwDefaultConfirmationStyle,
  923. &szMasterKey,
  924. rgbPwd,
  925. 0)) )
  926. goto Ret;
  927. }
  928. }
  929. // store the data itself
  930. if (!FBPSetSecuredItemData(
  931. szUser,
  932. szMasterKey,
  933. rgbPwd,
  934. pguidType,
  935. pguidSubtype,
  936. szItemName,
  937. pbData,
  938. cbData))
  939. {
  940. dwRet = PST_E_STORAGE_ERROR;
  941. goto Ret;
  942. }
  943. dwRet = PST_E_OK;
  944. Ret:
  945. // if creation didn't happen, item shouldn't exist
  946. if ((dwRet != PST_E_OK) && (!fExisted))
  947. BPDeleteItem(szUser, pguidType, pguidSubtype, szItemName);
  948. if (szMasterKey)
  949. SSFree(szMasterKey);
  950. if (szUser)
  951. SSFree(szUser);
  952. if (szType)
  953. SSFree(szType);
  954. if (szSubtype)
  955. SSFree(szSubtype);
  956. return dwRet;
  957. }
  958. HRESULT SPReadItem(
  959. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  960. /* [in] */ PST_KEY Key,
  961. /* [in] */ const GUID *pguidType,
  962. /* [in] */ const GUID *pguidSubtype,
  963. /* [in] */ LPCWSTR szItemName,
  964. /* [out] */ DWORD *pcbData,
  965. /* [size_is][size_is][out] */ BYTE **ppbData,
  966. /* [in] */ PPST_PROMPTINFO psPrompt,
  967. /* [in] */ DWORD dwFlags)
  968. {
  969. HRESULT dwRet = PST_E_FAIL;
  970. PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
  971. LPWSTR szUser = NULL;
  972. LPWSTR szMasterKey = NULL;
  973. LPWSTR szCallerName = NULL;
  974. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  975. LPWSTR szType=NULL, szSubtype=NULL;
  976. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  977. {
  978. dwRet = ERROR_INVALID_PARAMETER;
  979. goto Ret;
  980. }
  981. if ((dwFlags & ~(PST_UNRESTRICTED_ITEMDATA | PST_PROMPT_QUERY |
  982. PST_NO_UI_MIGRATION
  983. )) != 0)
  984. {
  985. dwRet = PST_E_BAD_FLAGS;
  986. goto Ret;
  987. }
  988. // Disable unnecessary UI.
  989. dwFlags |= PST_NO_UI_MIGRATION;
  990. if (psPrompt == NULL)
  991. {
  992. dwRet = ERROR_INVALID_PARAMETER;
  993. goto Ret;
  994. }
  995. // Check for invalid "" input
  996. if (wcslen(szItemName) == 0)
  997. {
  998. dwRet = ERROR_INVALID_PARAMETER;
  999. goto Ret;
  1000. }
  1001. // get current user
  1002. if (!FGetCurrentUser(
  1003. phPSTProv,
  1004. &szUser,
  1005. Key))
  1006. {
  1007. dwRet = (DWORD)PST_E_FAIL;
  1008. goto Ret;
  1009. }
  1010. if (dwFlags & PST_UNRESTRICTED_ITEMDATA)
  1011. {
  1012. // read insecure data stream
  1013. if (PST_E_OK != (dwRet =
  1014. BPGetInsecureItemData(
  1015. szUser,
  1016. pguidType,
  1017. pguidSubtype,
  1018. szItemName,
  1019. ppbData,
  1020. pcbData)) )
  1021. goto Ret;
  1022. dwRet = PST_E_OK;
  1023. goto Ret;
  1024. }
  1025. // ELSE: secure stream
  1026. {
  1027. POPENITEM_LIST_ITEM pli;
  1028. OPENITEM_LIST_ITEM li;
  1029. if(NULL == g_pCOpenItemList)
  1030. {
  1031. dwRet = PST_E_FAIL;
  1032. goto Ret;
  1033. }
  1034. CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
  1035. g_pCOpenItemList->LockList();
  1036. // get opened (cached) item
  1037. pli = g_pCOpenItemList->SearchList(&li);
  1038. if ((pli != NULL) && (pli->ModeFlags & PST_READ))
  1039. {
  1040. // found cached item; pull pwd
  1041. CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
  1042. szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
  1043. if( szMasterKey )
  1044. wcscpy(szMasterKey, pli->szMasterKey);
  1045. //
  1046. // unlock list.
  1047. //
  1048. g_pCOpenItemList->UnlockList();
  1049. if( szMasterKey == NULL ) {
  1050. dwRet = E_OUTOFMEMORY;
  1051. goto Ret;
  1052. }
  1053. // PST_PF_ALWAYS_SHOW always forces UI
  1054. if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
  1055. {
  1056. // retrieve names of type, subtype
  1057. if (PST_E_OK != (dwRet =
  1058. BPGetTypeName(
  1059. szUser,
  1060. pguidType,
  1061. &szType)) )
  1062. goto Ret;
  1063. if (PST_E_OK != (dwRet =
  1064. BPGetSubtypeName(
  1065. szUser,
  1066. pguidType,
  1067. pguidSubtype,
  1068. &szSubtype)) )
  1069. goto Ret;
  1070. if (PST_E_OK != (dwRet =
  1071. ShowOKCancelUI(
  1072. phPSTProv,
  1073. szUser,
  1074. Key,
  1075. szType,
  1076. szSubtype,
  1077. szItemName,
  1078. psPrompt,
  1079. g_PromptReadItem)) )
  1080. goto Ret;
  1081. }
  1082. }
  1083. else
  1084. {
  1085. //
  1086. // unlock list.
  1087. //
  1088. g_pCOpenItemList->UnlockList();
  1089. // not cached; do actual work
  1090. // retrieve names of type, subtype
  1091. if (PST_E_OK != (dwRet =
  1092. BPGetTypeName(
  1093. szUser,
  1094. pguidType,
  1095. &szType)) )
  1096. goto Ret;
  1097. if (PST_E_OK != (dwRet =
  1098. BPGetSubtypeName(
  1099. szUser,
  1100. pguidType,
  1101. pguidSubtype,
  1102. &szSubtype)) )
  1103. goto Ret;
  1104. // does ALL user confirm work
  1105. if (PST_E_OK != (dwRet =
  1106. GetUserConfirmBuf(
  1107. phPSTProv,
  1108. szUser,
  1109. Key,
  1110. szType,
  1111. pguidType,
  1112. szSubtype,
  1113. pguidSubtype,
  1114. szItemName,
  1115. psPrompt,
  1116. g_PromptReadItem,
  1117. &szMasterKey,
  1118. rgbPwd,
  1119. dwFlags)) )
  1120. goto Ret;
  1121. }
  1122. }
  1123. // if checked out, then actually retrieve item
  1124. if (!FBPGetSecuredItemData(
  1125. szUser,
  1126. szMasterKey,
  1127. rgbPwd,
  1128. pguidType,
  1129. pguidSubtype,
  1130. szItemName,
  1131. ppbData,
  1132. pcbData))
  1133. {
  1134. dwRet = PST_E_STORAGE_ERROR;
  1135. goto Ret;
  1136. }
  1137. dwRet = PST_E_OK;
  1138. Ret:
  1139. //
  1140. // see if caller requested UI disposition on item.
  1141. //
  1142. if( dwRet == PST_E_OK && dwFlags & PST_PROMPT_QUERY ) {
  1143. DWORD dwStoredConfirm;
  1144. LPWSTR pszMasterKey;
  1145. DWORD dwRetVal;
  1146. dwRetVal = BPGetItemConfirm(
  1147. phPSTProv,
  1148. szUser,
  1149. pguidType,
  1150. pguidSubtype,
  1151. szItemName,
  1152. &dwStoredConfirm,
  1153. &pszMasterKey
  1154. );
  1155. if( dwRetVal == PST_E_OK ) {
  1156. SSFree( pszMasterKey );
  1157. if( !(dwStoredConfirm & BP_CONFIRM_NONE) ) {
  1158. if(FIsProviderUIAllowed( szUser ))
  1159. dwRet = PST_E_ITEM_EXISTS;
  1160. }
  1161. }
  1162. }
  1163. if (szUser)
  1164. SSFree(szUser);
  1165. if (szMasterKey)
  1166. SSFree(szMasterKey);
  1167. if (szType)
  1168. SSFree(szType);
  1169. if (szSubtype)
  1170. SSFree(szSubtype);
  1171. if (szCallerName)
  1172. SSFree(szCallerName);
  1173. return dwRet;
  1174. }
  1175. HRESULT SPDeleteItem(
  1176. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  1177. /* [in] */ PST_KEY Key,
  1178. /* [in] */ const GUID *pguidType,
  1179. /* [in] */ const GUID *pguidSubtype,
  1180. /* [in] */ LPCWSTR szItemName,
  1181. /* [in] */ PPST_PROMPTINFO psPrompt,
  1182. /* [in] */ DWORD dwFlags)
  1183. {
  1184. HRESULT dwRet = PST_E_FAIL;
  1185. PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
  1186. LPWSTR szUser = NULL;
  1187. LPWSTR szMasterKey = NULL;
  1188. LPWSTR szCallerName = NULL;
  1189. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1190. LPWSTR szType=NULL, szSubtype=NULL;
  1191. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  1192. {
  1193. dwRet = ERROR_INVALID_PARAMETER;
  1194. goto Ret;
  1195. }
  1196. if (dwFlags & ~(PST_NO_UI_MIGRATION))
  1197. {
  1198. dwRet = PST_E_BAD_FLAGS;
  1199. goto Ret;
  1200. }
  1201. // Disable unnecessary UI.
  1202. dwFlags |= PST_NO_UI_MIGRATION;
  1203. if (psPrompt == NULL)
  1204. {
  1205. dwRet = ERROR_INVALID_PARAMETER;
  1206. goto Ret;
  1207. }
  1208. // Check for invalid "" input
  1209. if (wcslen(szItemName) == 0)
  1210. {
  1211. dwRet = ERROR_INVALID_PARAMETER;
  1212. goto Ret;
  1213. }
  1214. // get current user
  1215. if (!FGetCurrentUser(
  1216. phPSTProv,
  1217. &szUser,
  1218. Key))
  1219. {
  1220. dwRet = (DWORD)PST_E_FAIL;
  1221. goto Ret;
  1222. }
  1223. {
  1224. POPENITEM_LIST_ITEM pli;
  1225. OPENITEM_LIST_ITEM li;
  1226. if(NULL == g_pCOpenItemList)
  1227. {
  1228. dwRet = PST_E_FAIL;
  1229. goto Ret;
  1230. }
  1231. CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
  1232. g_pCOpenItemList->LockList();
  1233. // get opened (cached) item
  1234. pli = g_pCOpenItemList->SearchList(&li);
  1235. if ((pli != NULL) && (pli->ModeFlags & PST_WRITE))
  1236. {
  1237. // found cached item; pull pwd
  1238. CopyMemory(rgbPwd, pli->rgbPwd, A_SHA_DIGEST_LEN);
  1239. szMasterKey = (LPWSTR) SSAlloc(WSZ_BYTECOUNT(pli->szMasterKey));
  1240. if( szMasterKey )
  1241. wcscpy(szMasterKey, pli->szMasterKey);
  1242. g_pCOpenItemList->UnlockList();
  1243. if( szMasterKey == NULL ) {
  1244. dwRet = E_OUTOFMEMORY;
  1245. goto Ret;
  1246. }
  1247. // PST_PF_ALWAYS_SHOW always forces UI
  1248. if (PST_PF_ALWAYS_SHOW == psPrompt->dwPromptFlags)
  1249. {
  1250. // retrieve names of type, subtype
  1251. if (PST_E_OK != (dwRet =
  1252. BPGetTypeName(
  1253. szUser,
  1254. pguidType,
  1255. &szType)) )
  1256. goto Ret;
  1257. if (PST_E_OK != (dwRet =
  1258. BPGetSubtypeName(
  1259. szUser,
  1260. pguidType,
  1261. pguidSubtype,
  1262. &szSubtype)) )
  1263. goto Ret;
  1264. if (PST_E_OK != (dwRet =
  1265. ShowOKCancelUI(
  1266. phPSTProv,
  1267. szUser,
  1268. Key,
  1269. szType,
  1270. szSubtype,
  1271. szItemName,
  1272. psPrompt,
  1273. g_PromptDeleteItem)) )
  1274. goto Ret;
  1275. }
  1276. }
  1277. else
  1278. {
  1279. //
  1280. // unlock list.
  1281. //
  1282. g_pCOpenItemList->UnlockList();
  1283. // retrieve names of type, subtype
  1284. if (PST_E_OK != (dwRet =
  1285. BPGetTypeName(
  1286. szUser,
  1287. pguidType,
  1288. &szType)) )
  1289. goto Ret;
  1290. if (PST_E_OK != (dwRet =
  1291. BPGetSubtypeName(
  1292. szUser,
  1293. pguidType,
  1294. pguidSubtype,
  1295. &szSubtype)) )
  1296. goto Ret;
  1297. // does ALL user confirm work
  1298. if (PST_E_OK != (dwRet =
  1299. GetUserConfirmBuf(
  1300. phPSTProv,
  1301. szUser,
  1302. Key,
  1303. szType,
  1304. pguidType,
  1305. szSubtype,
  1306. pguidSubtype,
  1307. szItemName,
  1308. psPrompt,
  1309. g_PromptDeleteItem,
  1310. &szMasterKey,
  1311. rgbPwd,
  1312. dwFlags)) )
  1313. goto Ret;
  1314. }
  1315. }
  1316. // if checked out, then actually remove item
  1317. if (PST_E_OK != (dwRet =
  1318. BPDeleteItem(
  1319. szUser,
  1320. pguidType,
  1321. pguidSubtype,
  1322. szItemName)) )
  1323. goto Ret;
  1324. dwRet = PST_E_OK;
  1325. Ret:
  1326. if (szUser)
  1327. SSFree(szUser);
  1328. if (szMasterKey)
  1329. SSFree(szMasterKey);
  1330. if (szType)
  1331. SSFree(szType);
  1332. if (szSubtype)
  1333. SSFree(szSubtype);
  1334. if (szCallerName)
  1335. SSFree(szCallerName);
  1336. return dwRet;
  1337. }
  1338. HRESULT SPOpenItem(
  1339. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  1340. /* [in] */ PST_KEY Key,
  1341. /* [in] */ const GUID *pguidType,
  1342. /* [in] */ const GUID *pguidSubtype,
  1343. /* [in] */ LPCWSTR szItemName,
  1344. /* [in] */ PST_ACCESSMODE ModeFlags,
  1345. /* [in] */ PPST_PROMPTINFO psPrompt,
  1346. /* [in] */ DWORD dwFlags)
  1347. {
  1348. HRESULT dwRet = PST_E_FAIL;
  1349. PST_ACCESSRULESET sRules = {sizeof(sRules), 0, NULL};
  1350. LPWSTR szUser = NULL;
  1351. LPWSTR szMasterKey = NULL;
  1352. LPWSTR szCallerName = NULL;
  1353. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1354. LPWSTR szType=NULL, szSubtype=NULL;
  1355. POPENITEM_LIST_ITEM pli = NULL;
  1356. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  1357. {
  1358. dwRet = ERROR_INVALID_PARAMETER;
  1359. goto Ret;
  1360. }
  1361. if (dwFlags)
  1362. {
  1363. dwRet = PST_E_BAD_FLAGS;
  1364. goto Ret;
  1365. }
  1366. if(psPrompt == NULL)
  1367. {
  1368. dwRet = ERROR_INVALID_PARAMETER;
  1369. goto Ret;
  1370. }
  1371. // Check for invalid "" input
  1372. if (wcslen(szItemName) == 0)
  1373. {
  1374. dwRet = ERROR_INVALID_PARAMETER;
  1375. goto Ret;
  1376. }
  1377. // check for item already open
  1378. {
  1379. OPENITEM_LIST_ITEM li;
  1380. if(NULL == g_pCOpenItemList)
  1381. {
  1382. dwRet = PST_E_FAIL;
  1383. goto Ret;
  1384. }
  1385. CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
  1386. // get opened (cached) item
  1387. pli = g_pCOpenItemList->SearchList(&li);
  1388. if (pli != NULL)
  1389. {
  1390. // item already cached; error!
  1391. dwRet = (DWORD)PST_E_ALREADY_OPEN;
  1392. goto Ret;
  1393. }
  1394. }
  1395. // get current user
  1396. if (!FGetCurrentUser(
  1397. phPSTProv,
  1398. &szUser,
  1399. Key))
  1400. {
  1401. dwRet = (DWORD)PST_E_FAIL;
  1402. goto Ret;
  1403. }
  1404. // retrieve names of type, subtype
  1405. if (PST_E_OK != (dwRet =
  1406. BPGetTypeName(
  1407. szUser,
  1408. pguidType,
  1409. &szType)) )
  1410. goto Ret;
  1411. if (PST_E_OK != (dwRet =
  1412. BPGetSubtypeName(
  1413. szUser,
  1414. pguidType,
  1415. pguidSubtype,
  1416. &szSubtype)) )
  1417. goto Ret;
  1418. // does ALL user confirm work
  1419. if (PST_E_OK != (dwRet =
  1420. GetUserConfirmBuf(
  1421. phPSTProv,
  1422. szUser,
  1423. Key,
  1424. szType,
  1425. pguidType,
  1426. szSubtype,
  1427. pguidSubtype,
  1428. szItemName,
  1429. psPrompt,
  1430. g_PromptOpenItem,
  1431. &szMasterKey,
  1432. rgbPwd,
  1433. 0)) )
  1434. goto Ret;
  1435. // if checked out, then add to open item list
  1436. pli = (POPENITEM_LIST_ITEM) SSAlloc(sizeof(OPENITEM_LIST_ITEM));
  1437. if(NULL == pli)
  1438. {
  1439. dwRet = PST_E_FAIL;
  1440. goto Ret;
  1441. }
  1442. // fill in contents
  1443. CreateOpenListItem(pli, phPSTProv, Key, pguidType, pguidSubtype, NULL);
  1444. pli->szItemName = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szItemName));
  1445. wcscpy(pli->szItemName, szItemName);
  1446. pli->szMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szMasterKey));
  1447. wcscpy(pli->szMasterKey, szMasterKey);
  1448. CopyMemory(pli->rgbPwd, rgbPwd, A_SHA_DIGEST_LEN);
  1449. pli->ModeFlags = ModeFlags;
  1450. // add to the open list
  1451. g_pCOpenItemList->AddToList(pli);
  1452. dwRet = PST_E_OK;
  1453. Ret:
  1454. if (szUser)
  1455. SSFree(szUser);
  1456. if (szMasterKey)
  1457. SSFree(szMasterKey);
  1458. if (szType)
  1459. SSFree(szType);
  1460. if (szSubtype)
  1461. SSFree(szSubtype);
  1462. if (szCallerName)
  1463. SSFree(szCallerName);
  1464. return dwRet;
  1465. }
  1466. HRESULT SPCloseItem(
  1467. /* [in] */ PST_PROVIDER_HANDLE *phPSTProv,
  1468. /* [in] */ PST_KEY Key,
  1469. /* [in] */ const GUID *pguidType,
  1470. /* [in] */ const GUID *pguidSubtype,
  1471. /* [in] */ LPCWSTR szItemName,
  1472. /* [in] */ DWORD dwFlags)
  1473. {
  1474. HRESULT dwRet = PST_E_FAIL;
  1475. if (Key & ~(PST_KEY_CURRENT_USER | PST_KEY_LOCAL_MACHINE))
  1476. {
  1477. dwRet = ERROR_INVALID_PARAMETER;
  1478. goto Ret;
  1479. }
  1480. if (dwFlags)
  1481. {
  1482. dwRet = PST_E_BAD_FLAGS;
  1483. goto Ret;
  1484. }
  1485. // Check for invalid "" input
  1486. if (wcslen(szItemName) == 0)
  1487. {
  1488. dwRet = ERROR_INVALID_PARAMETER;
  1489. goto Ret;
  1490. }
  1491. // if item found in list, remove it
  1492. OPENITEM_LIST_ITEM li;
  1493. if(NULL == g_pCOpenItemList)
  1494. {
  1495. dwRet = PST_E_FAIL;
  1496. goto Ret;
  1497. }
  1498. CreateOpenListItem(&li, phPSTProv, Key, pguidType, pguidSubtype, szItemName);
  1499. if (!g_pCOpenItemList->DelFromList(&li))
  1500. {
  1501. dwRet = PST_E_NOT_OPEN;
  1502. goto Ret;
  1503. }
  1504. dwRet = PST_E_OK;
  1505. Ret:
  1506. return dwRet;
  1507. }
  1508. ///////////////////////////////////////////////////
  1509. // FInitProtectAPIGlobals
  1510. //
  1511. // Checks for registry overrides for some default values
  1512. // registry entries can change what algs are being used,
  1513. // as well as what provider is used.
  1514. BOOL FInitProtectAPIGlobals()
  1515. {
  1516. HKEY hProtectKey = NULL;
  1517. HKEY hProviderKey = NULL;
  1518. DWORD dwTemp, dwType, cbSize;
  1519. DWORD dwCreate;
  1520. static const WCHAR szProtectKeyName[] = REG_CRYPTPROTECT_LOC;
  1521. static const WCHAR szProviderKeyName[] = L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC L"\\" CRYPTPROTECT_DEFAULT_PROVIDER_GUIDSZ ;
  1522. LONG lRet;
  1523. //
  1524. // get password cache policy setting.
  1525. //
  1526. lRet = RegOpenKeyExU(
  1527. HKEY_LOCAL_MACHINE,
  1528. L"Software\\Policies\\Microsoft\\Cryptography\\Protect",
  1529. 0,
  1530. KEY_QUERY_VALUE,
  1531. &hProtectKey
  1532. );
  1533. if( lRet == ERROR_SUCCESS ) {
  1534. DWORD cbSize;
  1535. DWORD dwTemp;
  1536. DWORD dwType;
  1537. //
  1538. // query EnableCachePW value.
  1539. //
  1540. cbSize = sizeof(DWORD);
  1541. lRet = RegQueryValueExU(
  1542. hProtectKey,
  1543. REG_CRYPTPROTECT_ALLOW_CACHEPW,
  1544. NULL,
  1545. &dwType,
  1546. (PBYTE)&dwTemp,
  1547. &cbSize
  1548. );
  1549. if( lRet == ERROR_SUCCESS &&
  1550. dwType == REG_DWORD &&
  1551. dwTemp == 0 // 0 == disablePW cache
  1552. ) {
  1553. g_fAllowCachePW = FALSE;
  1554. } else {
  1555. g_fAllowCachePW = TRUE;
  1556. }
  1557. RegCloseKey( hProtectKey );
  1558. hProtectKey = NULL;
  1559. } else {
  1560. g_fAllowCachePW = TRUE;
  1561. }
  1562. return TRUE;
  1563. }