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.

3042 lines
74 KiB

  1. #include <pch.cpp>
  2. #pragma hdrstop
  3. #include "guidcnvt.h"
  4. #include "passwd.h"
  5. #include "storage.h"
  6. extern DISPIF_CALLBACKS g_sCallbacks;
  7. // note: REG_PSTTREE_LOC moved to pstprv.h
  8. #define REG_DATA_LOC L"Data"
  9. #define REG_MK_LOC L"Data 2"
  10. #define REG_ACCESSRULE_LOC L"Access Rules"
  11. #define REG_DISPLAYSTRING_VALNAME L"Display String"
  12. #define REG_USER_INTERNAL_MAC_KEY L"Blocking"
  13. #define REG_ITEM_SECURE_DATA_VALNAME L"Item Data"
  14. #define REG_ITEM_INSECURE_DATA_VALNAME L"Insecure Data"
  15. #define REG_ITEM_MK_VALNAME L"Behavior"
  16. #define REG_SECURITY_SALT_VALNAME L"Value"
  17. ///////////////////////////////////////////////////////////////////////
  18. ///////////////////////////////////////////////////////////////////////
  19. // PRIMITIVIES for snagging registry keys
  20. DWORD GetPSTUserHKEY(LPCWSTR szUser, HKEY* phUserKey, BOOL* pfExisted)
  21. {
  22. HKEY hKeyBase = NULL;
  23. DWORD dwRet = (DWORD)PST_E_STORAGE_ERROR;
  24. DWORD dwCreate;
  25. DWORD cbKeyName;
  26. LPWSTR szKeyName = NULL;
  27. WCHAR FastBuffer[(sizeof(REG_PSTTREE_LOC) / sizeof(WCHAR)) + 64];
  28. LPWSTR SlowBuffer = NULL;
  29. LPCWSTR szContainer = szUser;
  30. DWORD dwDesiredAccess = KEY_READ | KEY_WRITE;
  31. cbKeyName = sizeof(REG_PSTTREE_LOC) ;
  32. //
  33. // For Win95, we may have an empty or NULL container
  34. // name (szUser), so use a default storage area for
  35. // that scenario
  36. //
  37. if(szContainer == NULL || szContainer[0] == L'\0') {
  38. // "*" is an invalid LM username character
  39. szContainer = L"*Default*";
  40. hKeyBase = HKEY_LOCAL_MACHINE;
  41. } else {
  42. //
  43. // see if we should go to HKEY_LOCAL_MACHINE or
  44. // HKEY_CURRENT_USER
  45. //
  46. if( _wcsicmp(WSZ_LOCAL_MACHINE, szContainer) == 0 ) {
  47. // HKEY_LOCAL_MACHINE
  48. hKeyBase = HKEY_LOCAL_MACHINE;
  49. } else {
  50. // HKEY_CURRENT_USER
  51. if(!GetUserHKEY(szContainer, dwDesiredAccess, &hKeyBase)) {
  52. if(FIsWinNT()) {
  53. goto Ret;
  54. }
  55. //
  56. // Win95, profiles may be disabled, so go to
  57. // HKEY_LOCAL_MACHINE\xxx\szContainer
  58. //
  59. hKeyBase = HKEY_LOCAL_MACHINE;
  60. } else {
  61. //
  62. // no container name when going to HKEY_CURRENT_USER
  63. //
  64. //
  65. // sfield: continue to use a container name for HKEY_CURRENT_USER
  66. // because the configuration may be shared, roamable hives
  67. // (mandatators profiles, etc, which we are telling people not
  68. // to use anymore, but never-the-less, this could come up
  69. //
  70. // szContainer = L"\0";
  71. }
  72. }
  73. }
  74. cbKeyName += (lstrlenW(szContainer) * sizeof(WCHAR)) +
  75. sizeof(WCHAR) + // L'\\'
  76. sizeof(WCHAR) ; // terminal NULL
  77. //
  78. // use faster stack based buffer if the material fits
  79. //
  80. if(cbKeyName > sizeof(FastBuffer)) {
  81. SlowBuffer = (LPWSTR)SSAlloc( cbKeyName );
  82. if (SlowBuffer == NULL)
  83. {
  84. dwRet = (DWORD)PST_E_FAIL;
  85. goto Ret;
  86. }
  87. szKeyName = SlowBuffer;
  88. } else {
  89. szKeyName = FastBuffer;
  90. }
  91. wcscpy(szKeyName, REG_PSTTREE_LOC);
  92. //
  93. // work-around bug in RegCreateKeyEx that returns the wrong
  94. // creation disposition if a trailing "\" is in the key name
  95. //
  96. if(szContainer && szContainer[0] != L'\0') {
  97. wcscat(szKeyName, L"\\");
  98. wcscat(szKeyName, szContainer);
  99. }
  100. // Open Base Key //
  101. // get current user, open (REG_PSTTREE_LOC\\CurrentUser)
  102. if (ERROR_SUCCESS !=
  103. RegCreateKeyExU(
  104. hKeyBase,
  105. szKeyName,
  106. 0,
  107. NULL, // address of class string
  108. 0,
  109. dwDesiredAccess,
  110. NULL,
  111. phUserKey,
  112. &dwCreate))
  113. {
  114. goto Ret;
  115. }
  116. if (pfExisted) {
  117. *pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
  118. }
  119. if(dwCreate == REG_CREATED_NEW_KEY && FIsWinNT()) {
  120. //
  121. // WinNT: restrict access to Local System on newly created key.
  122. //
  123. HKEY hKeyWriteDac;
  124. //
  125. // duplicate to WRITE_DAC access key and use that
  126. //
  127. if(ERROR_SUCCESS == RegOpenKeyExW(*phUserKey, NULL, 0, WRITE_DAC, &hKeyWriteDac)) {
  128. SetRegistrySecurity(hKeyWriteDac);
  129. RegCloseKey(hKeyWriteDac);
  130. }
  131. }
  132. dwRet = PST_E_OK;
  133. Ret:
  134. if (SlowBuffer)
  135. SSFree(SlowBuffer);
  136. //
  137. // close the per-user "root" key
  138. //
  139. if(hKeyBase != NULL && hKeyBase != HKEY_LOCAL_MACHINE)
  140. RegCloseKey(hKeyBase);
  141. return dwRet;
  142. }
  143. DWORD GetPSTTypeHKEY(LPCWSTR szUser, const GUID* pguidType, HKEY* phTypeKey)
  144. {
  145. DWORD dwRet;
  146. HKEY hBaseKey = NULL;
  147. HKEY hDataKey = NULL;
  148. CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
  149. // Open User Key //
  150. if (PST_E_OK != (dwRet =
  151. GetPSTUserHKEY(
  152. szUser,
  153. &hBaseKey,
  154. NULL)) )
  155. goto Ret;
  156. // Open Data Key //
  157. if (ERROR_SUCCESS !=
  158. RegOpenKeyExU(
  159. hBaseKey,
  160. REG_DATA_LOC,
  161. 0,
  162. KEY_READ | KEY_WRITE,
  163. &hDataKey))
  164. {
  165. dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
  166. goto Ret;
  167. }
  168. if (PST_E_OK != (dwRet =
  169. MyGuidToStringA(
  170. pguidType,
  171. rgszTypeGuid)) )
  172. goto Ret;
  173. // Open Category Key //
  174. if (ERROR_SUCCESS !=
  175. RegOpenKeyExA(
  176. hDataKey,
  177. rgszTypeGuid,
  178. 0,
  179. KEY_READ | KEY_WRITE,
  180. phTypeKey))
  181. {
  182. dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
  183. goto Ret;
  184. }
  185. dwRet = PST_E_OK;
  186. Ret:
  187. if (hBaseKey)
  188. RegCloseKey(hBaseKey);
  189. if (hDataKey)
  190. RegCloseKey(hDataKey);
  191. return dwRet;
  192. }
  193. DWORD CreatePSTTypeHKEY(LPCWSTR szUser, const GUID* pguidType, HKEY* phTypeKey, BOOL* pfExisted)
  194. {
  195. DWORD dwRet;
  196. DWORD dwCreate;
  197. HKEY hBaseKey = NULL;
  198. HKEY hDataKey = NULL;
  199. CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
  200. // Open User Key //
  201. if (PST_E_OK != (dwRet =
  202. GetPSTUserHKEY(
  203. szUser,
  204. &hBaseKey,
  205. NULL)) )
  206. goto Ret;
  207. // Open Data Key //
  208. if (ERROR_SUCCESS !=
  209. RegCreateKeyExU(
  210. hBaseKey,
  211. REG_DATA_LOC,
  212. 0,
  213. NULL, // address of class string
  214. 0,
  215. KEY_READ | KEY_WRITE,
  216. NULL,
  217. &hDataKey,
  218. &dwCreate))
  219. {
  220. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  221. goto Ret;
  222. }
  223. if (PST_E_OK != (dwRet =
  224. MyGuidToStringA(
  225. pguidType,
  226. rgszTypeGuid)) )
  227. goto Ret;
  228. // Open Category Key //
  229. if (ERROR_SUCCESS !=
  230. RegCreateKeyExA(
  231. hDataKey,
  232. rgszTypeGuid,
  233. 0,
  234. NULL, // address of class string
  235. 0,
  236. KEY_READ | KEY_WRITE,
  237. NULL,
  238. phTypeKey,
  239. &dwCreate))
  240. {
  241. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  242. goto Ret;
  243. }
  244. if (pfExisted)
  245. *pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
  246. dwRet = PST_E_OK;
  247. Ret:
  248. if (hBaseKey)
  249. RegCloseKey(hBaseKey);
  250. if (hDataKey)
  251. RegCloseKey(hDataKey);
  252. return dwRet;
  253. }
  254. DWORD GetPSTMasterKeyHKEY(LPCWSTR szUser, LPCWSTR szMasterKey, HKEY* phMyKey)
  255. {
  256. DWORD dwRet;
  257. DWORD dwCreate;
  258. HKEY hBaseKey = NULL;
  259. HKEY hMKKey = NULL;
  260. // Open User Key //
  261. if (PST_E_OK != (dwRet =
  262. GetPSTUserHKEY(
  263. szUser,
  264. &hBaseKey,
  265. NULL)) )
  266. goto Ret;
  267. // Open Master Key section //
  268. if (ERROR_SUCCESS !=
  269. RegCreateKeyExU(
  270. hBaseKey,
  271. REG_MK_LOC,
  272. 0,
  273. NULL, // address of class string
  274. 0,
  275. KEY_READ | KEY_WRITE,
  276. NULL,
  277. &hMKKey,
  278. &dwCreate))
  279. {
  280. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  281. goto Ret;
  282. }
  283. if (szMasterKey)
  284. {
  285. // Open specific Master Key //
  286. if (ERROR_SUCCESS !=
  287. RegCreateKeyExU(
  288. hMKKey,
  289. szMasterKey,
  290. 0,
  291. NULL, // address of class string
  292. 0,
  293. KEY_READ | KEY_WRITE,
  294. NULL,
  295. phMyKey,
  296. &dwCreate))
  297. {
  298. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  299. goto Ret;
  300. }
  301. }
  302. else
  303. {
  304. // wanted master parent, not specific MK
  305. *phMyKey = hMKKey;
  306. }
  307. dwRet = PST_E_OK;
  308. Ret:
  309. if (hBaseKey)
  310. RegCloseKey(hBaseKey);
  311. // wanted parent, not specific MK
  312. if ((*phMyKey != hMKKey) && (hMKKey))
  313. RegCloseKey(hMKKey);
  314. return dwRet;
  315. }
  316. DWORD GetPSTSubtypeHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, HKEY* phSubTypeKey)
  317. {
  318. DWORD dwRet;
  319. DWORD dwCreate;
  320. HKEY hTypeKey = NULL;
  321. CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
  322. // Open User Key //
  323. if (PST_E_OK != (dwRet =
  324. GetPSTTypeHKEY(
  325. szUser,
  326. pguidType,
  327. &hTypeKey)) )
  328. goto Ret;
  329. if (PST_E_OK != (dwRet =
  330. MyGuidToStringA(
  331. pguidSubtype,
  332. rgszSubtypeGuid)) )
  333. goto Ret;
  334. // Open SubType Key //
  335. if (ERROR_SUCCESS !=
  336. RegOpenKeyExA(
  337. hTypeKey,
  338. rgszSubtypeGuid,
  339. 0,
  340. KEY_READ | KEY_WRITE,
  341. phSubTypeKey))
  342. {
  343. dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
  344. goto Ret;
  345. }
  346. dwRet = PST_E_OK;
  347. Ret:
  348. if (hTypeKey)
  349. RegCloseKey(hTypeKey);
  350. return dwRet;
  351. }
  352. DWORD CreatePSTSubtypeHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, HKEY* phSubTypeKey, BOOL* pfExisted)
  353. {
  354. DWORD dwRet;
  355. DWORD dwCreate;
  356. HKEY hTypeKey = NULL;
  357. CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
  358. // Open Type Key //
  359. if (PST_E_OK != (dwRet =
  360. GetPSTTypeHKEY(
  361. szUser,
  362. pguidType,
  363. &hTypeKey)) )
  364. goto Ret;
  365. if (PST_E_OK != (dwRet =
  366. MyGuidToStringA(
  367. pguidSubtype,
  368. rgszSubtypeGuid)) )
  369. goto Ret;
  370. // Open SubType Key //
  371. if (ERROR_SUCCESS !=
  372. RegCreateKeyExA(
  373. hTypeKey,
  374. rgszSubtypeGuid,
  375. 0,
  376. NULL, // address of class string
  377. 0,
  378. KEY_READ | KEY_WRITE,
  379. NULL,
  380. phSubTypeKey,
  381. &dwCreate))
  382. {
  383. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  384. goto Ret;
  385. }
  386. if (pfExisted)
  387. *pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
  388. dwRet = PST_E_OK;
  389. Ret:
  390. if (hTypeKey)
  391. RegCloseKey(hTypeKey);
  392. return dwRet;
  393. }
  394. DWORD CreatePSTItemHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, LPCWSTR szItemName, HKEY* phItemKey, BOOL* pfExisted)
  395. {
  396. BOOL dwRet;
  397. DWORD dwCreate;
  398. HKEY hSubTypeKey = NULL;
  399. // Open SubType key //
  400. if (PST_E_OK != (dwRet =
  401. GetPSTSubtypeHKEY(
  402. szUser,
  403. pguidType,
  404. pguidSubtype,
  405. &hSubTypeKey)) )
  406. goto Ret;
  407. // Open name key //
  408. if (ERROR_SUCCESS !=
  409. RegCreateKeyExU(
  410. hSubTypeKey,
  411. szItemName,
  412. 0,
  413. NULL, // address of class string
  414. 0,
  415. KEY_READ | KEY_WRITE,
  416. NULL,
  417. phItemKey,
  418. &dwCreate))
  419. {
  420. dwRet = (DWORD)PST_E_STORAGE_ERROR;
  421. goto Ret;
  422. }
  423. if (pfExisted)
  424. *pfExisted = (dwCreate == REG_OPENED_EXISTING_KEY);
  425. dwRet = PST_E_OK;
  426. Ret:
  427. if (hSubTypeKey)
  428. RegCloseKey(hSubTypeKey);
  429. return dwRet;
  430. }
  431. DWORD GetPSTItemHKEY(LPCWSTR szUser, const GUID* pguidType, const GUID* pguidSubtype, LPCWSTR szItemName, HKEY* phItemKey)
  432. {
  433. DWORD dwRet;
  434. DWORD dwCreate;
  435. HKEY hSubtypeKey = NULL;
  436. // Open SubType key //
  437. if (PST_E_OK != (dwRet =
  438. GetPSTSubtypeHKEY(
  439. szUser,
  440. pguidType,
  441. pguidSubtype,
  442. &hSubtypeKey)) )
  443. goto Ret;
  444. // Open name key //
  445. if (ERROR_SUCCESS !=
  446. RegOpenKeyExU(
  447. hSubtypeKey,
  448. szItemName,
  449. 0,
  450. KEY_READ | KEY_WRITE,
  451. phItemKey))
  452. {
  453. dwRet = (DWORD)PST_E_ITEM_NO_EXISTS;
  454. goto Ret;
  455. }
  456. dwRet = PST_E_OK;
  457. Ret:
  458. if (hSubtypeKey)
  459. RegCloseKey(hSubtypeKey);
  460. return dwRet;
  461. }
  462. // end PRIMITIVES
  463. ///////////////////////////////////////////////////////////////////////
  464. ///////////////////////////////////////////////////////////////////////
  465. ///////////////////////////////////////////////////////////////////////
  466. ///////////////////////////////////////////////////////////////////////
  467. // PICKLE routines
  468. #if 0
  469. BOOL FAccessRulesPickle(
  470. PST_ACCESSRULESET *psRules,
  471. PBYTE* ppbPickled,
  472. DWORD* pcbPickled)
  473. {
  474. BOOL fRet = FALSE;
  475. DWORD cbTotal = 0;
  476. DWORD dwRule;
  477. // ease-of-use write pointer
  478. PBYTE pbCurrentWrite;
  479. // init out params
  480. *ppbPickled = NULL;
  481. *pcbPickled = 0;
  482. // ASSERT new size member was initialized
  483. SS_ASSERT(psRules->cbSize == sizeof(PST_ACCESSRULESET));
  484. if (psRules->cbSize != sizeof(PST_ACCESSRULESET))
  485. goto Ret;
  486. cbTotal += sizeof(DWORD); // Ruleset struct versioning
  487. cbTotal += sizeof(DWORD); // # Rules in Ruleset
  488. // walk through each Rule in Ruleset
  489. for (dwRule=0; dwRule<psRules->cRules; dwRule++)
  490. {
  491. DWORD cClause;
  492. // ASSERT new size member was initialized
  493. SS_ASSERT(psRules->rgRules[dwRule].cbSize == sizeof(PST_ACCESSRULE));
  494. if (psRules->rgRules[dwRule].cbSize != sizeof(PST_ACCESSRULE))
  495. goto Ret;
  496. cbTotal += sizeof(DWORD); // Rule struct versioning
  497. cbTotal += sizeof(PST_ACCESSMODE); // mode in each Rule
  498. cbTotal += sizeof(DWORD); // # Clauses in Rule
  499. // for each Rule, we'll have array of clauses
  500. for (cClause=0; cClause<psRules->rgRules[dwRule].cClauses; cClause++)
  501. {
  502. // ASSERT new size member was initialized
  503. SS_ASSERT(psRules->rgRules[dwRule].rgClauses[cClause].cbSize == sizeof(PST_ACCESSCLAUSE));
  504. if (psRules->rgRules[dwRule].rgClauses[cClause].cbSize != sizeof(PST_ACCESSCLAUSE))
  505. goto Ret;
  506. cbTotal += sizeof(DWORD); // Clause struct versioning
  507. // we'll see every clause here
  508. cbTotal += sizeof(PST_ACCESSCLAUSETYPE); // type in each clause
  509. cbTotal += sizeof(DWORD); // # bytes in clause buffer
  510. cbTotal += psRules->rgRules[dwRule].rgClauses[cClause].cbClauseData; // buffer itself
  511. }
  512. }
  513. *ppbPickled = (BYTE*)SSAlloc(cbTotal);
  514. if(*ppbPickled == NULL)
  515. goto Ret;
  516. pbCurrentWrite = *ppbPickled;
  517. *pcbPickled = cbTotal;
  518. // copy Ruleset struct version
  519. *(DWORD*)pbCurrentWrite = psRules->cbSize;
  520. pbCurrentWrite += sizeof(DWORD);
  521. // copy # rules in ruleset
  522. *(DWORD*)pbCurrentWrite = psRules->cRules;
  523. pbCurrentWrite += sizeof(DWORD);
  524. // walk through each Rule in Ruleset
  525. for (dwRule=0; dwRule<psRules->cRules; dwRule++)
  526. {
  527. // copy Rule struct version
  528. *(DWORD*)pbCurrentWrite = psRules->rgRules[dwRule].cbSize;
  529. pbCurrentWrite += sizeof(DWORD);
  530. // copy # clauses in rule
  531. *(DWORD*)pbCurrentWrite = psRules->rgRules[dwRule].cClauses;
  532. pbCurrentWrite += sizeof(DWORD);
  533. // copy rule accessmode
  534. CopyMemory(pbCurrentWrite, &psRules->rgRules[dwRule].AccessModeFlags, sizeof(PST_ACCESSMODE));
  535. pbCurrentWrite += sizeof(PST_ACCESSMODE);
  536. // now for each Rule, we'll have array of clauses
  537. for (DWORD cClause=0; cClause<psRules->rgRules[dwRule].cClauses; cClause++)
  538. {
  539. PST_ACCESSCLAUSE* pTmp = &psRules->rgRules[dwRule].rgClauses[cClause];
  540. // copy clause struct version
  541. *(DWORD*)pbCurrentWrite = pTmp->cbSize;
  542. pbCurrentWrite += sizeof(DWORD);
  543. // clause type
  544. CopyMemory(pbCurrentWrite, &pTmp->ClauseType, sizeof(PST_ACCESSCLAUSETYPE));
  545. pbCurrentWrite += sizeof(PST_ACCESSCLAUSETYPE);
  546. // clause data buffer len
  547. *(DWORD*)pbCurrentWrite = pTmp->cbClauseData;
  548. pbCurrentWrite += sizeof(DWORD);
  549. // buffer itself
  550. CopyMemory(pbCurrentWrite, pTmp->pbClauseData, pTmp->cbClauseData);
  551. pbCurrentWrite += pTmp->cbClauseData;
  552. }
  553. }
  554. #if DBG
  555. {
  556. // ASSERT!
  557. DWORD dwWroteBytes = (DWORD) (((DWORD_PTR)pbCurrentWrite) - ((DWORD_PTR)*ppbPickled));
  558. SS_ASSERT(dwWroteBytes == cbTotal);
  559. SS_ASSERT(cbTotal == *pcbPickled);
  560. }
  561. #endif
  562. fRet = TRUE;
  563. Ret:
  564. // on error and alloc, free
  565. if ((!fRet) && (*ppbPickled != NULL))
  566. {
  567. SSFree(*ppbPickled);
  568. *ppbPickled = NULL;
  569. }
  570. return fRet;
  571. }
  572. BOOL FAccessRulesUnPickle(
  573. PPST_ACCESSRULESET psRules, // out
  574. PBYTE pbPickled,
  575. DWORD cbPickled)
  576. {
  577. BOOL fRet = FALSE;
  578. PBYTE pbCurrentRead = pbPickled;
  579. DWORD cRule;
  580. // Ruleset struct version
  581. psRules->cbSize = *(DWORD*)pbCurrentRead;
  582. pbCurrentRead += sizeof(DWORD);
  583. // currently only one version known
  584. if (psRules->cbSize != sizeof(PST_ACCESSRULESET))
  585. goto Ret;
  586. // get # rules in ruleset
  587. cRule = *(DWORD*)pbCurrentRead;
  588. pbCurrentRead += sizeof(DWORD);
  589. // now we know how many Rule in Ruleset
  590. psRules->rgRules = (PST_ACCESSRULE*)SSAlloc(sizeof(PST_ACCESSRULE)*cRule);
  591. if(psRules->rgRules == NULL)
  592. goto Ret;
  593. psRules->cRules = cRule;
  594. // now unpack each Rule
  595. for (cRule=0; cRule<psRules->cRules; cRule++)
  596. {
  597. DWORD cClauses;
  598. // Ruleset struct version
  599. psRules->rgRules[cRule].cbSize = *(DWORD*)pbCurrentRead;
  600. // currently only one version known
  601. if (psRules->rgRules[cRule].cbSize != sizeof(PST_ACCESSRULE))
  602. goto Ret;
  603. pbCurrentRead += sizeof(DWORD);
  604. // get # clauses in rule
  605. cClauses = *(DWORD*)pbCurrentRead;
  606. pbCurrentRead += sizeof(DWORD);
  607. // now we know how many Clauses in Rule
  608. psRules->rgRules[cRule].rgClauses = (PST_ACCESSCLAUSE*)SSAlloc(sizeof(PST_ACCESSCLAUSE)*cClauses);
  609. if (psRules->rgRules[cRule].rgClauses == NULL) // check allocation
  610. goto Ret;
  611. psRules->rgRules[cRule].cClauses = cClauses;
  612. // copy rule accessmode flags
  613. CopyMemory(&psRules->rgRules[cRule].AccessModeFlags, pbCurrentRead, sizeof(PST_ACCESSMODE));
  614. pbCurrentRead += sizeof(PST_ACCESSMODE);
  615. // now load each Clause
  616. for (DWORD cClause=0; cClause<psRules->rgRules[cRule].cClauses; cClause++)
  617. {
  618. PST_ACCESSCLAUSE* pTmp = &psRules->rgRules[cRule].rgClauses[cClause];
  619. // Clause struct version
  620. pTmp->cbSize = *(DWORD*)pbCurrentRead;
  621. // currently only one version known
  622. if (pTmp->cbSize != sizeof(PST_ACCESSCLAUSE))
  623. goto Ret;
  624. pbCurrentRead += sizeof(DWORD);
  625. CopyMemory(&pTmp->ClauseType, pbCurrentRead, sizeof(PST_ACCESSCLAUSETYPE));
  626. pbCurrentRead += sizeof(PST_ACCESSCLAUSETYPE);
  627. // clause data buffer len
  628. pTmp->cbClauseData = *(DWORD*)pbCurrentRead;
  629. pbCurrentRead += sizeof(DWORD);
  630. // buffer itself
  631. pTmp->pbClauseData = (PBYTE) SSAlloc(pTmp->cbClauseData);
  632. if (pTmp->pbClauseData == NULL) // check allocation
  633. goto Ret;
  634. CopyMemory(pTmp->pbClauseData, pbCurrentRead, pTmp->cbClauseData);
  635. pbCurrentRead += pTmp->cbClauseData;
  636. }
  637. }
  638. #if DBG
  639. {
  640. // ASSERT!
  641. DWORD dwReadBytes = (DWORD) (((DWORD_PTR)pbCurrentRead) - ((DWORD_PTR)pbPickled));
  642. SS_ASSERT(dwReadBytes == cbPickled);
  643. }
  644. #endif
  645. fRet = TRUE;
  646. Ret:
  647. if (!fRet)
  648. FreeRuleset(psRules);
  649. return fRet;
  650. }
  651. #endif
  652. // end PICKLE routines
  653. ///////////////////////////////////////////////////////////////////////
  654. ///////////////////////////////////////////////////////////////////////
  655. ///////////////////////////////////////////////////////////////////////
  656. ///////////////////////////////////////////////////////////////////////
  657. // TYPE management
  658. DWORD BPCreateType(
  659. LPCWSTR szUser, // in
  660. const GUID* pguidType, // in
  661. PST_TYPEINFO* pinfoType) // in
  662. {
  663. DWORD dwRet;
  664. BOOL fExisted;
  665. HKEY hKey = NULL;
  666. // now we need to create entries in hierarchy
  667. if (PST_E_OK != (dwRet =
  668. CreatePSTTypeHKEY(
  669. szUser,
  670. pguidType,
  671. &hKey,
  672. &fExisted)) )
  673. goto Ret;
  674. // if we didn't create it, setting is an error
  675. if (fExisted)
  676. {
  677. dwRet = (DWORD)PST_E_TYPE_EXISTS;
  678. goto Ret;
  679. }
  680. if (ERROR_SUCCESS != (dwRet =
  681. RegSetValueExU(
  682. hKey,
  683. REG_DISPLAYSTRING_VALNAME,
  684. 0,
  685. REG_SZ,
  686. (PBYTE)pinfoType->szDisplayName,
  687. WSZ_BYTECOUNT(pinfoType->szDisplayName))) )
  688. goto Ret;
  689. dwRet = (DWORD)PST_E_OK;
  690. Ret:
  691. if (hKey)
  692. RegCloseKey(hKey);
  693. return dwRet;
  694. }
  695. DWORD BPDeleteType(
  696. LPCWSTR szUser, // in
  697. const GUID* pguidType) // in
  698. {
  699. DWORD dwRet;
  700. CHAR rgszTypeGuid[MAX_GUID_SZ_CHARS];
  701. // now remove the entry in hierarchy
  702. HKEY hBaseKey = NULL;
  703. HKEY hDataKey = NULL;
  704. if (PST_E_OK != (dwRet =
  705. GetPSTUserHKEY(
  706. szUser,
  707. &hBaseKey,
  708. NULL)) )
  709. goto Ret;
  710. // Open Data Key //
  711. if (ERROR_SUCCESS != (dwRet =
  712. RegOpenKeyExU(
  713. hBaseKey,
  714. REG_DATA_LOC,
  715. 0,
  716. KEY_READ | KEY_WRITE,
  717. &hDataKey)) )
  718. goto Ret;
  719. if (PST_E_OK != (dwRet =
  720. MyGuidToStringA(
  721. pguidType,
  722. rgszTypeGuid)) )
  723. goto Ret;
  724. if (!FIsWinNT())
  725. {
  726. CHAR rgszTmp[MAX_GUID_SZ_CHARS];
  727. DWORD cbTmp = MAX_GUID_SZ_CHARS;
  728. FILETIME ft;
  729. HKEY hTestEmptyKey = NULL;
  730. // open the type
  731. if (ERROR_SUCCESS != (dwRet =
  732. RegOpenKeyExA(
  733. hDataKey,
  734. rgszTypeGuid,
  735. 0,
  736. KEY_ALL_ACCESS,
  737. &hTestEmptyKey)) )
  738. goto Ret;
  739. // check for emptiness
  740. if (ERROR_NO_MORE_ITEMS !=
  741. RegEnumKeyExA(
  742. hTestEmptyKey,
  743. 0,
  744. rgszTmp, // address of buffer for subkey name
  745. &cbTmp, // address for size of subkey buffer
  746. NULL, // reserved
  747. NULL, // pbclass
  748. NULL, // cbclass
  749. &ft))
  750. {
  751. RegCloseKey(hTestEmptyKey);
  752. dwRet = (DWORD)PST_E_NOTEMPTY;
  753. goto Ret;
  754. }
  755. // close key before deletion
  756. RegCloseKey(hTestEmptyKey);
  757. }
  758. // now, remove the friendly name
  759. if (ERROR_SUCCESS != (dwRet =
  760. RegDeleteKeyA(
  761. hDataKey,
  762. rgszTypeGuid)) )
  763. {
  764. if (dwRet == ERROR_ACCESS_DENIED)
  765. dwRet = (DWORD)PST_E_NOTEMPTY;
  766. goto Ret;
  767. }
  768. dwRet = (DWORD)PST_E_OK;
  769. Ret:
  770. if (hBaseKey)
  771. RegCloseKey(hBaseKey);
  772. if (hDataKey)
  773. RegCloseKey(hDataKey);
  774. return dwRet;
  775. }
  776. DWORD BPEnumTypes(
  777. LPCWSTR szUser, // in
  778. DWORD dwIndex, // in
  779. GUID* pguidType) // out
  780. {
  781. DWORD dwRet;
  782. CHAR rgszGuidType[MAX_GUID_SZ_CHARS];
  783. DWORD cbName = MAX_GUID_SZ_CHARS;
  784. FILETIME ft;
  785. // now walk through types, returning them one by one
  786. HKEY hKey=NULL, hDataKey=NULL;
  787. if (PST_E_OK != (dwRet =
  788. GetPSTUserHKEY(
  789. szUser,
  790. &hKey,
  791. NULL)) )
  792. goto Ret;
  793. // Open Data Key //
  794. if (ERROR_SUCCESS != (dwRet =
  795. RegOpenKeyExU(
  796. hKey,
  797. REG_DATA_LOC,
  798. 0,
  799. KEY_READ | KEY_WRITE,
  800. &hDataKey)) )
  801. goto Ret;
  802. // enum the dwIndex'th item, alloc & return
  803. if (ERROR_SUCCESS != (dwRet =
  804. RegEnumKeyExA(
  805. hDataKey,
  806. dwIndex,
  807. rgszGuidType, // address of buffer for subkey name
  808. &cbName, // address for size of subkey buffer
  809. NULL, // reserved
  810. NULL, // pbclass
  811. NULL, // cbclass
  812. &ft)) )
  813. goto Ret;
  814. if (ERROR_SUCCESS != (dwRet =
  815. MyGuidFromStringA(
  816. rgszGuidType,
  817. pguidType)) )
  818. goto Ret;
  819. dwRet = (DWORD)PST_E_OK;
  820. Ret:
  821. if (hKey)
  822. RegCloseKey(hKey);
  823. if (hDataKey)
  824. RegCloseKey(hDataKey);
  825. return dwRet;
  826. }
  827. DWORD BPGetTypeName(
  828. LPCWSTR szUser, // in
  829. const GUID* pguidType, // in
  830. LPWSTR* ppszType) // out
  831. {
  832. HKEY hKey = NULL;
  833. DWORD cbName = 0;
  834. DWORD dwRet;
  835. if (PST_E_OK != (dwRet =
  836. GetPSTTypeHKEY(
  837. szUser,
  838. pguidType,
  839. &hKey)) )
  840. {
  841. dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
  842. goto Ret;
  843. }
  844. if (ERROR_SUCCESS != (dwRet =
  845. RegGetStringValue(
  846. hKey,
  847. REG_DISPLAYSTRING_VALNAME,
  848. (PBYTE*)ppszType,
  849. &cbName)) )
  850. goto Ret;
  851. dwRet = (DWORD)PST_E_OK;
  852. Ret:
  853. if (hKey)
  854. RegCloseKey(hKey);
  855. return dwRet;
  856. }
  857. // end TYPE management
  858. ///////////////////////////////////////////////////////////////////////
  859. ///////////////////////////////////////////////////////////////////////
  860. ///////////////////////////////////////////////////////////////////////
  861. ///////////////////////////////////////////////////////////////////////
  862. // SUBTYPE management
  863. DWORD BPCreateSubtype(
  864. LPCWSTR szUser, // in
  865. const GUID* pguidType, // in
  866. const GUID* pguidSubtype, // in
  867. PST_TYPEINFO* pinfoSubtype) // in
  868. {
  869. DWORD dwRet;
  870. BOOL fExisted;
  871. // now we need to create entries in hierarchy
  872. HKEY hKey = NULL;
  873. if (PST_E_OK != (dwRet =
  874. CreatePSTSubtypeHKEY(
  875. szUser,
  876. pguidType,
  877. pguidSubtype,
  878. &hKey,
  879. &fExisted)) )
  880. goto Ret;
  881. // if we didn't create it, setting is an error
  882. if (fExisted)
  883. {
  884. dwRet = (DWORD)PST_E_TYPE_EXISTS;
  885. goto Ret;
  886. }
  887. if (ERROR_SUCCESS != (dwRet =
  888. RegSetValueExU(
  889. hKey,
  890. REG_DISPLAYSTRING_VALNAME,
  891. 0,
  892. REG_SZ,
  893. (PBYTE)pinfoSubtype->szDisplayName,
  894. WSZ_BYTECOUNT(pinfoSubtype->szDisplayName) )) )
  895. goto Ret;
  896. dwRet = (DWORD)PST_E_OK;
  897. Ret:
  898. if (hKey)
  899. RegCloseKey(hKey);
  900. return dwRet;
  901. }
  902. DWORD BPDeleteSubtype(
  903. LPCWSTR szUser, // in
  904. const GUID* pguidType, // in
  905. const GUID* pguidSubtype) // in
  906. {
  907. DWORD dwRet;
  908. CHAR rgszSubtypeGuid[MAX_GUID_SZ_CHARS];
  909. // now remove the entry in hierarchy
  910. HKEY hKey = NULL;
  911. if (PST_E_OK != (dwRet =
  912. GetPSTTypeHKEY(
  913. szUser,
  914. pguidType,
  915. &hKey)) )
  916. {
  917. dwRet = (DWORD)PST_E_TYPE_NO_EXISTS;
  918. goto Ret;
  919. }
  920. if (PST_E_OK != (dwRet =
  921. MyGuidToStringA(
  922. pguidSubtype,
  923. rgszSubtypeGuid)) )
  924. goto Ret;
  925. if (!FIsWinNT())
  926. {
  927. CHAR rgszTmp[MAX_GUID_SZ_CHARS];
  928. DWORD cbTmp = MAX_GUID_SZ_CHARS;
  929. FILETIME ft;
  930. HKEY hTestEmptyKey = NULL;
  931. // open the subtype
  932. if (ERROR_SUCCESS != (dwRet =
  933. RegOpenKeyExA(
  934. hKey,
  935. rgszSubtypeGuid,
  936. 0,
  937. KEY_ALL_ACCESS,
  938. &hTestEmptyKey)) )
  939. goto Ret;
  940. // check for emptiness
  941. if (ERROR_NO_MORE_ITEMS !=
  942. RegEnumKeyExA(
  943. hTestEmptyKey,
  944. 0,
  945. rgszTmp, // address of buffer for subkey name
  946. &cbTmp, // address for size of subkey buffer
  947. NULL, // reserved
  948. NULL, // pbclass
  949. NULL, // cbclass
  950. &ft))
  951. {
  952. RegCloseKey(hTestEmptyKey);
  953. dwRet = (DWORD)PST_E_NOTEMPTY;
  954. goto Ret;
  955. }
  956. // close key before deletion
  957. RegCloseKey(hTestEmptyKey);
  958. }
  959. // now, remove the friendly name
  960. if (ERROR_SUCCESS != (dwRet =
  961. RegDeleteKeyA(
  962. hKey,
  963. rgszSubtypeGuid)) )
  964. {
  965. if (dwRet == ERROR_ACCESS_DENIED)
  966. dwRet = (DWORD)PST_E_NOTEMPTY;
  967. goto Ret;
  968. }
  969. dwRet = (DWORD)PST_E_OK;
  970. Ret:
  971. if (hKey)
  972. RegCloseKey(hKey);
  973. return dwRet;
  974. }
  975. DWORD BPEnumSubtypes(
  976. LPCWSTR szUser, // in
  977. DWORD dwIndex, // in
  978. const GUID* pguidType, // in
  979. GUID* pguidSubtype) // out
  980. {
  981. DWORD dwRet;
  982. CHAR rgszGuidSubtype[MAX_GUID_SZ_CHARS];
  983. DWORD cbName = MAX_GUID_SZ_CHARS;
  984. FILETIME ft;
  985. // now walk through types, returning them one by one
  986. HKEY hTypeKey=NULL, hSubtypeKey=NULL;
  987. if (PST_E_OK != (dwRet =
  988. GetPSTTypeHKEY(
  989. szUser,
  990. pguidType,
  991. &hTypeKey)) )
  992. goto Ret;
  993. // enum the dwIndex'th item, alloc & return
  994. if (ERROR_SUCCESS != (dwRet =
  995. RegEnumKeyExA(
  996. hTypeKey,
  997. dwIndex,
  998. rgszGuidSubtype, // address of buffer for subkey name
  999. &cbName, // address for size of subkey buffer
  1000. NULL, // reserved
  1001. NULL, // pbclass
  1002. NULL, // cbclass
  1003. &ft)) )
  1004. goto Ret;
  1005. if (ERROR_SUCCESS != (dwRet =
  1006. MyGuidFromStringA(
  1007. rgszGuidSubtype,
  1008. pguidSubtype)) )
  1009. goto Ret;
  1010. if (ERROR_SUCCESS != (dwRet =
  1011. RegOpenKeyExA(
  1012. hTypeKey,
  1013. rgszGuidSubtype,
  1014. 0,
  1015. KEY_READ | KEY_WRITE,
  1016. &hSubtypeKey)) )
  1017. goto Ret;
  1018. dwRet = (DWORD)PST_E_OK;
  1019. Ret:
  1020. if (hTypeKey)
  1021. RegCloseKey(hTypeKey);
  1022. if (hSubtypeKey)
  1023. RegCloseKey(hSubtypeKey);
  1024. return dwRet;
  1025. }
  1026. DWORD BPGetSubtypeName(
  1027. LPCWSTR szUser, // in
  1028. const GUID* pguidType, // in
  1029. const GUID* pguidSubtype, // in
  1030. LPWSTR* ppszSubtype) // out
  1031. {
  1032. HKEY hKey = NULL;
  1033. DWORD cbName = 0;
  1034. DWORD dwRet;
  1035. if (PST_E_OK != (dwRet =
  1036. GetPSTSubtypeHKEY(
  1037. szUser,
  1038. pguidType,
  1039. pguidSubtype,
  1040. &hKey)) )
  1041. goto Ret;
  1042. if (ERROR_SUCCESS != (dwRet =
  1043. RegGetStringValue(
  1044. hKey,
  1045. REG_DISPLAYSTRING_VALNAME,
  1046. (PBYTE*)ppszSubtype,
  1047. &cbName)) )
  1048. goto Ret;
  1049. dwRet = (DWORD)PST_E_OK;
  1050. Ret:
  1051. if (hKey)
  1052. RegCloseKey(hKey);
  1053. return dwRet;
  1054. }
  1055. // end SUBTYPE management
  1056. ///////////////////////////////////////////////////////////////////////
  1057. ///////////////////////////////////////////////////////////////////////
  1058. ///////////////////////////////////////////////////////////////////////
  1059. ///////////////////////////////////////////////////////////////////////
  1060. // ITEM management
  1061. // given uuid, push entries into storage
  1062. DWORD BPCreateItem(
  1063. LPCWSTR szUser, // in
  1064. const GUID* pguidType, // in
  1065. const GUID* pguidSubtype, // in
  1066. LPCWSTR szItemName) // in
  1067. {
  1068. DWORD dwRet;
  1069. BOOL fExisted;
  1070. HKEY hKey = NULL;
  1071. //
  1072. // mattt 2/5/97: allow items with \ in them to be created. Urgh!
  1073. //
  1074. // mattt 4/28/97: begin restricting strings.
  1075. // Cert request code has been changed to not create this type of key name
  1076. //
  1077. /*
  1078. if (!FStringIsValidItemName(szItemName))
  1079. {
  1080. dwRet = (DWORD)PST_E_INVALID_STRING;
  1081. goto Ret;
  1082. }
  1083. */
  1084. // now we need to create entries in hierarchy
  1085. if (PST_E_OK != (dwRet =
  1086. CreatePSTItemHKEY(
  1087. szUser,
  1088. pguidType,
  1089. pguidSubtype,
  1090. szItemName,
  1091. &hKey,
  1092. &fExisted)) )
  1093. goto Ret;
  1094. if (fExisted)
  1095. {
  1096. dwRet = (DWORD)PST_E_ITEM_EXISTS;
  1097. goto Ret;
  1098. }
  1099. dwRet = (DWORD)PST_E_OK;
  1100. Ret:
  1101. if (hKey)
  1102. RegCloseKey(hKey);
  1103. return dwRet;
  1104. }
  1105. DWORD BPDeleteItem(
  1106. LPCWSTR szUser, // in
  1107. const GUID* pguidType, // in
  1108. const GUID* pguidSubtype, // in
  1109. LPCWSTR szItemName) // in
  1110. {
  1111. DWORD dwRet;
  1112. HKEY hSubTypeKey = NULL;
  1113. // now we need to remove entries in hierarchy
  1114. if (PST_E_OK != (dwRet =
  1115. GetPSTSubtypeHKEY(
  1116. szUser,
  1117. pguidType,
  1118. pguidSubtype,
  1119. &hSubTypeKey)) )
  1120. goto Ret;
  1121. // now, remove the friendly name
  1122. if (ERROR_SUCCESS != (dwRet =
  1123. RegDeleteKeyU(
  1124. hSubTypeKey,
  1125. szItemName)) )
  1126. goto Ret;
  1127. dwRet = (DWORD)PST_E_OK;
  1128. Ret:
  1129. if (hSubTypeKey)
  1130. RegCloseKey(hSubTypeKey);
  1131. return dwRet;
  1132. }
  1133. // Warning: Item path must be fully specified.. szName returned
  1134. DWORD BPEnumItems(
  1135. LPCWSTR szUser, // in
  1136. const GUID* pguidType, // in
  1137. const GUID* pguidSubtype, // in
  1138. DWORD dwIndex, // in
  1139. LPWSTR* ppszName) // out
  1140. {
  1141. DWORD dwRet;
  1142. WCHAR szName[MAX_PATH];
  1143. DWORD cchName = MAX_PATH;
  1144. FILETIME ft;
  1145. // now walk through types, returning them one by one
  1146. HKEY hKey = NULL;
  1147. // Open SubType key //
  1148. if (PST_E_OK != (dwRet =
  1149. GetPSTSubtypeHKEY(
  1150. szUser,
  1151. pguidType,
  1152. pguidSubtype,
  1153. &hKey)) )
  1154. goto Ret;
  1155. // enum the dwIndex'th item, alloc & return
  1156. if (ERROR_SUCCESS != (dwRet =
  1157. RegEnumKeyExU(
  1158. hKey,
  1159. dwIndex,
  1160. szName, // address of buffer for subkey name
  1161. &cchName, // address for size of subkey buffer
  1162. NULL, // reserved
  1163. NULL, // pbclass
  1164. NULL, // cbclass
  1165. &ft)) )
  1166. goto Ret;
  1167. *ppszName = (LPWSTR)SSAlloc((cchName+1)*sizeof(WCHAR));
  1168. if(*ppszName == NULL)
  1169. {
  1170. dwRet = (DWORD)PST_E_FAIL;
  1171. goto Ret;
  1172. }
  1173. wcscpy(*ppszName, szName);
  1174. dwRet = (DWORD)PST_E_OK;
  1175. Ret:
  1176. if (hKey)
  1177. RegCloseKey(hKey);
  1178. return dwRet;
  1179. }
  1180. // end ITEM management
  1181. ///////////////////////////////////////////////////////////////////////
  1182. ///////////////////////////////////////////////////////////////////////
  1183. ///////////////////////////////////////////////////////////////////////
  1184. ///////////////////////////////////////////////////////////////////////
  1185. // SECURED DATA
  1186. BOOL FBPGetSecuredItemData(
  1187. LPCWSTR szUser, // in
  1188. LPCWSTR szMasterKey, // in
  1189. BYTE rgbPwd[A_SHA_DIGEST_LEN], // in
  1190. const GUID* pguidType, // in
  1191. const GUID* pguidSubtype, // in
  1192. LPCWSTR szItemName, // in
  1193. PBYTE* ppbData, // out
  1194. DWORD* pcbData) // out
  1195. {
  1196. DWORD dwRet;
  1197. *ppbData = NULL; // on err return NULL
  1198. *pcbData = 0;
  1199. HKEY hItemKey = NULL;
  1200. if (PST_E_OK != (dwRet =
  1201. GetPSTItemHKEY(
  1202. szUser,
  1203. pguidType,
  1204. pguidSubtype,
  1205. szItemName,
  1206. &hItemKey)) )
  1207. goto Ret;
  1208. // Version | Key Block | Secure Data [...]
  1209. if (ERROR_SUCCESS != (dwRet =
  1210. RegGetValue(
  1211. hItemKey,
  1212. REG_ITEM_SECURE_DATA_VALNAME,
  1213. ppbData,
  1214. pcbData)) )
  1215. goto Ret;
  1216. if (!FProvDecryptData(
  1217. szUser,
  1218. szMasterKey,
  1219. rgbPwd, // in
  1220. ppbData, // in out
  1221. pcbData)) // in out
  1222. {
  1223. dwRet = (DWORD)PST_E_FAIL;
  1224. goto Ret;
  1225. }
  1226. dwRet = PST_E_OK;
  1227. Ret:
  1228. if ((dwRet != PST_E_OK) && (*ppbData != NULL))
  1229. {
  1230. SSFree(*ppbData);
  1231. *ppbData = NULL;
  1232. *pcbData = 0;
  1233. }
  1234. if (hItemKey)
  1235. RegCloseKey(hItemKey);
  1236. return (dwRet == PST_E_OK);
  1237. }
  1238. BOOL FBPSetSecuredItemData(
  1239. LPCWSTR szUser, // in
  1240. LPCWSTR szMasterKey, // in
  1241. BYTE rgbPwd[A_SHA_DIGEST_LEN], // in
  1242. const GUID* pguidType, // in
  1243. const GUID* pguidSubtype, // in
  1244. LPCWSTR szItemName, // in
  1245. PBYTE pbData, // in
  1246. DWORD cbData) // in
  1247. {
  1248. #define REALLOC_FUDGESIZE 96 // 5dw + SHA_LEN + KeyBlock + DES_BLOCKLEN (block encr expansion)
  1249. DWORD dwRet;
  1250. HKEY hItemKey = NULL;
  1251. PBYTE pbMyData = NULL;
  1252. DWORD cbMyData;
  1253. // make whackable copy
  1254. cbMyData = cbData;
  1255. pbMyData = (PBYTE)SSAlloc(cbMyData + REALLOC_FUDGESIZE);
  1256. if (pbMyData == NULL)
  1257. {
  1258. dwRet = (DWORD)PST_E_FAIL;
  1259. goto Ret;
  1260. }
  1261. CopyMemory(pbMyData, pbData, cbData);
  1262. if (PST_E_OK != (dwRet =
  1263. GetPSTItemHKEY(
  1264. szUser,
  1265. pguidType,
  1266. pguidSubtype,
  1267. szItemName,
  1268. &hItemKey)) )
  1269. goto Ret;
  1270. if (!FProvEncryptData(
  1271. szUser,
  1272. szMasterKey,
  1273. rgbPwd, // in
  1274. &pbMyData, // in out
  1275. &cbMyData)) // in out
  1276. {
  1277. dwRet = (DWORD)PST_E_FAIL;
  1278. goto Ret;
  1279. }
  1280. if (ERROR_SUCCESS != (dwRet =
  1281. RegSetValueExU(
  1282. hItemKey,
  1283. REG_ITEM_SECURE_DATA_VALNAME,
  1284. 0,
  1285. REG_BINARY,
  1286. pbMyData,
  1287. cbMyData)) )
  1288. goto Ret;
  1289. dwRet = PST_E_OK;
  1290. Ret:
  1291. if (hItemKey)
  1292. RegCloseKey(hItemKey);
  1293. if (pbMyData)
  1294. SSFree(pbMyData);
  1295. return (dwRet == PST_E_OK);
  1296. }
  1297. // end SECURED DATA
  1298. ///////////////////////////////////////////////////////////////////////
  1299. ///////////////////////////////////////////////////////////////////////
  1300. ///////////////////////////////////////////////////////////////////////
  1301. ///////////////////////////////////////////////////////////////////////
  1302. // INSECURE DATA
  1303. DWORD BPGetInsecureItemData(
  1304. LPCWSTR szUser, // in
  1305. const GUID* pguidType, // in
  1306. const GUID* pguidSubtype, // in
  1307. LPCWSTR szItemName, // in
  1308. PBYTE* ppbData, // out
  1309. DWORD* pcbData) // out
  1310. {
  1311. DWORD dwRet;
  1312. *ppbData = NULL;
  1313. HKEY hItemKey = NULL;
  1314. if (PST_E_OK != (dwRet =
  1315. GetPSTItemHKEY(
  1316. szUser,
  1317. pguidType,
  1318. pguidSubtype,
  1319. szItemName,
  1320. &hItemKey)) )
  1321. goto Ret;
  1322. if (ERROR_SUCCESS != (dwRet =
  1323. RegGetValue(
  1324. hItemKey,
  1325. REG_ITEM_INSECURE_DATA_VALNAME,
  1326. ppbData,
  1327. pcbData)) )
  1328. goto Ret;
  1329. dwRet = PST_E_OK;
  1330. Ret:
  1331. if (hItemKey)
  1332. RegCloseKey(hItemKey);
  1333. return dwRet;
  1334. }
  1335. DWORD BPSetInsecureItemData(
  1336. LPCWSTR szUser, // in
  1337. const GUID* pguidType, // in
  1338. const GUID* pguidSubtype, // in
  1339. LPCWSTR szItemName, // in
  1340. PBYTE pbData, // in
  1341. DWORD cbData) // in
  1342. {
  1343. DWORD dwRet;
  1344. HKEY hItemKey = NULL;
  1345. if (PST_E_OK != (dwRet =
  1346. GetPSTItemHKEY(
  1347. szUser,
  1348. pguidType,
  1349. pguidSubtype,
  1350. szItemName,
  1351. &hItemKey)) )
  1352. goto Ret;
  1353. if (ERROR_SUCCESS != (dwRet =
  1354. RegSetValueExU(
  1355. hItemKey,
  1356. REG_ITEM_INSECURE_DATA_VALNAME,
  1357. 0,
  1358. REG_BINARY,
  1359. pbData,
  1360. cbData)) )
  1361. goto Ret;
  1362. dwRet = PST_E_OK;
  1363. Ret:
  1364. if (hItemKey)
  1365. RegCloseKey(hItemKey);
  1366. return dwRet;
  1367. }
  1368. // end INSECURE DATA
  1369. ///////////////////////////////////////////////////////////////////////
  1370. ///////////////////////////////////////////////////////////////////////
  1371. ///////////////////////////////////////////////////////////////////////
  1372. ///////////////////////////////////////////////////////////////////////
  1373. // RULESETS
  1374. // #define RULESET_VERSION 0x1
  1375. // 6-12-97 incremented version; version 0x1 contains old HMAC
  1376. #define RULESET_VERSION 0x2
  1377. #if 0
  1378. DWORD BPGetSubtypeRuleset(
  1379. PST_PROVIDER_HANDLE* phPSTProv, // in
  1380. LPCWSTR szUser, // in
  1381. const GUID* pguidType, // in
  1382. const GUID* pguidSubtype, // in
  1383. PST_ACCESSRULESET* psRules) // out
  1384. {
  1385. DWORD dwRet;
  1386. HKEY hSubtypeKey = NULL;
  1387. BYTE rgbHMAC[A_SHA_DIGEST_LEN];
  1388. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1389. PBYTE pbBuf = NULL;
  1390. DWORD cbBuf;
  1391. PBYTE pbCurrent;
  1392. DWORD cbRuleSize;
  1393. PBYTE pbRuleSet;
  1394. DWORD dwVersion;
  1395. // Open Subtype //
  1396. if (PST_E_OK != (dwRet =
  1397. GetPSTSubtypeHKEY(
  1398. szUser,
  1399. pguidType,
  1400. pguidSubtype,
  1401. &hSubtypeKey)) )
  1402. goto Ret;
  1403. if (ERROR_SUCCESS != (dwRet =
  1404. RegGetValue(
  1405. hSubtypeKey,
  1406. REG_ACCESSRULE_LOC,
  1407. &pbBuf,
  1408. &cbBuf)) )
  1409. goto Ret;
  1410. // RULESET DATA FORMAT:
  1411. // version | size(ruleset) | ruleset | size(MAC) | MAC {of type, subtype, ruleset}
  1412. pbCurrent = pbBuf;
  1413. if( cbBuf < (sizeof(DWORD)*2) ) {
  1414. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1415. goto Ret;
  1416. }
  1417. // version check
  1418. dwVersion = *(DWORD*)pbCurrent;
  1419. if (dwVersion > RULESET_VERSION)
  1420. {
  1421. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1422. goto Ret;
  1423. }
  1424. pbCurrent += sizeof(DWORD);
  1425. cbRuleSize = *(DWORD*)pbCurrent;
  1426. // get WinPW
  1427. if (PST_E_OK !=
  1428. BPVerifyPwd(
  1429. phPSTProv,
  1430. szUser,
  1431. WSZ_PASSWORD_WINDOWS,
  1432. rgbPwd,
  1433. BP_CONFIRM_NONE))
  1434. {
  1435. dwRet = (DWORD)PST_E_WRONG_PASSWORD;
  1436. goto Ret;
  1437. }
  1438. // check MAC
  1439. // Compute Geographically sensitive (can't move) HMAC on { size(ruleset), ruleset }
  1440. if (!FHMACGeographicallySensitiveData(
  1441. szUser,
  1442. WSZ_PASSWORD_WINDOWS,
  1443. (dwVersion == 0x01) ? OLD_HMAC_VERSION : NEW_HMAC_VERSION,
  1444. rgbPwd,
  1445. pguidType,
  1446. pguidSubtype,
  1447. NULL,
  1448. pbCurrent,
  1449. cbRuleSize + sizeof(DWORD), // include the rulesize
  1450. rgbHMAC))
  1451. {
  1452. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1453. goto Ret;
  1454. }
  1455. pbCurrent += sizeof(DWORD); // skip past cbRuleSize (already snarfed)
  1456. pbRuleSet = pbCurrent; // point to rules
  1457. pbCurrent += cbRuleSize; // skip past rules
  1458. // check MAC len
  1459. if (*(DWORD*)pbCurrent != A_SHA_DIGEST_LEN)
  1460. {
  1461. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1462. goto Ret;
  1463. }
  1464. pbCurrent += sizeof(DWORD); // skip past sizeof(MAC)
  1465. // check MAC
  1466. if (0 != memcmp(rgbHMAC, pbCurrent, A_SHA_DIGEST_LEN))
  1467. {
  1468. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1469. goto Ret;
  1470. }
  1471. // MAC okay! shrink to rulesize
  1472. MoveMemory(pbBuf, pbRuleSet, cbRuleSize);
  1473. cbBuf = cbRuleSize;
  1474. pbBuf = (PBYTE)SSReAlloc(pbBuf, cbBuf);
  1475. if (pbBuf == NULL) // check allocation
  1476. {
  1477. dwRet = PST_E_FAIL;
  1478. goto Ret;
  1479. }
  1480. // serialize rules out of the buffer
  1481. if (!FAccessRulesUnPickle(
  1482. psRules,
  1483. pbBuf,
  1484. cbBuf))
  1485. {
  1486. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1487. goto Ret;
  1488. }
  1489. dwRet = (DWORD)PST_E_OK;
  1490. Ret:
  1491. if (pbBuf)
  1492. SSFree(pbBuf);
  1493. if (hSubtypeKey)
  1494. RegCloseKey(hSubtypeKey);
  1495. return dwRet;
  1496. }
  1497. DWORD BPSetSubtypeRuleset(
  1498. PST_PROVIDER_HANDLE* phPSTProv, // in
  1499. LPCWSTR szUser, // in
  1500. const GUID* pguidType, // in
  1501. const GUID* pguidSubtype, // in
  1502. PST_ACCESSRULESET *psRules) // in
  1503. {
  1504. DWORD dwRet;
  1505. HKEY hSubtypeKey = NULL;
  1506. BYTE rgbHMAC[A_SHA_DIGEST_LEN];
  1507. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1508. PBYTE pbBuf = NULL;
  1509. DWORD cbBuf;
  1510. PBYTE pbCurPtr;
  1511. DWORD cbNewSize;
  1512. // serialize rules into a buffer
  1513. if (!FAccessRulesPickle(
  1514. psRules,
  1515. &pbBuf,
  1516. &cbBuf))
  1517. {
  1518. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1519. goto Ret;
  1520. }
  1521. // RULESET DATA FORMAT:
  1522. // version | size(ruleset) | ruleset | size(MAC) | Geographical MAC {size(ruleset), ruleset}
  1523. cbNewSize = cbBuf + 3*sizeof(DWORD) + A_SHA_DIGEST_LEN;
  1524. pbBuf = (PBYTE)SSReAlloc(pbBuf, cbNewSize);
  1525. if (pbBuf == NULL) // check allocation
  1526. {
  1527. dwRet = PST_E_FAIL;
  1528. goto Ret;
  1529. }
  1530. MoveMemory(pbBuf + 2*sizeof(DWORD), pbBuf, cbBuf);
  1531. // helpful pointer
  1532. pbCurPtr = pbBuf;
  1533. // version
  1534. *(DWORD*)pbCurPtr = (DWORD)RULESET_VERSION;
  1535. pbCurPtr += sizeof(DWORD);
  1536. // size(ruleset)
  1537. *(DWORD*)pbCurPtr = (DWORD)cbBuf;
  1538. pbCurPtr += sizeof(DWORD);
  1539. // ruleset previously moved by MoveMemory call
  1540. pbCurPtr += cbBuf; // fwd past ruleset
  1541. // get WinPW
  1542. if (PST_E_OK !=
  1543. BPVerifyPwd(
  1544. phPSTProv,
  1545. szUser,
  1546. WSZ_PASSWORD_WINDOWS,
  1547. rgbPwd,
  1548. BP_CONFIRM_NONE))
  1549. {
  1550. dwRet = (DWORD)PST_E_WRONG_PASSWORD;
  1551. goto Ret;
  1552. }
  1553. // check MAC
  1554. // Compute Geographically sensitive (can't move) HMAC on { size(ruleset), ruleset }
  1555. if (!FHMACGeographicallySensitiveData(
  1556. szUser,
  1557. WSZ_PASSWORD_WINDOWS,
  1558. NEW_HMAC_VERSION,
  1559. rgbPwd,
  1560. pguidType,
  1561. pguidSubtype,
  1562. NULL,
  1563. pbBuf + sizeof(DWORD),
  1564. cbBuf + sizeof(DWORD),
  1565. rgbHMAC))
  1566. {
  1567. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1568. goto Ret;
  1569. }
  1570. // HMAC size
  1571. *(DWORD*)pbCurPtr = (DWORD) sizeof(rgbHMAC);
  1572. pbCurPtr += sizeof(DWORD);
  1573. // HMAC
  1574. CopyMemory(pbCurPtr, rgbHMAC, sizeof(rgbHMAC));
  1575. // done; set cbBuf = new size
  1576. cbBuf = cbNewSize;
  1577. // Open Subtype //
  1578. if (PST_E_OK != (dwRet =
  1579. GetPSTSubtypeHKEY(
  1580. szUser,
  1581. pguidType,
  1582. pguidSubtype,
  1583. &hSubtypeKey)) )
  1584. {
  1585. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1586. goto Ret;
  1587. }
  1588. // now write item
  1589. if (ERROR_SUCCESS != (dwRet =
  1590. RegSetValueExU(
  1591. hSubtypeKey,
  1592. REG_ACCESSRULE_LOC,
  1593. 0,
  1594. REG_BINARY,
  1595. pbBuf,
  1596. cbBuf)) )
  1597. {
  1598. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1599. goto Ret;
  1600. }
  1601. dwRet = (DWORD)PST_E_OK;
  1602. Ret:
  1603. if (pbBuf)
  1604. SSFree(pbBuf);
  1605. if (hSubtypeKey)
  1606. RegCloseKey(hSubtypeKey);
  1607. return dwRet;
  1608. }
  1609. DWORD BPGetItemRuleset(
  1610. PST_PROVIDER_HANDLE* phPSTProv, // in
  1611. LPCWSTR szUser, // in
  1612. const GUID* pguidType, // in
  1613. const GUID* pguidSubtype, // in
  1614. LPCWSTR szItemName, // in
  1615. PST_ACCESSRULESET* psRules) // out
  1616. {
  1617. DWORD dwRet;
  1618. HKEY hItemKey = NULL;
  1619. PBYTE pbBuf = NULL;
  1620. DWORD cbBuf;
  1621. if (PST_E_OK != (dwRet =
  1622. GetPSTItemHKEY(
  1623. szUser,
  1624. pguidType,
  1625. pguidSubtype,
  1626. szItemName,
  1627. &hItemKey)) )
  1628. goto Ret; // item doesn't exist -- ouch!!
  1629. if (ERROR_SUCCESS != (dwRet =
  1630. RegGetValue(
  1631. hItemKey,
  1632. REG_ACCESSRULE_LOC,
  1633. &pbBuf,
  1634. &cbBuf)) )
  1635. {
  1636. // item exists, rules don't
  1637. // fall back on subtype ruleset
  1638. if (PST_E_OK != (dwRet =
  1639. BPGetSubtypeRuleset(
  1640. phPSTProv,
  1641. szUser,
  1642. pguidType,
  1643. pguidSubtype,
  1644. psRules)) )
  1645. goto Ret;
  1646. }
  1647. else
  1648. {
  1649. // serialize rules into a buffer
  1650. if (!FAccessRulesUnPickle(
  1651. psRules,
  1652. pbBuf,
  1653. cbBuf))
  1654. {
  1655. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1656. goto Ret;
  1657. }
  1658. }
  1659. dwRet = (DWORD)PST_E_OK;
  1660. Ret:
  1661. if (pbBuf)
  1662. SSFree(pbBuf);
  1663. if (hItemKey)
  1664. RegCloseKey(hItemKey);
  1665. return dwRet;
  1666. }
  1667. DWORD BPSetItemRuleset(
  1668. PST_PROVIDER_HANDLE* phPSTProv, // in
  1669. LPCWSTR szUser, // in
  1670. const GUID* pguidType, // in
  1671. const GUID* pguidSubtype, // in
  1672. LPCWSTR szItemName, // in
  1673. PST_ACCESSRULESET *psRules) // in
  1674. {
  1675. DWORD dwRet;
  1676. HKEY hItemKey = NULL;
  1677. PBYTE pbBuf = NULL;
  1678. DWORD cbBuf;
  1679. // serialize rules into a buffer
  1680. if (!FAccessRulesPickle(
  1681. psRules,
  1682. &pbBuf,
  1683. &cbBuf))
  1684. {
  1685. dwRet = (DWORD)PST_E_INVALID_RULESET;
  1686. goto Ret;
  1687. }
  1688. // Open Subtype //
  1689. if (PST_E_OK != (dwRet =
  1690. GetPSTItemHKEY(
  1691. szUser,
  1692. pguidType,
  1693. pguidSubtype,
  1694. szItemName,
  1695. &hItemKey)) )
  1696. goto Ret;
  1697. // now write item
  1698. if (ERROR_SUCCESS != (dwRet =
  1699. RegSetValueExU(
  1700. hItemKey,
  1701. REG_ACCESSRULE_LOC,
  1702. 0,
  1703. REG_BINARY,
  1704. pbBuf,
  1705. cbBuf)) )
  1706. goto Ret;
  1707. dwRet = (DWORD)PST_E_OK;
  1708. Ret:
  1709. if (pbBuf)
  1710. SSFree(pbBuf);
  1711. if (hItemKey)
  1712. RegCloseKey(hItemKey);
  1713. return dwRet;
  1714. }
  1715. #endif
  1716. // end RULESETS
  1717. ///////////////////////////////////////////////////////////////////////
  1718. ///////////////////////////////////////////////////////////////////////
  1719. ///////////////////////////////////////////////////////////////////////
  1720. ///////////////////////////////////////////////////////////////////////
  1721. // ITEM CONFIRM INFO
  1722. // #define CONFIRMATION_VERSION 0x01
  1723. // 6-12-97 incremented version: version 0x1 contains old HMAC
  1724. #define CONFIRMATION_VERSION 0x02
  1725. DWORD BPGetItemConfirm(
  1726. PST_PROVIDER_HANDLE* phPSTProv, // in
  1727. LPCWSTR szUser, // in
  1728. const GUID* pguidType, // in
  1729. const GUID* pguidSubtype, // in
  1730. LPCWSTR szItemName, // in
  1731. DWORD* pdwConfirm, // in
  1732. LPWSTR* pszMK) // in
  1733. {
  1734. DWORD dwRet;
  1735. HKEY hItemKey = NULL;
  1736. PBYTE pbBuf = NULL;
  1737. DWORD cbBuf = 0;
  1738. BYTE rgbHMAC[A_SHA_DIGEST_LEN];
  1739. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1740. // helpful pointers
  1741. PBYTE pbCurPtr = NULL;
  1742. PBYTE pbString;
  1743. DWORD cbString;
  1744. DWORD dwVersion;
  1745. // Open nonexistent item master key
  1746. if (PST_E_OK != (dwRet =
  1747. GetPSTItemHKEY(
  1748. szUser,
  1749. pguidType,
  1750. pguidSubtype,
  1751. szItemName,
  1752. &hItemKey)) )
  1753. goto Ret;
  1754. if (ERROR_SUCCESS != (dwRet =
  1755. RegGetValue(
  1756. hItemKey,
  1757. REG_ITEM_MK_VALNAME,
  1758. &pbBuf,
  1759. &cbBuf)) )
  1760. goto Ret;
  1761. // Confirmation data format
  1762. // Version | dwConfirm | size(szMasterKey) | szMasterKey | size(MAC) | Geographical MAC { dwConfirm | size(szMasterKey) | szMasterKey }
  1763. // version check
  1764. dwVersion = *(DWORD*)pbBuf;
  1765. if (CONFIRMATION_VERSION < dwVersion)
  1766. {
  1767. dwRet = (DWORD)PST_E_FAIL;
  1768. goto Ret;
  1769. }
  1770. pbCurPtr = pbBuf + sizeof(DWORD); // fwd past vers
  1771. // get WinPW
  1772. if (PST_E_OK !=
  1773. BPVerifyPwd(
  1774. phPSTProv,
  1775. szUser,
  1776. WSZ_PASSWORD_WINDOWS,
  1777. rgbPwd,
  1778. BP_CONFIRM_NONE))
  1779. {
  1780. dwRet = (DWORD)PST_E_WRONG_PASSWORD;
  1781. goto Ret;
  1782. }
  1783. // check MAC
  1784. // Compute Geographically sensitive (can't move) HMAC on { dwConfirm | size(szMasterKey) | szMasterKey }
  1785. if (!FHMACGeographicallySensitiveData(
  1786. szUser,
  1787. WSZ_PASSWORD_WINDOWS,
  1788. (dwVersion == 0x01) ? OLD_HMAC_VERSION : NEW_HMAC_VERSION,
  1789. rgbPwd,
  1790. pguidType,
  1791. pguidSubtype,
  1792. szItemName,
  1793. pbBuf + sizeof(DWORD), // fwd past Version
  1794. cbBuf - 2*sizeof(DWORD) - A_SHA_DIGEST_LEN, // Version, size(MAC), MAC
  1795. rgbHMAC))
  1796. {
  1797. dwRet = (DWORD)PST_E_FAIL;
  1798. goto Ret;
  1799. }
  1800. // dwConfirm
  1801. *pdwConfirm = *(DWORD*)pbCurPtr; // dwConfirm
  1802. pbCurPtr += sizeof(DWORD); // fwd past dwConfirm
  1803. // szMasterKey
  1804. cbString = *(DWORD*)pbCurPtr; // strlen
  1805. pbCurPtr += sizeof(DWORD); // fwd past len
  1806. pbString = pbCurPtr; // save ptr to string
  1807. pbCurPtr += cbString; // skip string
  1808. if (*(DWORD*)pbCurPtr != A_SHA_DIGEST_LEN)
  1809. {
  1810. dwRet = (DWORD)PST_E_FAIL;
  1811. goto Ret;
  1812. }
  1813. pbCurPtr += sizeof(DWORD);
  1814. if (0 != memcmp(pbCurPtr, rgbHMAC, A_SHA_DIGEST_LEN))
  1815. {
  1816. dwRet = (DWORD)PST_E_FAIL;
  1817. goto Ret;
  1818. }
  1819. MoveMemory(pbBuf, pbString, cbString); // shift left string
  1820. pbCurPtr = (PBYTE)SSReAlloc(pbBuf, cbString); // shorten to strlen
  1821. if (pbCurPtr == NULL) // check allocation
  1822. {
  1823. dwRet = PST_E_FAIL;
  1824. if (pbBuf) {
  1825. SSFree(pbBuf);
  1826. pbBuf = NULL;
  1827. }
  1828. goto Ret;
  1829. }
  1830. pbBuf = pbCurPtr;
  1831. dwRet = (DWORD)PST_E_OK;
  1832. Ret:
  1833. *pszMK = (LPWSTR)pbBuf; // assign to out param
  1834. if (hItemKey)
  1835. RegCloseKey(hItemKey);
  1836. return dwRet;
  1837. }
  1838. DWORD BPSetItemConfirm(
  1839. PST_PROVIDER_HANDLE* phPSTProv, // in
  1840. LPCWSTR szUser, // in
  1841. const GUID* pguidType, // in
  1842. const GUID* pguidSubtype, // in
  1843. LPCWSTR szItemName, // in
  1844. DWORD dwConfirm, // in
  1845. LPCWSTR szMK) // in
  1846. {
  1847. DWORD dwRet;
  1848. HKEY hItemKey = NULL;
  1849. BYTE rgbHMAC[A_SHA_DIGEST_LEN];
  1850. BYTE rgbPwd[A_SHA_DIGEST_LEN];
  1851. // helpful pointer
  1852. PBYTE pbCurPtr;
  1853. // Confirmation data format
  1854. // Version | dwConfirm | size(szMasterKey) | szMasterKey | size(MAC) | Geographical MAC { dwConfirm | size(szMasterKey) | szMasterKey }
  1855. DWORD cbBuf = WSZ_BYTECOUNT(szMK)+ 4*sizeof(DWORD) + A_SHA_DIGEST_LEN;
  1856. PBYTE pbBuf = (PBYTE)SSAlloc(cbBuf);
  1857. if (pbBuf == NULL) // check allocation
  1858. {
  1859. dwRet = PST_E_FAIL;
  1860. goto Ret;
  1861. }
  1862. pbCurPtr = pbBuf;
  1863. // version
  1864. *(DWORD*)pbCurPtr = (DWORD)CONFIRMATION_VERSION;
  1865. pbCurPtr += sizeof(DWORD);
  1866. // dwConfirm
  1867. *(DWORD*)pbCurPtr = dwConfirm;
  1868. pbCurPtr += sizeof(DWORD);
  1869. // szMasterKey size
  1870. *(DWORD*)pbCurPtr = (DWORD)WSZ_BYTECOUNT(szMK);
  1871. pbCurPtr += sizeof(DWORD);
  1872. // szMasterKey
  1873. wcscpy((LPWSTR)pbCurPtr, szMK);
  1874. pbCurPtr += WSZ_BYTECOUNT(szMK); // fwd past szMK
  1875. // get WinPW
  1876. if (PST_E_OK !=
  1877. BPVerifyPwd(
  1878. phPSTProv,
  1879. szUser,
  1880. WSZ_PASSWORD_WINDOWS,
  1881. rgbPwd,
  1882. BP_CONFIRM_NONE))
  1883. {
  1884. dwRet = (DWORD)PST_E_WRONG_PASSWORD;
  1885. goto Ret;
  1886. }
  1887. // check MAC
  1888. // Compute Geographically sensitive (can't move) HMAC on { dwConfirm | size(szMasterKey) | szMasterKey }
  1889. if (!FHMACGeographicallySensitiveData(
  1890. szUser,
  1891. WSZ_PASSWORD_WINDOWS,
  1892. NEW_HMAC_VERSION,
  1893. rgbPwd,
  1894. pguidType,
  1895. pguidSubtype,
  1896. szItemName,
  1897. pbBuf + sizeof(DWORD), // fwd past Version
  1898. cbBuf - 2*sizeof(DWORD) - A_SHA_DIGEST_LEN, // Version, size(MAC), MAC
  1899. rgbHMAC))
  1900. {
  1901. dwRet = (DWORD)PST_E_FAIL;
  1902. goto Ret;
  1903. }
  1904. // HMAC size
  1905. *(DWORD*)pbCurPtr = (DWORD) sizeof(rgbHMAC);
  1906. pbCurPtr += sizeof(DWORD);
  1907. // HMAC
  1908. CopyMemory(pbCurPtr, rgbHMAC, sizeof(rgbHMAC));
  1909. // Open Item //
  1910. if (PST_E_OK != (dwRet =
  1911. GetPSTItemHKEY(
  1912. szUser,
  1913. pguidType,
  1914. pguidSubtype,
  1915. szItemName,
  1916. &hItemKey)) )
  1917. goto Ret;
  1918. // now write item
  1919. if (ERROR_SUCCESS != (dwRet =
  1920. RegSetValueExU(
  1921. hItemKey,
  1922. REG_ITEM_MK_VALNAME,
  1923. 0,
  1924. REG_BINARY,
  1925. pbBuf,
  1926. cbBuf)) )
  1927. goto Ret;
  1928. dwRet = (DWORD)PST_E_OK;
  1929. Ret:
  1930. if (hItemKey)
  1931. RegCloseKey(hItemKey);
  1932. if (pbBuf)
  1933. SSFree(pbBuf);
  1934. return dwRet;
  1935. }
  1936. // ITEM CONFIRM INFO
  1937. ///////////////////////////////////////////////////////////////////////
  1938. ///////////////////////////////////////////////////////////////////////
  1939. ///////////////////////////////////////////////////////////////////////
  1940. ///////////////////////////////////////////////////////////////////////
  1941. // MASTER KEYS
  1942. BOOL BPMasterKeyExists(
  1943. LPCWSTR szUser, // in
  1944. LPWSTR szMasterKey) // in
  1945. {
  1946. BOOL fRet = FALSE;
  1947. HKEY hMyKey = NULL;
  1948. HKEY hMasterKey = NULL;
  1949. // Open Master parent key //
  1950. if (PST_E_OK !=
  1951. GetPSTMasterKeyHKEY(
  1952. szUser,
  1953. NULL,
  1954. &hMyKey))
  1955. goto Ret;
  1956. // attempt to open the master key location
  1957. if (ERROR_SUCCESS !=
  1958. RegOpenKeyExU(
  1959. hMyKey,
  1960. szMasterKey,
  1961. 0,
  1962. KEY_QUERY_VALUE,
  1963. &hMasterKey))
  1964. goto Ret;
  1965. // key does exist
  1966. fRet = TRUE;
  1967. Ret:
  1968. if (hMyKey)
  1969. RegCloseKey(hMyKey);
  1970. if (hMasterKey)
  1971. RegCloseKey(hMasterKey);
  1972. return fRet;
  1973. }
  1974. DWORD BPEnumMasterKeys(
  1975. LPCWSTR szUser, // in
  1976. DWORD dwIndex, // in
  1977. LPWSTR* ppszMasterKey) // out
  1978. {
  1979. DWORD dwRet;
  1980. HKEY hMyKey = NULL;
  1981. WCHAR szName[MAX_PATH];
  1982. DWORD cchName = MAX_PATH;
  1983. FILETIME ft;
  1984. // Open Master parent key //
  1985. if (PST_E_OK != (dwRet =
  1986. GetPSTMasterKeyHKEY(
  1987. szUser,
  1988. NULL,
  1989. &hMyKey)) )
  1990. goto Ret;
  1991. // enum the dwIndex'th item, alloc & return
  1992. if (ERROR_SUCCESS != (dwRet =
  1993. RegEnumKeyExU(
  1994. hMyKey,
  1995. dwIndex,
  1996. szName, // address of buffer for subkey name
  1997. &cchName, // address for size of subkey buffer
  1998. NULL, // reserved
  1999. NULL, // pbclass
  2000. NULL, // cbclass
  2001. &ft)) )
  2002. goto Ret;
  2003. *ppszMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(szName));
  2004. if(*ppszMasterKey == NULL)
  2005. {
  2006. dwRet = (DWORD)PST_E_FAIL;
  2007. goto Ret;
  2008. }
  2009. wcscpy(*ppszMasterKey, szName);
  2010. dwRet = (DWORD)PST_E_OK;
  2011. Ret:
  2012. if (hMyKey)
  2013. RegCloseKey(hMyKey);
  2014. return dwRet;
  2015. }
  2016. DWORD BPGetMasterKeys(
  2017. LPCWSTR szUser,
  2018. LPWSTR rgszMasterKeys[],
  2019. DWORD* pcbMasterKeys,
  2020. BOOL fUserFilter)
  2021. {
  2022. DWORD dwRet;
  2023. DWORD cKeys=0;
  2024. for (DWORD cntEnum=0; cntEnum<*pcbMasterKeys; cntEnum++)
  2025. {
  2026. if (PST_E_OK != (dwRet =
  2027. BPEnumMasterKeys(
  2028. szUser,
  2029. cntEnum,
  2030. &rgszMasterKeys[cKeys])) )
  2031. break;
  2032. cKeys++;
  2033. // filter out non-user keys
  2034. if (fUserFilter)
  2035. {
  2036. if (!FIsUserMasterKey(rgszMasterKeys[cKeys-1]))
  2037. SSFree(rgszMasterKeys[--cKeys]);
  2038. }
  2039. }
  2040. *pcbMasterKeys = cKeys;
  2041. return PST_E_OK;
  2042. }
  2043. // end MASTER KEYS
  2044. ///////////////////////////////////////////////////////////////////////
  2045. ///////////////////////////////////////////////////////////////////////
  2046. ///////////////////////////////////////////////////////////////////////
  2047. ///////////////////////////////////////////////////////////////////////
  2048. // SECURITY STATE
  2049. #define SECURITY_STATE_VERSION 0x01
  2050. BOOL FBPGetSecurityState(
  2051. LPCWSTR szUser,
  2052. LPCWSTR szMK,
  2053. BYTE rgbSalt[],
  2054. DWORD cbSalt,
  2055. BYTE rgbConfirm[],
  2056. DWORD cbConfirm,
  2057. PBYTE* ppbMK,
  2058. DWORD* pcbMK)
  2059. {
  2060. DWORD dwRet;
  2061. HKEY hMKKey = NULL;
  2062. // Open MK Key //
  2063. if (PST_E_OK != (dwRet =
  2064. GetPSTMasterKeyHKEY(
  2065. szUser,
  2066. szMK,
  2067. &hMKKey)) )
  2068. goto Ret;
  2069. dwRet = PST_E_FAIL;
  2070. if(!FBPGetSecurityStateFromHKEY(
  2071. hMKKey,
  2072. rgbSalt,
  2073. cbSalt,
  2074. rgbConfirm,
  2075. cbConfirm,
  2076. ppbMK,
  2077. pcbMK))
  2078. goto Ret;
  2079. dwRet = PST_E_OK;
  2080. Ret:
  2081. if (hMKKey)
  2082. RegCloseKey(hMKKey);
  2083. return (dwRet == PST_E_OK);
  2084. }
  2085. BOOL FBPGetSecurityStateFromHKEY(
  2086. HKEY hMKKey,
  2087. BYTE rgbSalt[],
  2088. DWORD cbSalt,
  2089. BYTE rgbConfirm[],
  2090. DWORD cbConfirm,
  2091. PBYTE* ppbMK,
  2092. DWORD* pcbMK)
  2093. {
  2094. DWORD dwRet;
  2095. PBYTE pbBuf = NULL;
  2096. DWORD cbBuf;
  2097. // helpful pointer
  2098. PBYTE pbCurPtr;
  2099. DWORD dwMemberSize;
  2100. DWORD dwCreated;
  2101. PBYTE pbLocalSalt;
  2102. PBYTE pbLocalMK;
  2103. PBYTE pbLocalConfirm;
  2104. DWORD cbLocalSalt;
  2105. DWORD cbLocalMK;
  2106. DWORD cbLocalConfirm;
  2107. PBYTE pbMaximumPtr;
  2108. PBYTE pbMinimumPtr;
  2109. if (ERROR_SUCCESS != (dwRet =
  2110. RegGetValue(
  2111. hMKKey,
  2112. REG_SECURITY_SALT_VALNAME,
  2113. &pbBuf,
  2114. &cbBuf)) )
  2115. goto Ret;
  2116. dwRet = PST_E_FAIL;
  2117. // Security data format
  2118. // Version | size(MK) | MK | size(Salt) | Salt | size(Confirm) | Confirm
  2119. if ( cbBuf < (sizeof(DWORD)*4) )
  2120. goto Ret;
  2121. // version check
  2122. if (SECURITY_STATE_VERSION != *(DWORD*)pbBuf)
  2123. goto Ret;
  2124. pbCurPtr = pbBuf + sizeof(DWORD); // fwd past vers
  2125. pbMinimumPtr = pbCurPtr;
  2126. pbMaximumPtr = (pbBuf+cbBuf);
  2127. //
  2128. // MK
  2129. //
  2130. if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
  2131. goto Ret;
  2132. cbLocalMK = *(DWORD*)pbCurPtr; // size
  2133. if( cbLocalMK > cbBuf )
  2134. goto Ret;
  2135. pbCurPtr += sizeof(DWORD); // fwd past size
  2136. pbLocalMK = pbCurPtr;
  2137. pbCurPtr += cbLocalMK; // fwd past data
  2138. //
  2139. // Salt
  2140. //
  2141. if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
  2142. goto Ret;
  2143. cbLocalSalt = *(DWORD*)pbCurPtr; // size
  2144. if( cbLocalSalt > cbBuf )
  2145. goto Ret;
  2146. pbCurPtr += sizeof(DWORD); // fwd past size
  2147. pbLocalSalt = pbCurPtr;
  2148. if (cbLocalSalt != cbSalt) // sizechk
  2149. goto Ret;
  2150. pbCurPtr += cbSalt; // fwd past data
  2151. //
  2152. // Confirm
  2153. //
  2154. if( pbCurPtr >= pbMaximumPtr || pbCurPtr < pbMinimumPtr )
  2155. goto Ret;
  2156. cbLocalConfirm = *(DWORD*)pbCurPtr; // size
  2157. if( cbLocalConfirm > cbBuf )
  2158. goto Ret;
  2159. pbCurPtr += sizeof(DWORD); // fwd past size
  2160. pbLocalConfirm = pbCurPtr;
  2161. if (cbLocalConfirm != cbConfirm) // sizechk
  2162. goto Ret;
  2163. pbCurPtr += cbConfirm; // fwd past data
  2164. //
  2165. // do a single size sanity check before copying data out.
  2166. //
  2167. if( pbCurPtr != (pbBuf + cbBuf) )
  2168. goto Ret;
  2169. MoveMemory(pbBuf, pbLocalMK, cbLocalMK); // move left to front for later realloc
  2170. CopyMemory(rgbSalt, pbLocalSalt, cbLocalSalt); // data
  2171. CopyMemory(rgbConfirm, pbLocalConfirm, cbLocalConfirm); // data
  2172. //
  2173. // MK fixup
  2174. //
  2175. *pcbMK = cbLocalMK;
  2176. pbCurPtr = (PBYTE)SSReAlloc(pbBuf, *pcbMK); // shorten to MK data
  2177. if (pbCurPtr == NULL)
  2178. {
  2179. dwRet = PST_E_FAIL;
  2180. if (pbBuf) {
  2181. SSFree(pbBuf);
  2182. *ppbMK = NULL;
  2183. }
  2184. goto Ret;
  2185. }
  2186. *ppbMK = pbCurPtr;
  2187. dwRet = PST_E_OK;
  2188. Ret:
  2189. return (dwRet == PST_E_OK);
  2190. }
  2191. BOOL FBPSetSecurityState(
  2192. LPCWSTR szUser,
  2193. LPCWSTR szMK,
  2194. BYTE rgbSalt[],
  2195. DWORD cbSalt,
  2196. BYTE rgbConfirm[],
  2197. DWORD cbConfirm,
  2198. PBYTE pbMK,
  2199. DWORD cbMK)
  2200. {
  2201. DWORD dwRet;
  2202. HKEY hMKKey = NULL;
  2203. // helpful pointer
  2204. PBYTE pbCurPtr;
  2205. DWORD cbBuf = cbSalt + cbConfirm + cbMK + 4*sizeof(DWORD); // ver + size + data
  2206. PBYTE pbBuf = (PBYTE)SSAlloc(cbBuf);
  2207. if (pbBuf == NULL)
  2208. {
  2209. dwRet = PST_E_FAIL;
  2210. goto Ret;
  2211. }
  2212. pbCurPtr = pbBuf;
  2213. // Security data format
  2214. // Version | size(MK) | MK | size(Salt) | Salt | size(Confirm) | Confirm
  2215. *(DWORD*)pbCurPtr = SECURITY_STATE_VERSION; // ver
  2216. pbCurPtr += sizeof(DWORD); // fwd past ver
  2217. // MK
  2218. *(DWORD*)pbCurPtr = cbMK; // size
  2219. pbCurPtr += sizeof(DWORD); // fwd past size
  2220. CopyMemory(pbCurPtr, pbMK, cbMK); // data
  2221. pbCurPtr += cbMK; // fwd past data
  2222. // Salt
  2223. *(DWORD*)pbCurPtr = cbSalt; // size
  2224. pbCurPtr += sizeof(DWORD); // fwd past size
  2225. CopyMemory(pbCurPtr, rgbSalt, cbSalt); // data
  2226. pbCurPtr += cbSalt; // fwd past data
  2227. // Confirm
  2228. *(DWORD*)pbCurPtr = cbConfirm; // size
  2229. pbCurPtr += sizeof(DWORD); // fwd past size
  2230. CopyMemory(pbCurPtr, rgbConfirm, cbConfirm);// data
  2231. pbCurPtr += cbConfirm; // fwd past data
  2232. // Open User Key //
  2233. if (PST_E_OK != (dwRet =
  2234. GetPSTMasterKeyHKEY(
  2235. szUser,
  2236. szMK,
  2237. &hMKKey)) )
  2238. goto Ret;
  2239. if (ERROR_SUCCESS != (dwRet =
  2240. RegSetValueExU(
  2241. hMKKey,
  2242. REG_SECURITY_SALT_VALNAME,
  2243. 0,
  2244. REG_BINARY,
  2245. pbBuf,
  2246. cbBuf)) )
  2247. goto Ret;
  2248. dwRet = PST_E_OK;
  2249. Ret:
  2250. if (hMKKey)
  2251. RegCloseKey(hMKKey);
  2252. if (pbBuf)
  2253. SSFree(pbBuf);
  2254. return (dwRet == PST_E_OK);
  2255. }
  2256. // end SECURITY STATE
  2257. ///////////////////////////////////////////////////////////////////////
  2258. ///////////////////////////////////////////////////////////////////////
  2259. ///////////////////////////////////////////////////////////////////////
  2260. ///////////////////////////////////////////////////////////////////////
  2261. // begin global MAC Key storage
  2262. #define INTERNAL_MAC_KEY_VERSION 0x1
  2263. BOOL FGetInternalMACKey(LPCWSTR szUser, PBYTE* ppbKey, DWORD* pcbKey)
  2264. {
  2265. BOOL fRet = FALSE;
  2266. HKEY hBaseKey = NULL;
  2267. HKEY hDataKey = NULL;
  2268. // Open User Key //
  2269. if (PST_E_OK !=
  2270. GetPSTUserHKEY(
  2271. szUser,
  2272. &hBaseKey,
  2273. NULL))
  2274. goto Ret;
  2275. // Open Data Key //
  2276. if (ERROR_SUCCESS !=
  2277. RegOpenKeyExU(
  2278. hBaseKey,
  2279. REG_DATA_LOC,
  2280. 0,
  2281. KEY_READ | KEY_WRITE,
  2282. &hDataKey))
  2283. goto Ret;
  2284. if (ERROR_SUCCESS !=
  2285. RegGetValue(
  2286. hDataKey,
  2287. REG_USER_INTERNAL_MAC_KEY,
  2288. ppbKey,
  2289. pcbKey))
  2290. goto Ret;
  2291. if(*pcbKey < sizeof(DWORD))
  2292. goto Ret;
  2293. // only know about ver 1 keys
  2294. if (*(DWORD*)*ppbKey != INTERNAL_MAC_KEY_VERSION)
  2295. goto Ret;
  2296. // strip version tag, shift left
  2297. *pcbKey -= sizeof(DWORD);
  2298. MoveMemory(*ppbKey, *ppbKey + sizeof(DWORD), *pcbKey);
  2299. fRet = TRUE;
  2300. Ret:
  2301. if (hBaseKey)
  2302. RegCloseKey(hBaseKey);
  2303. if (hDataKey)
  2304. RegCloseKey(hDataKey);
  2305. return fRet;
  2306. }
  2307. BOOL FSetInternalMACKey(LPCWSTR szUser, PBYTE pbKey, DWORD cbKey)
  2308. {
  2309. BOOL fRet = FALSE;
  2310. HKEY hBaseKey = NULL;
  2311. HKEY hDataKey = NULL;
  2312. DWORD dwCreate;
  2313. // no need to alloc, we assume we know cbKey size (2 deskeys + blocklen pad + dwVersion)
  2314. BYTE rgbTmp[(8*3)+sizeof(DWORD)];
  2315. // ASSUME: two deskeys, each 8 bytes + blocklen pad
  2316. if (cbKey != (8*3))
  2317. goto Ret;
  2318. // tack version on front
  2319. *(DWORD*)rgbTmp = (DWORD)INTERNAL_MAC_KEY_VERSION;
  2320. CopyMemory(rgbTmp + sizeof(DWORD), pbKey, cbKey);
  2321. // Open User Key //
  2322. if (PST_E_OK !=
  2323. GetPSTUserHKEY(
  2324. szUser,
  2325. &hBaseKey,
  2326. NULL))
  2327. goto Ret;
  2328. // Open/Create Data Key //
  2329. if (ERROR_SUCCESS !=
  2330. RegCreateKeyExU(
  2331. hBaseKey,
  2332. REG_DATA_LOC,
  2333. 0,
  2334. NULL, // address of class string
  2335. 0,
  2336. KEY_READ | KEY_WRITE,
  2337. NULL,
  2338. &hDataKey,
  2339. &dwCreate))
  2340. goto Ret;
  2341. if (ERROR_SUCCESS !=
  2342. RegSetValueExU(
  2343. hDataKey,
  2344. REG_USER_INTERNAL_MAC_KEY,
  2345. 0,
  2346. REG_BINARY,
  2347. rgbTmp,
  2348. sizeof(rgbTmp) ))
  2349. goto Ret;
  2350. fRet = TRUE;
  2351. Ret:
  2352. if (hBaseKey)
  2353. RegCloseKey(hBaseKey);
  2354. if (hDataKey)
  2355. RegCloseKey(hDataKey);
  2356. return fRet;
  2357. }
  2358. // end global MAC Key storage
  2359. ///////////////////////////////////////////////////////////////////////
  2360. ///////////////////////////////////////////////////////////////////////
  2361. BOOL
  2362. DeleteAllUserData(
  2363. HKEY hKey
  2364. )
  2365. {
  2366. BOOL fRestorePrivs = FALSE;
  2367. BOOL fRet = FALSE;
  2368. //
  2369. // enable backup and restore privs on NT to circumvent any security
  2370. // settings.
  2371. //
  2372. if(FIsWinNT()) {
  2373. SetCurrentPrivilege(L"SeRestorePrivilege", TRUE);
  2374. SetCurrentPrivilege(L"SeBackupPrivilege", TRUE);
  2375. fRestorePrivs = TRUE;
  2376. }
  2377. fRet = DeleteUserData( hKey );
  2378. if(fRestorePrivs) {
  2379. SetCurrentPrivilege(L"SeRestorePrivilege", FALSE);
  2380. SetCurrentPrivilege(L"SeBackupPrivilege", FALSE);
  2381. }
  2382. return fRet;
  2383. }
  2384. BOOL
  2385. DeleteUserData(
  2386. HKEY hKey
  2387. )
  2388. {
  2389. LONG rc;
  2390. WCHAR szSubKey[MAX_PATH];
  2391. DWORD cchSubKeyLength;
  2392. DWORD dwSubKeyMaxIndex;
  2393. DWORD dwDisposition;
  2394. cchSubKeyLength = sizeof(szSubKey) / sizeof(WCHAR);
  2395. // First, get the number of subkeys, so we can decrement the index,
  2396. // and avoid and re-indexing of the subkeys
  2397. if (ERROR_SUCCESS != RegQueryInfoKeyA(hKey,
  2398. NULL,
  2399. NULL,
  2400. NULL,
  2401. &dwSubKeyMaxIndex,
  2402. NULL,
  2403. NULL,
  2404. NULL,
  2405. NULL,
  2406. NULL,
  2407. NULL,
  2408. NULL))
  2409. {
  2410. return FALSE;
  2411. }
  2412. if (dwSubKeyMaxIndex) dwSubKeyMaxIndex--; // 0 based index, so index = #keys -1
  2413. while((rc=RegEnumKeyExU(
  2414. hKey,
  2415. dwSubKeyMaxIndex,
  2416. szSubKey,
  2417. &cchSubKeyLength,
  2418. NULL,
  2419. NULL,
  2420. NULL,
  2421. NULL)
  2422. ) != ERROR_NO_MORE_ITEMS) { // are we done?
  2423. if(rc == ERROR_SUCCESS)
  2424. {
  2425. HKEY hSubKey;
  2426. LONG lRet;
  2427. lRet = RegCreateKeyExU(
  2428. hKey,
  2429. szSubKey,
  2430. 0,
  2431. NULL,
  2432. REG_OPTION_BACKUP_RESTORE, // in winnt.h
  2433. DELETE | KEY_ENUMERATE_SUB_KEYS,
  2434. NULL,
  2435. &hSubKey,
  2436. &dwDisposition
  2437. );
  2438. if(lRet != ERROR_SUCCESS)
  2439. return FALSE;
  2440. //
  2441. // recurse
  2442. //
  2443. DeleteUserData(hSubKey);
  2444. RegDeleteKeyU(hKey, szSubKey);
  2445. RegCloseKey(hSubKey);
  2446. // increment index into the key
  2447. dwSubKeyMaxIndex--;
  2448. // reset buffer size
  2449. cchSubKeyLength = sizeof(szSubKey) / sizeof(WCHAR);
  2450. // Continue the festivities
  2451. continue;
  2452. }
  2453. else
  2454. {
  2455. //
  2456. // note: we need to watch for ERROR_MORE_DATA
  2457. // this indicates we need a bigger szSubKey buffer
  2458. //
  2459. return FALSE;
  2460. }
  2461. }
  2462. return TRUE;
  2463. }