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.

356 lines
7.2 KiB

  1. //*************************************************************
  2. //
  3. // profile.hxx
  4. //
  5. // Header file for Profile.cpp
  6. //
  7. // Microsoft Confidential
  8. // Copyright (c) Microsoft Corporation 2000
  9. // All rights reserved
  10. //
  11. //*************************************************************
  12. #ifndef _PROFILE_HXX_
  13. #define _PROFILE_HXX_
  14. #include "iprofile.h"
  15. //
  16. // Number of buckets in the hash table.
  17. //
  18. #define NUM_OF_BUCKETS 23
  19. //
  20. // Flags used by WatchHiveRefCount.
  21. //
  22. #define WHRC_UNLOAD_HIVE 0x00000001
  23. #define WHRC_UNLOAD_CLASSESROOT 0x00000002
  24. #define WHRC_NOT_HIVE_OPEN_HANDLE 0x00000004
  25. //
  26. // .Default HKEY_USERS
  27. //
  28. const LPTSTR DEFAULT_HKU = TEXT(".DEFAULT");
  29. //
  30. // Entries which contain the user profile critical sections. These entries are
  31. // used by the synchronization manager.
  32. //
  33. class CSEntry
  34. {
  35. public:
  36. CSEntry()
  37. {
  38. pNext = NULL;
  39. pSid = NULL;
  40. dwRef = 0;
  41. szRPCEndPoint = NULL;
  42. }
  43. ~CSEntry()
  44. {
  45. pNext = NULL;
  46. pSid = NULL;
  47. if (szRPCEndPoint)
  48. LocalFree(szRPCEndPoint);
  49. }
  50. friend class CSyncManager;
  51. BOOL Initialize(LPTSTR pSid);
  52. void Uninitialize();
  53. void EnterCS();
  54. void LeaveCS();
  55. BOOL NoMoreUser();
  56. void IncrementRefCount();
  57. LPTSTR GetRPCEndPoint(void) { return szRPCEndPoint; }
  58. void SetRPCEndPoint(LPTSTR lpRPCEndPoint);
  59. private:
  60. class CSEntry* pNext;
  61. LPTSTR pSid;
  62. CRITICAL_SECTION csUser;
  63. LPTSTR szRPCEndPoint;
  64. DWORD dwRef;
  65. };
  66. //
  67. // Hash table. Uses chained bucket.
  68. //
  69. class BUCKET
  70. {
  71. public:
  72. BUCKET(LPTSTR ptszStr, CSEntry* pEntryParam)
  73. {
  74. ptszString = ptszStr;
  75. pEntry = pEntryParam;
  76. pNext = NULL;
  77. }
  78. ~BUCKET()
  79. {
  80. ptszString = NULL;
  81. pEntry = NULL;
  82. pNext = NULL;
  83. }
  84. BUCKET* pNext;
  85. LPTSTR ptszString;
  86. CSEntry* pEntry;
  87. };
  88. typedef BUCKET* PBUCKET;
  89. class CHashTable
  90. {
  91. public:
  92. CHashTable() {}
  93. ~CHashTable() {}
  94. void Initialize();
  95. DWORD Hash(LPTSTR ptszString);
  96. BOOL IsInTable(LPTSTR ptszString, CSEntry** ppCSEntry = NULL);
  97. BOOL HashAdd(LPTSTR ptszString, CSEntry* pCSEntry = NULL);
  98. void HashDelete(LPTSTR ptszString);
  99. private:
  100. PBUCKET Table[NUM_OF_BUCKETS];
  101. };
  102. //
  103. // The synchronization manager. This class synchronizes LoadUserProfile/
  104. // UnloadUserProfile calls.
  105. //
  106. class CSyncManager
  107. {
  108. public:
  109. //
  110. // Constructor.
  111. //
  112. CSyncManager()
  113. {
  114. pCSList = NULL;
  115. }
  116. //
  117. // Initializes the table, the list, and the critical section.
  118. //
  119. BOOL Initialize();
  120. //
  121. // Sync functions. These functions are protected by a critical section
  122. // No two users can update their locks at the same time. This can be
  123. // optimized but optimization requires a lot more code. This is also the
  124. // only place where user's profile locks gets held and released.
  125. //
  126. BOOL EnterLock(LPTSTR pSid, LPTSTR lpRPCEndPoint);
  127. BOOL LeaveLock(LPTSTR pSid);
  128. LPTSTR GetRPCEndPoint(LPTSTR pSid);
  129. private:
  130. CHashTable cTable; // All the user profile critical section's associated sids.
  131. CSEntry* pCSList;
  132. CRITICAL_SECTION cs;
  133. };
  134. //
  135. // Mapping between profile work lists and threads. This is for the registry
  136. // key leak fix.
  137. //
  138. class MAP
  139. {
  140. public:
  141. MAP();
  142. ~MAP() {}
  143. friend class CUserProfile;
  144. //
  145. // Delete/insert a work item from/into the map.
  146. //
  147. void Delete(DWORD dwIndex);
  148. void Insert(HANDLE hEvent, LPTSTR ptszSid);
  149. BOOL IsEmpty() { return dwItems <= 1; }
  150. LPTSTR GetSid(DWORD dwIndex);
  151. private:
  152. MAP* pNext;
  153. //
  154. // These two arrays must always be in sync.
  155. //
  156. HANDLE rghEvents[MAXIMUM_WAIT_OBJECTS];
  157. LPTSTR rgSids[MAXIMUM_WAIT_OBJECTS];
  158. DWORD dwItems;
  159. };
  160. typedef MAP* PMAP;
  161. //
  162. // The IUserProfile interface functions use this class api to do the core processing. User profiles are loaded
  163. // unloaded through the api provided in this class. Console winlogon is the server and only one global instance
  164. // of this class runs in console winlogon.
  165. //
  166. class CUserProfile
  167. {
  168. public:
  169. //
  170. // Constructor/Destructor.
  171. //
  172. CUserProfile() {bInitialized = FALSE; bConsoleWinlogon = FALSE; }
  173. ~CUserProfile() {};
  174. //
  175. // Initialization function.
  176. //
  177. void Initialize();
  178. //
  179. // Are we in console winlogon process?
  180. //
  181. BOOL IsConsoleWinlogon() { return bConsoleWinlogon; }
  182. //
  183. // Main function for the worker threads.
  184. //
  185. DWORD WorkerThreadMain(PMAP pmap);
  186. //
  187. // Make getting the user profile lock easier.
  188. //
  189. BOOL EnterUserProfileLockLocal(LPTSTR pSid);
  190. BOOL LeaveUserProfileLockLocal(LPTSTR pSid);
  191. //
  192. // The actual LoadUserProfile/UnloadUserProfile that does all the work.
  193. //
  194. BOOL LoadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, LPPROFILEINFO lpProfileInfo, LPTSTR lpRPCEndPoint);
  195. BOOL UnloadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, HKEY hProfile, LPTSTR lpRPCEndPoint);
  196. //
  197. // Returns the RPCEndPoint associated with registered IProfileDialog interface
  198. //
  199. LPTSTR GetRPCEndPoint(LPTSTR pSid);
  200. private:
  201. //
  202. // Handles the situation when keys are leaked from the registry.
  203. //
  204. DWORD HandleRegKeyLeak(LPTSTR lpSidString,
  205. LPPROFILE lpProfile,
  206. BOOL bUnloadHiveSucceeded,
  207. DWORD* dwWatchHiveFlags,
  208. DWORD* dwCopyTmpHive,
  209. LPTSTR pTmpHiveFile);
  210. //
  211. // This function is called when a registry key is leaked.
  212. //
  213. STDMETHODIMP WatchHiveRefCount(LPCTSTR pctszSid, DWORD dwWHRCFlags);
  214. //
  215. // Get the reference count.
  216. //
  217. long GetRefCountAndFlags(LPCTSTR ptszSid, HKEY* phkPL, DWORD* dwRefCount, DWORD* dwInternalFlags);
  218. //
  219. // Add a new work item to both the map structure and a worker thread.
  220. //
  221. HRESULT AddWorkItem(LPCTSTR ptszSid, HANDLE hEvent);
  222. //
  223. // Delete the profile as well if necessary, i.e.,
  224. // temporary profiles, guest profiles, and mandatory profiles.
  225. //
  226. void CleanupUserProfile(LPTSTR ptszSid, HKEY* phkProfileList);
  227. //
  228. // Reg leak fix structures. This hash table holds the sids of all the
  229. // unloaded user registry hives.
  230. //
  231. CRITICAL_SECTION csMap;
  232. PMAP pMap;
  233. CHashTable cTable;
  234. //
  235. // LoadUserProfile/UnloadUserProfile synchronization manager.
  236. //
  237. CSyncManager cSyncMgr;
  238. //
  239. // Tells the caller if we are already initialized. Also tells us if we are
  240. // in the console winlogon process because it's the only process that'll
  241. // initialize this object.
  242. //
  243. BOOL bInitialized;
  244. //
  245. // Tells us if we are in console winlogon process
  246. //
  247. BOOL bConsoleWinlogon;
  248. };
  249. //
  250. // Functions prototype for binding rpc handle
  251. //
  252. BOOL GetInterface(handle_t *phIfHandle, LPTSTR lpRPCEndPoint);
  253. BOOL ReleaseInterface(handle_t *phIfHandle);
  254. #endif