Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

967 lines
23 KiB

  1. //
  2. // Author: DebiM
  3. // Date: September 1996
  4. //
  5. // File: csuser.cxx
  6. //
  7. // Maintains a list of class containers per User SID.
  8. // Looks up this list for every IClassAccess call from OLE32/SCM.
  9. //
  10. //
  11. //---------------------------------------------------------------------
  12. #include "cstore.hxx"
  13. void GetCurrentUsn(LPOLESTR pStoreUsn);
  14. //
  15. // Link list pointer for Class Containers Seen
  16. //
  17. extern CLASSCONTAINER *gpContainerHead;
  18. //
  19. // Link list pointer for User Profiles Seen
  20. //
  21. extern USERPROFILE *gpUserHead;
  22. // Initialzed in InitializeClassStore at startup
  23. extern CRITICAL_SECTION ClassStoreBindList;
  24. //-------------------------------------------------------------------------
  25. //
  26. // OpenUserRegKey
  27. //
  28. // Opens a key under a user's HKEY_CLASSES_ROOT registry key. On NT5
  29. // HKCR is equivalent to HKEY_USERS\{sid string}\Software\Classes.
  30. //
  31. // A SID string is used to create
  32. // the proper registry key name to open.
  33. //
  34. //-------------------------------------------------------------------------
  35. DWORD
  36. OpenUserRegKey(
  37. IN PSID pSid,
  38. IN WCHAR * pwszSubKey,
  39. OUT HKEY * phKey
  40. )
  41. {
  42. UNICODE_STRING UnicodeString;
  43. WCHAR * pwszKey;
  44. DWORD AllocSize;
  45. NTSTATUS Status;
  46. UnicodeString.Length = UnicodeString.MaximumLength = 0;
  47. UnicodeString.Buffer = 0;
  48. Status = RtlConvertSidToUnicodeString(
  49. &UnicodeString,
  50. pSid,
  51. (BOOLEAN)TRUE // Allocate
  52. );
  53. //
  54. // Don't return a raw NT status code. This is the only possible error
  55. // condition presuming our sid is valid.
  56. //
  57. if ( Status != STATUS_SUCCESS )
  58. return ERROR_OUTOFMEMORY;
  59. //
  60. // Your friendly reminder, unicode string length is in bytes and doesn't include
  61. // null terminator, if any.
  62. // Add byte for '\\' and end null.
  63. //
  64. AllocSize = UnicodeString.Length + ((1 + lstrlen(pwszSubKey) + 1) * sizeof(WCHAR));
  65. pwszKey = (WCHAR *) PrivMemAlloc( AllocSize );
  66. if ( pwszKey )
  67. {
  68. memcpy( pwszKey, UnicodeString.Buffer, UnicodeString.Length );
  69. pwszKey[UnicodeString.Length / 2] = L'\\';
  70. lstrcpyW( &pwszKey[(UnicodeString.Length / 2) + 1], pwszSubKey );
  71. }
  72. RtlFreeUnicodeString( &UnicodeString );
  73. if ( ! pwszKey )
  74. return ERROR_OUTOFMEMORY;
  75. Status = RegOpenKeyEx(
  76. HKEY_USERS,
  77. pwszKey,
  78. 0,
  79. KEY_READ,
  80. phKey );
  81. PrivMemFree( pwszKey );
  82. return Status;
  83. }
  84. //
  85. // GetUserSid
  86. // ----------
  87. //
  88. // Synopsis: return the user SID of the caller.
  89. //
  90. // Arguments: &PSID - Where to store the caller's PSID
  91. //
  92. // Returns: HRESULT - S_OK if successful
  93. // E_FAIL otherwise
  94. //
  95. SID LocalSystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID };
  96. #define CS_CALL_LOCALSYSTEM 1
  97. #define CS_CALL_USERPROCESS 2
  98. #define CS_CALL_IMPERSONATED 3
  99. HRESULT GetUserSid(PSID *ppUserSid, UINT *pCallType)
  100. {
  101. BYTE achBuffer[100];
  102. PTOKEN_USER pUser = (PTOKEN_USER) &achBuffer;
  103. PSID pSid;
  104. DWORD dwBytesRequired;
  105. BOOL fAllocatedBuffer = FALSE;
  106. HRESULT hr = S_OK;
  107. HANDLE hUserToken = NULL;
  108. BOOL fImpersonated = TRUE;
  109. *pCallType = CS_CALL_USERPROCESS;
  110. // Initialize
  111. *ppUserSid = NULL;
  112. // Get caller's token while impersonating
  113. if (!OpenThreadToken(GetCurrentThread(),
  114. TOKEN_DUPLICATE | TOKEN_QUERY,
  115. TRUE,
  116. &hUserToken))
  117. {
  118. fImpersonated = FALSE;
  119. if (ERROR_NO_TOKEN != GetLastError())
  120. return HRESULT_FROM_WIN32(GetLastError());
  121. if (!OpenProcessToken(GetCurrentProcess(),
  122. TOKEN_DUPLICATE | TOKEN_QUERY,
  123. &hUserToken))
  124. {
  125. return HRESULT_FROM_WIN32(GetLastError());
  126. }
  127. }
  128. if (SUCCEEDED(hr))
  129. {
  130. if (!GetTokenInformation(
  131. hUserToken, // Handle
  132. TokenUser, // TokenInformationClass
  133. pUser, // TokenInformation
  134. sizeof(achBuffer), // TokenInformationLength
  135. &dwBytesRequired // ReturnLength
  136. ))
  137. {
  138. //
  139. // Need to handle the case of insufficient buffer size.
  140. //
  141. if (sizeof(achBuffer) >= dwBytesRequired)
  142. {
  143. hr = HRESULT_FROM_WIN32(GetLastError());
  144. }
  145. if (SUCCEEDED(hr))
  146. {
  147. //
  148. // Allocate space for the user info
  149. //
  150. pUser = (PTOKEN_USER) CoTaskMemAlloc(dwBytesRequired);
  151. if (pUser == NULL)
  152. {
  153. hr = E_OUTOFMEMORY;
  154. }
  155. }
  156. if (SUCCEEDED(hr))
  157. {
  158. fAllocatedBuffer = TRUE;
  159. //
  160. // Read in the UserInfo
  161. //
  162. if (!GetTokenInformation(
  163. hUserToken, // Handle
  164. TokenUser, // TokenInformationClass
  165. pUser, // TokenInformation
  166. dwBytesRequired, // TokenInformationLength
  167. &dwBytesRequired // ReturnLength
  168. ))
  169. {
  170. hr = HRESULT_FROM_WIN32(GetLastError());
  171. }
  172. }
  173. }
  174. }
  175. if (SUCCEEDED(hr))
  176. {
  177. //
  178. // Distinguish between
  179. // a) LOCAL_SYSTEM,
  180. // b) Impersonated Call from a LOCAL_SYSTEM
  181. // and c) In_proc call from a user process
  182. //
  183. // For case (c) make the SID null.
  184. //
  185. if (EqualSid(pUser->User.Sid, &LocalSystemSid))
  186. {
  187. *pCallType = CS_CALL_LOCALSYSTEM;
  188. }
  189. else
  190. if (fImpersonated)
  191. {
  192. *pCallType = CS_CALL_IMPERSONATED;
  193. }
  194. else
  195. {
  196. *pCallType = CS_CALL_USERPROCESS;
  197. }
  198. // Alloc buffer for copy of SID
  199. dwBytesRequired = GetLengthSid(pUser->User.Sid);
  200. *ppUserSid = CoTaskMemAlloc(dwBytesRequired);
  201. if (*ppUserSid == NULL)
  202. {
  203. hr = E_OUTOFMEMORY;
  204. }
  205. else
  206. {
  207. // Copy SID
  208. if (!CopySid(dwBytesRequired, *ppUserSid, pUser->User.Sid))
  209. {
  210. hr = HRESULT_FROM_WIN32(GetLastError());
  211. CoTaskMemFree(*ppUserSid);
  212. *ppUserSid = NULL;
  213. }
  214. }
  215. }
  216. if (fAllocatedBuffer == TRUE)
  217. {
  218. CoTaskMemFree(pUser);
  219. }
  220. if (hUserToken)
  221. CloseHandle( hUserToken );
  222. return hr;
  223. }
  224. #if 0
  225. //
  226. // GetDomainClassStore
  227. // -------------------
  228. //
  229. // This will go away.
  230. //
  231. // Currently this is used to get the Class Store Path
  232. // for the domain.
  233. //
  234. #define DEFAULTSTORENAME L"CN=ClassStore"
  235. HRESULT
  236. GetDomainClassStore(
  237. LPOLESTR * pszDefaultContainer,
  238. LPOLESTR * pszDefaultStore)
  239. //
  240. // Finds the Root Path for the DC for this machine
  241. // Then gets the Default Known CLass Store for the DC
  242. //
  243. {
  244. HRESULT hr;
  245. LPOLESTR PathNames[2];
  246. VARIANT * pVarFilter = NULL;
  247. IEnumVARIANT * pEnum;
  248. IADs * pADs;
  249. VARIANT VariantArray[2];
  250. IDispatch * pDispatch = NULL;
  251. ULONG cFetched;
  252. IADsContainer * pContainer = NULL;
  253. //
  254. // Do a bind to the DC by a GetObject for the Path LDAP:
  255. //
  256. hr = ADsGetObject(
  257. L"LDAP:",
  258. IID_IADsContainer,
  259. (void **)&pContainer
  260. );
  261. RETURN_ON_FAILURE(hr);
  262. hr = ADsBuildEnumerator(
  263. pContainer,
  264. &pEnum
  265. );
  266. hr = ADsEnumerateNext(
  267. pEnum,
  268. 1,
  269. VariantArray,
  270. &cFetched
  271. );
  272. pEnum->Release();
  273. if ((hr == S_FALSE) || (cFetched == 0))
  274. {
  275. return E_FAIL;
  276. }
  277. pDispatch = VariantArray[0].pdispVal;
  278. memset(VariantArray, 0, sizeof(VARIANT)*2);
  279. hr = pDispatch->QueryInterface(IID_IADs, (void **) &pADs) ;
  280. pDispatch->Release();
  281. pADs->get_ADsPath(pszDefaultContainer);
  282. pADs->Release();
  283. pContainer->Release();
  284. *pszDefaultStore = DEFAULTSTORENAME;
  285. return S_OK;
  286. }
  287. #endif
  288. // GetKnownClassStore
  289. // -------------------
  290. //
  291. //
  292. // Synopsis: Gets a class container path.
  293. // Looks up list of containers seen
  294. // and returns the pointer for this container.
  295. // If a new class container is seen,
  296. // it is added to this list and its pointer is returned.
  297. //
  298. // Arguments: [in] pszPath - Class container Path
  299. // Returns: pClassStoreNode : Class Container Node
  300. //
  301. //
  302. PCLASSCONTAINER
  303. GetKnownClassStore (LPOLESTR pszPath)
  304. {
  305. PCLASSCONTAINER pCS = gpContainerHead;
  306. //
  307. // Chain thru the link list of containers ...
  308. //
  309. while (pCS != NULL)
  310. {
  311. if (!wcscmp (pszPath, pCS->pszClassStorePath))
  312. {
  313. break;
  314. }
  315. pCS = pCS->pNextClassStore;
  316. }
  317. //
  318. // If not matched ..
  319. // Add it to the beginning of the list.
  320. //
  321. if (pCS == NULL)
  322. {
  323. pCS = (CLASSCONTAINER *) CoTaskMemAlloc (sizeof(CLASSCONTAINER));
  324. pCS->pNextClassStore = gpContainerHead;
  325. gpContainerHead = pCS;
  326. pCS->gpClassStore = NULL;
  327. pCS->cBindFailures = 0;
  328. pCS->cAccess = 0;
  329. pCS->cNotFound = 0;
  330. pCS->pszClassStorePath = (LPOLESTR)CoTaskMemAlloc
  331. (sizeof(WCHAR) * (wcslen(pszPath)+1));
  332. wcscpy (pCS->pszClassStorePath, pszPath);
  333. //++cStores;
  334. }
  335. return pCS;
  336. }
  337. /*
  338. //
  339. // GetUserSyncPoint
  340. // ----------------
  341. //
  342. // Synopsis: Receives and Stores the Next Sync Point.
  343. // Reads and returns the current sync point.
  344. // When Advance is called the current becomes the lastsyncpoint.
  345. // No error returned,
  346. //
  347. // BUGBUG. This is NOT thread-safe now. Fix it!
  348. //
  349. HRESULT GetUserSyncPoint(LPWSTR pszContainer, CSUSN *pPrevUsn)
  350. {
  351. LONG lErrorCode;
  352. DWORD dwDataLen = _MAX_PATH;
  353. DWORD dwType;
  354. HKEY hKey = NULL;
  355. HRESULT hr = S_OK;
  356. WCHAR wszSync[_MAX_PATH + 1];
  357. PSID pUserSid;
  358. CSUSN CurrUsn;
  359. //
  360. // Get the current USN
  361. //
  362. GetCurrentUsn(&CurrUsn);
  363. //
  364. // Get the SID of the calling process
  365. //
  366. hr = GetUserSid(&pUserSid);
  367. RETURN_ON_FAILURE(hr);
  368. //
  369. // This should be outside of impersonation
  370. // So revert to LOCAL SYSTEM.
  371. RpcRevertToSelf();
  372. lErrorCode = OpenUserRegKey(
  373. pUserSid,
  374. L"Software\\Microsoft\\ClassStore",
  375. &hKey);
  376. if (lErrorCode != ERROR_SUCCESS)
  377. {
  378. DWORD dwDisp;
  379. lErrorCode = RegCreateKeyEx(HKEY_CURRENT_USER,
  380. L"Software\\Microsoft\\ClassStore",
  381. NULL,
  382. L"REG_SZ",
  383. REG_OPTION_NON_VOLATILE,
  384. KEY_ALL_ACCESS,
  385. NULL,
  386. &hKey,
  387. &dwDisp);
  388. }
  389. lErrorCode = RegQueryValueEx(hKey,
  390. pszContainer,
  391. NULL,
  392. &dwType,
  393. (LPBYTE)wszSync,
  394. &dwDataLen);
  395. if (lErrorCode != ERROR_SUCCESS)
  396. {
  397. pPrevUsn->dwLowDateTime = CurrUsn.dwLowDateTime;
  398. pPrevUsn->dwHighDateTime = CurrUsn.dwHighDateTime;
  399. wsprintf (wszSync, L"%lu %lu %lu %lu",
  400. pPrevUsn->dwHighDateTime,
  401. pPrevUsn->dwLowDateTime,
  402. pPrevUsn->dwHighDateTime,
  403. pPrevUsn->dwLowDateTime);
  404. lErrorCode = RegSetValueEx(
  405. hKey,
  406. pszContainer, //L"LastSync",
  407. NULL,
  408. REG_SZ,
  409. (LPBYTE)wszSync,
  410. (2 * wcslen(wszSync)) + 2);
  411. RegCloseKey(hKey);
  412. }
  413. else
  414. {
  415. swscanf (wszSync, L"%lu %lu",
  416. &pPrevUsn->dwHighDateTime,
  417. &pPrevUsn->dwLowDateTime);
  418. wsprintf (wszSync, L"%lu %lu %lu %lu",
  419. pPrevUsn->dwHighDateTime,
  420. pPrevUsn->dwLowDateTime,
  421. CurrUsn.dwHighDateTime,
  422. CurrUsn.dwLowDateTime);
  423. lErrorCode = RegSetValueEx(
  424. hKey,
  425. pszContainer, //L"LastSync",
  426. NULL,
  427. REG_SZ,
  428. (LPBYTE)wszSync,
  429. (2 * wcslen(wszSync)) + 2);
  430. RegCloseKey(hKey);
  431. }
  432. // Impersonate again
  433. RpcImpersonateClient((RPC_BINDING_HANDLE)0);
  434. return S_OK;
  435. }
  436. //
  437. // AdvanceUserSyncPoint
  438. // --------------------
  439. //
  440. // Synopsis: Makes the Next Sync Point as Last Sync Point.
  441. // No error returned,
  442. //
  443. //
  444. HRESULT AdvanceUserSyncPoint(LPWSTR pszContainer)
  445. {
  446. LONG lErrorCode;
  447. DWORD dwDataLen = _MAX_PATH;
  448. DWORD dwType;
  449. HKEY hKey = NULL;
  450. HRESULT hr = S_OK;
  451. WCHAR wszSync[_MAX_PATH + 1];
  452. CSUSN PrevUsn, NextUsn;
  453. PSID pUserSid;
  454. //
  455. // Get the SID of the calling process
  456. // Already assumed to be under impersonation
  457. //
  458. hr = GetUserSid(&pUserSid);
  459. RETURN_ON_FAILURE(hr);
  460. //
  461. // This should be outside of impersonation
  462. // So revert to LOCAL SYSTEM.
  463. RpcRevertToSelf();
  464. lErrorCode = OpenUserRegKey(
  465. pUserSid,
  466. L"Software\\Microsoft\\ClassStore",
  467. &hKey);
  468. if ( lErrorCode == ERROR_SUCCESS)
  469. {
  470. lErrorCode = RegQueryValueEx(hKey,
  471. pszContainer,
  472. NULL,
  473. &dwType,
  474. (LPBYTE)wszSync,
  475. &dwDataLen);
  476. if (lErrorCode != ERROR_SUCCESS)
  477. {
  478. RegCloseKey(hKey);
  479. }
  480. }
  481. if (lErrorCode == ERROR_SUCCESS)
  482. {
  483. swscanf (wszSync, L"%lu %lu %lu %lu",
  484. &PrevUsn.dwHighDateTime,
  485. &PrevUsn.dwLowDateTime,
  486. &NextUsn.dwHighDateTime,
  487. &NextUsn.dwLowDateTime);
  488. wsprintf (wszSync, L"%lu %lu %lu %lu",
  489. NextUsn.dwHighDateTime,
  490. NextUsn.dwLowDateTime,
  491. NextUsn.dwHighDateTime,
  492. NextUsn.dwLowDateTime);
  493. lErrorCode = RegSetValueEx(
  494. hKey,
  495. pszContainer, //L"LastSync",
  496. NULL,
  497. REG_SZ,
  498. (LPBYTE)wszSync,
  499. (2 * wcslen(wszSync)) + 2);
  500. RegCloseKey(hKey);
  501. }
  502. // Impersonate again
  503. RpcImpersonateClient((RPC_BINDING_HANDLE)0);
  504. return S_OK;
  505. }
  506. */
  507. extern WCHAR pwszDebugPath [];
  508. extern BOOL fDebugPath;
  509. //
  510. // GetPerUserClassStore
  511. // ---------------------
  512. //
  513. // Synopsis: Gets the ADT Class Store List from the
  514. // per-user Registry.
  515. // Returns error if none defined,
  516. //
  517. // Arguments:
  518. // [out] ppStoreList : where to store list of class container
  519. // serial numbers
  520. // [out] pcStores : where to store number of class containers
  521. //
  522. // Returns: S_OK,
  523. //
  524. // History: Changed by (DebiM)
  525. // 2/24/97
  526. // return a NULL list of Class Stores when none defined.
  527. //
  528. #define MAXCLASSSTORES 10
  529. HRESULT GetPerUserClassStore(
  530. PSID pSid,
  531. UINT CallType,
  532. LPOLESTR **ppStoreList,
  533. DWORD *pcStores)
  534. {
  535. LONG lErrorCode;
  536. DWORD dwDataLen = 2000;
  537. DWORD dwType;
  538. HKEY hKey = NULL;
  539. HRESULT hr = S_OK;
  540. LPOLESTR pszPath, pszStart;
  541. LPOLESTR *ppszPath;
  542. WCHAR pszPathList [2000 + 1];
  543. *pcStores = 0;
  544. *ppStoreList = NULL;
  545. if (!fDebugPath)
  546. {
  547. switch (CallType)
  548. {
  549. case CS_CALL_LOCALSYSTEM :
  550. lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  551. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy",
  552. NULL,
  553. KEY_READ,
  554. &hKey);
  555. break;
  556. case CS_CALL_IMPERSONATED :
  557. lErrorCode = OpenUserRegKey(
  558. pSid,
  559. L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy",
  560. &hKey);
  561. break;
  562. case CS_CALL_USERPROCESS :
  563. lErrorCode = RegOpenKeyEx(HKEY_CURRENT_USER,
  564. L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy",
  565. NULL,
  566. KEY_ALL_ACCESS,
  567. &hKey);
  568. break;
  569. default:
  570. return E_FAIL;
  571. }
  572. if ( lErrorCode != ERROR_SUCCESS)
  573. {
  574. // treat as NULL list of Class Stores
  575. return S_OK;
  576. }
  577. lErrorCode = RegQueryValueEx(hKey,
  578. L"ClassStorePath",
  579. NULL,
  580. &dwType,
  581. (LPBYTE)pszPathList,
  582. &dwDataLen);
  583. RegCloseKey(hKey);
  584. if (lErrorCode != ERROR_SUCCESS)
  585. {
  586. // treat as NULL list of Class Stores
  587. return S_OK;
  588. }
  589. }
  590. else // Test Mode - Privately Set Path - Only for testing
  591. {
  592. wcscpy (&pszPathList[0], &pwszDebugPath[0]);
  593. }
  594. pszPath = pszPathList;
  595. ppszPath = *ppStoreList = (LPOLESTR *) CoTaskMemAlloc
  596. (sizeof(LPOLESTR) * MAXCLASSSTORES);
  597. if (*ppStoreList == NULL)
  598. {
  599. return E_OUTOFMEMORY;
  600. }
  601. //
  602. // Parse the list to separate different class containers
  603. //
  604. while (*pszPath)
  605. {
  606. while (*pszPath == L' ')
  607. ++pszPath;
  608. pszStart = pszPath;
  609. if (!*pszPath)
  610. break;
  611. if (*pszPath == L';')
  612. {
  613. ++pszPath;
  614. continue;
  615. }
  616. while (*pszPath && (*pszPath != L';'))
  617. ++pszPath;
  618. //
  619. // got one. save it.
  620. //
  621. *ppszPath = (LPOLESTR) CoTaskMemAlloc (sizeof(WCHAR) * (pszPath - pszStart + 1));
  622. memcpy (*ppszPath, pszStart, sizeof (WCHAR) * (pszPath - pszStart));
  623. *((*ppszPath)+(pszPath - pszStart)) = NULL;
  624. (ppszPath)++;
  625. ++(*pcStores);
  626. if (*pszPath == L';')
  627. {
  628. ++pszPath;
  629. }
  630. }
  631. return S_OK;
  632. }
  633. //
  634. // CacheSid
  635. // ---------
  636. //
  637. // Synopsis: Gets a SID.
  638. // Gets a list of class container paths for this SID.
  639. // Looks up known class containers to map these to
  640. // ClassStore Node pointers.
  641. // Caches the SID and associated class store list.
  642. //
  643. // Arguments:
  644. // [in] pUserSid: SID
  645. // [in] ppStoreList: Class Store Path List,
  646. // [in] cStores: Number of Class Stores
  647. //
  648. //
  649. // Returns: ppStoreList: Class Store Node List
  650. //
  651. PCLASSCONTAINER * CacheSid (PSID pUserSid,
  652. LPOLESTR *ppStoreList,
  653. DWORD cStores)
  654. {
  655. ULONG i;
  656. PCLASSCONTAINER *pStoreList, *pList;
  657. USERPROFILE *pUser;
  658. //
  659. // Allocate a User structure
  660. // and store the user specific values in it
  661. //
  662. pUser = (USERPROFILE *) CoTaskMemAlloc (sizeof(USERPROFILE));
  663. if (pUserSid)
  664. {
  665. pUser->pCachedSid = (PSID) CoTaskMemAlloc (GetLengthSid(pUserSid));
  666. CopySid(GetLengthSid(pUserSid),
  667. pUser->pCachedSid,
  668. pUserSid);
  669. }
  670. else
  671. pUser->pCachedSid = NULL;
  672. //
  673. // Link it to the beginning of the User Linklist
  674. //
  675. pUser->pNextUser = gpUserHead;
  676. gpUserHead = pUser;
  677. //
  678. // Find its ClassStore Path and setup the class store node chain
  679. //
  680. if (cStores == 0)
  681. {
  682. // NULL list of Class Stores
  683. pStoreList = pUser->pUserStoreList = NULL;
  684. }
  685. else
  686. {
  687. pStoreList = pList =
  688. pUser->pUserStoreList = (PCLASSCONTAINER *)
  689. CoTaskMemAlloc (sizeof(PCLASSCONTAINER) * cStores);
  690. for (i=0; i < cStores; i++)
  691. {
  692. *pList = GetKnownClassStore (*ppStoreList);
  693. ppStoreList++;
  694. pList++;
  695. }
  696. }
  697. pUser->cUserStoreCount = cStores;
  698. return pStoreList;
  699. }
  700. //
  701. // GetUserClassStores
  702. // ------------------
  703. //
  704. // Synopsis: This routine finds out the SID of the user.
  705. // It then looks up a global cache of SIDs to see if it
  706. // has accessed the list of Class Stores for this user.
  707. //
  708. // If not, it reads the Class Store list and parses it.
  709. // If it has prior knowledge it reurns the parsed list.
  710. // Arguments:
  711. // [out] pcStores: Number of Class Stores
  712. // [out] ppStoreIdList: Class Store Id List,
  713. //
  714. // Returns: S_OK
  715. // See change note for GetPerUserClassStore().
  716. // May return a NULL list of Class Stores.
  717. //
  718. //
  719. HRESULT GetUserClassStores(
  720. PCLASSCONTAINER **ppStoreList,
  721. DWORD *pcStores)
  722. {
  723. int l;
  724. PSID pUserSid;
  725. HRESULT hr = S_OK;
  726. UINT CallType;
  727. // Impersonate before accessing SID
  728. //RpcImpersonateClient((RPC_BINDING_HANDLE)0);
  729. //
  730. // Get the SID of the calling process
  731. //
  732. hr = GetUserSid(&pUserSid, &CallType);
  733. if (FAILED(hr))
  734. {
  735. pUserSid = NULL;
  736. hr = S_OK;
  737. }
  738. //RpcRevertToSelf();
  739. EnterCriticalSection (&ClassStoreBindList);
  740. //
  741. // Look this up in the global list of SIDs
  742. //
  743. USERPROFILE *pUser = gpUserHead;
  744. while (pUser != NULL)
  745. {
  746. if ((pUserSid == pUser->pCachedSid) || // Null UserSid
  747. (EqualSid(pUserSid, pUser->pCachedSid)))
  748. //
  749. // Found the match
  750. //
  751. {
  752. *ppStoreList = pUser->pUserStoreList;
  753. *pcStores = pUser->cUserStoreCount;
  754. break;
  755. }
  756. pUser = pUser->pNextUser;
  757. }
  758. if (pUser == NULL)
  759. {
  760. //
  761. // Didnt find this User's Sid
  762. // Get the Class Store List and cache it along with this SID
  763. //
  764. LPOLESTR *ppStoreNameList = NULL;
  765. UINT i;
  766. hr = GetPerUserClassStore(
  767. pUserSid, CallType, &ppStoreNameList, pcStores);
  768. //
  769. // Note that the above may return a NULL list of Class Stores
  770. //
  771. if (SUCCEEDED(hr))
  772. {
  773. *ppStoreList = CacheSid (pUserSid, ppStoreNameList, *pcStores);
  774. //
  775. // release memory allocated in GetPerUserClassStore()
  776. //
  777. for (i=0; i < *pcStores; ++i)
  778. {
  779. CoTaskMemFree (ppStoreNameList[i]);
  780. }
  781. if (ppStoreNameList)
  782. CoTaskMemFree (ppStoreNameList);
  783. }
  784. }
  785. LeaveCriticalSection (&ClassStoreBindList);
  786. //
  787. // Free the Sid
  788. //
  789. if (pUserSid)
  790. CoTaskMemFree (pUserSid);
  791. return hr;
  792. }