|
|
//*************************************************************
//
// profile.hxx
//
// Header file for Profile.cpp
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 2000
// All rights reserved
//
//*************************************************************
#ifndef _PROFILE_HXX_
#define _PROFILE_HXX_
#include "iprofile.h"
//
// Number of buckets in the hash table.
//
#define NUM_OF_BUCKETS 23
//
// Flags used by WatchHiveRefCount.
//
#define WHRC_UNLOAD_HIVE 0x00000001
#define WHRC_UNLOAD_CLASSESROOT 0x00000002
#define WHRC_NOT_HIVE_OPEN_HANDLE 0x00000004
//
// .Default HKEY_USERS
//
const LPTSTR DEFAULT_HKU = TEXT(".DEFAULT");
//
// Entries which contain the user profile critical sections. These entries are
// used by the synchronization manager.
//
class CSEntry { public:
CSEntry() { pNext = NULL; pSid = NULL; dwRef = 0; szRPCEndPoint = NULL; cbCookie = 0; pbCookie = NULL; } ~CSEntry() { pNext = NULL; pSid = NULL; if (szRPCEndPoint) LocalFree(szRPCEndPoint); if (pbCookie) LocalFree(pbCookie); }
friend class CSyncManager;
BOOL Initialize(LPTSTR pSid); void Uninitialize();
void EnterCS(); void LeaveCS();
BOOL NoMoreUser(); void IncrementRefCount();
LPTSTR GetRPCEndPoint(void) { return szRPCEndPoint; } void SetRPCEndPoint(LPTSTR lpRPCEndPoint);
BYTE* GetCookie() { return pbCookie; } DWORD GetCookieLen() { return cbCookie; } void SetCookie(BYTE* pbCookieIn, DWORD cbCookieIn);
private:
class CSEntry* pNext; LPTSTR pSid; CRITICAL_SECTION csUser; LPTSTR szRPCEndPoint; DWORD dwRef; DWORD cbCookie; BYTE* pbCookie; };
//
// Hash table. Uses chained bucket.
//
class BUCKET { public:
BUCKET(LPTSTR ptszStr, CSEntry* pEntryParam) { ptszString = ptszStr; pEntry = pEntryParam; pNext = NULL; } ~BUCKET() { ptszString = NULL; pEntry = NULL; pNext = NULL; }
BUCKET* pNext; LPTSTR ptszString; CSEntry* pEntry; }; typedef BUCKET* PBUCKET;
class CHashTable { public:
CHashTable() {} ~CHashTable() {}
void Initialize();
DWORD Hash(LPTSTR ptszString); BOOL IsInTable(LPTSTR ptszString, CSEntry** ppCSEntry = NULL); BOOL HashAdd(LPTSTR ptszString, CSEntry* pCSEntry = NULL); void HashDelete(LPTSTR ptszString);
private:
PBUCKET Table[NUM_OF_BUCKETS]; };
//
// The synchronization manager. This class synchronizes LoadUserProfile/
// UnloadUserProfile calls.
//
class CSyncManager { public: //
// Constructor.
//
CSyncManager() { pCSList = NULL; }
//
// Initializes the table, the list, and the critical section.
//
BOOL Initialize();
//
// Sync functions. These functions are protected by a critical section
// No two users can update their locks at the same time. This can be
// optimized but optimization requires a lot more code. This is also the
// only place where user's profile locks gets held and released.
//
BOOL EnterLock(LPTSTR pSid, LPTSTR lpRPCEndPoint, BYTE* pbCookie, DWORD cbCookie); BOOL LeaveLock(LPTSTR pSid);
HRESULT GetRPCEndPointAndCookie(LPTSTR pSid, LPTSTR* lplpEndPoint, BYTE** ppbCookie, DWORD* pcbCookie);
private:
CHashTable cTable; // All the user profile critical section's associated sids.
CSEntry* pCSList; CRITICAL_SECTION cs; };
//
// Mapping between profile work lists and threads. This is for the registry
// key leak fix.
//
class MAP { public:
MAP(); ~MAP() {}
friend class CUserProfile;
//
// Delete/insert a work item from/into the map.
//
void Delete(DWORD dwIndex); void Insert(HANDLE hEvent, LPTSTR ptszSid);
BOOL IsEmpty() { return dwItems <= 1; }
LPTSTR GetSid(DWORD dwIndex);
private:
MAP* pNext;
//
// These two arrays must always be in sync.
//
HANDLE rghEvents[MAXIMUM_WAIT_OBJECTS]; LPTSTR rgSids[MAXIMUM_WAIT_OBJECTS]; DWORD dwItems; };
typedef MAP* PMAP;
//
// The IUserProfile interface functions use this class api to do the core processing. User profiles are loaded
// unloaded through the api provided in this class. Console winlogon is the server and only one global instance
// of this class runs in console winlogon.
//
class CUserProfile { public:
//
// Constructor/Destructor.
//
CUserProfile() {bInitialized = FALSE; bConsoleWinlogon = FALSE; } ~CUserProfile() {};
//
// Initialization function.
//
void Initialize();
//
// Are we in console winlogon process?
//
BOOL IsConsoleWinlogon() { return bConsoleWinlogon; }
//
// Main function for the worker threads.
//
DWORD WorkerThreadMain(PMAP pmap);
//
// Make getting the user profile lock easier.
//
BOOL EnterUserProfileLockLocal(LPTSTR pSid); BOOL LeaveUserProfileLockLocal(LPTSTR pSid);
//
// The actual LoadUserProfile/UnloadUserProfile that does all the work.
//
BOOL LoadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, LPPROFILEINFO lpProfileInfo, LPTSTR lpRPCEndPoint, BYTE* pbCookie, DWORD cbCookie); BOOL UnloadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, HKEY hProfile, LPTSTR lpRPCEndPoint, BYTE* pbCookie, DWORD cbCookie);
//
// Get RPCEndPoint and security cookie associated with registered IProfileDialog interface
//
HRESULT GetRPCEndPointAndCookie(LPTSTR pSid, LPTSTR* lplpEndPoint, BYTE** ppbCookie, DWORD* pcbCookie);
private:
//
// Handles the situation when keys are leaked from the registry.
//
DWORD HandleRegKeyLeak(LPTSTR lpSidString, LPPROFILE lpProfile, BOOL bUnloadHiveSucceeded, DWORD* dwWatchHiveFlags, DWORD* dwCopyTmpHive, LPTSTR pTmpHiveFile, DWORD cchTmpHiveFile);
//
// This function is called when a registry key is leaked.
//
STDMETHODIMP WatchHiveRefCount(LPCTSTR pctszSid, DWORD dwWHRCFlags);
//
// Get the reference count.
//
long GetRefCountAndFlags(LPCTSTR ptszSid, HKEY* phkPL, DWORD* dwRefCount, DWORD* dwInternalFlags);
//
// Add a new work item to both the map structure and a worker thread.
//
HRESULT AddWorkItem(LPCTSTR ptszSid, HANDLE hEvent);
//
// Get the exisiting work item event from map structure
//
HANDLE GetWorkItem(LPCTSTR ptszSid);
//
// Delete the profile as well if necessary, i.e.,
// temporary profiles, guest profiles, and mandatory profiles.
//
void CleanupUserProfile(LPTSTR ptszSid, HKEY* phkProfileList);
//
// Reg leak fix structures. This hash table holds the sids of all the
// unloaded user registry hives.
//
CRITICAL_SECTION csMap; PMAP pMap; CHashTable cTable;
//
// LoadUserProfile/UnloadUserProfile synchronization manager.
//
CSyncManager cSyncMgr;
//
// Tells the caller if we are already initialized. Also tells us if we are
// in the console winlogon process because it's the only process that'll
// initialize this object.
//
BOOL bInitialized;
//
// Tells us if we are in console winlogon process
//
BOOL bConsoleWinlogon; };
//
// Functions prototype for binding rpc handle
//
BOOL GetInterface(handle_t *phIfHandle, LPTSTR lpRPCEndPoint); BOOL ReleaseInterface(handle_t *phIfHandle);
#endif
|