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.
373 lines
8.3 KiB
373 lines
8.3 KiB
//*************************************************************
|
|
//
|
|
// 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
|