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.
 
 
 
 
 
 

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