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.
 
 
 
 
 
 

2432 lines
59 KiB

/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
flbuilder.cpp
Abstract:
This class uses the CXMLFileListParser, CFLHashList and CFLPathTree
classses to take an a protected XML file and build a data file for the FL.
Author:
Kanwaljit Marok (kmarok) 01-May-2000
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include "srdefs.h"
//#include <windows.h>
//#include <windowsx.h>
//#include <stdlib.h>
//#include <stdio.h>
#include <io.h>
#include <tchar.h>
#ifdef _ASSERT
#undef _ASSERT
#endif
#include <commonlib.h>
#include <atlbase.h>
#include <msxml.h>
#include "xmlparser.h"
#include "flbuilder.h"
#include "flpathtree.h"
#include "flhashlist.h"
#include "commonlibh.h"
#include "datastormgr.h"
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
#define TRACE_FILEID 0
#define FILEID 0
#define SAFEDELETE(p) if (p) { HeapFree( m_hHeapToUse, 0, p); p = NULL;} else ;
//
// redefine a new max buf
//
#ifdef MAX_BUFFER
#undef MAX_BUFFER
#define MAX_BUFFER 1024
#endif
//
// Some Registry keys used to merge registry info into the blob.
//
static TCHAR s_cszUserHivePrefix[] = TEXT("\\REGISTRY\\USER\\");
static TCHAR s_cszUserHiveClassesSuffix[] = TEXT("_CLASSES");
static TCHAR s_cszTempUserProfileKey[] = TEXT("FILELIST0102");
static TCHAR s_cszProfileImagePath[] = TEXT("ProfileImagePath");
static TCHAR s_cszUserHiveDefault[] = TEXT(".DEFAULT");
static TCHAR s_cszUserProfileEnv [] = TEXT("USERPROFILE");
static TCHAR s_cszFilesNotToBackup[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup");
static TCHAR s_cszProfileList[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList");
static TCHAR s_cszUserShellFolderKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders");
static TCHAR s_cszWinLogonKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon");
static TCHAR s_cszSnapshotKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore\\FilesToSnapshot");
static INT s_nSnapShotEntries = 0;
static BOOL s_bSnapShotInit = FALSE;
//
// Some invalid patterns found in FilesNotToBackup Key.
//
TCHAR ArrInvalidPatterns[][64] = { TEXT("*."),
TEXT("%USERPROFILE%"),
TEXT("%TEMP%")
};
#define INVALID_PATTERNS 3
//
// CFLDatBuilder Implementation
//
CFLDatBuilder::CFLDatBuilder()
{
m_lNodeCount = m_lFileListCount = m_lNumFiles = m_lNumChars = 0;
m_pRoot = NULL;
m_chDefaultType = _TEXT('i');
if( ( m_hHeapToUse = HeapCreate( 0, 1048576 /* 1 meg */, 0 ) ) == NULL )
{
m_hHeapToUse = GetProcessHeap();
}
}
CFLDatBuilder::~CFLDatBuilder()
{
if( m_hHeapToUse != GetProcessHeap() )
{
HeapDestroy( m_hHeapToUse );
}
}
//
// CFLDatBuilder::DeleteList - free'd up a a linked list of
// FL_FILELIST structures and the attached strings.
//
BOOL
CFLDatBuilder::DeleteList(
LPFL_FILELIST pList
)
{
LPFL_FILELIST pListNext;
TraceFunctEnter("CFLDatBuilder::DeleteList");
while( pList )
{
if( pList->szFileName )
{
HeapFree( m_hHeapToUse, 0, pList->szFileName );
}
pListNext = pList->pNext;
HeapFree( m_hHeapToUse, 0, pList );
pList = pListNext;
}
TraceFunctLeave();
return TRUE;
}
//
// CFLDatBuilder::DeleteTree - Recurses through a FLTREE_NODE, deletes
// all the nods, allocated strings for path and file lists attached
// to the nodes.
//
BOOL
CFLDatBuilder::DeleteTree(
LPFLTREE_NODE pTree
)
{
TraceFunctEnter("CFLDatBuilder::DeleteTree");
if( pTree )
{
if( pTree->szPath )
{
HeapFree( m_hHeapToUse, 0, pTree->szPath );
}
if( pTree->pFileList )
{
DeleteList( pTree->pFileList );
}
//
// go depth first
//
if( pTree->pChild )
{
DeleteTree( pTree->pChild );
}
if( pTree->pSibling )
{
DeleteTree( pTree->pSibling );
}
HeapFree( m_hHeapToUse, 0, pTree );
}
TraceFunctLeave( );
return TRUE;
}
//
// CFLDatBuilder::CreateNode - Allocates space for a tree node and path
// string and copies szPath into the newly allocated path. It also
// sets the internal node parent pointer.
// ->Increments the global ( m_lNodeCount ) node count.
// ->Increments the global characters allocated ( m_lNumChars ) count
// (These counts are used to reserve space in the FLDAT file)
//
LPFLTREE_NODE
CFLDatBuilder::CreateNode(
LPTSTR szPath,
TCHAR chType,
LPFLTREE_NODE pParent,
BOOL fDisable)
{
LPFLTREE_NODE pNode=NULL;
LONG lPathLen;
TraceFunctEnter("CFLDatBuilder::CreateNode");
pNode = (LPFLTREE_NODE) HeapAlloc( m_hHeapToUse, 0, sizeof(FLTREE_NODE) );
if (pNode == NULL)
{
goto End;
}
memset( pNode, 0, sizeof( FLTREE_NODE ) );
lPathLen = _tcslen( szPath );
if ( (pNode->szPath = _MyStrDup( szPath ) ) == NULL)
{
HeapFree( m_hHeapToUse, 0, pNode);
pNode = NULL;
goto End;
}
pNode->chType = chType;
//
// give me a node number, used for indexing later.
//
pNode->lNodeNumber = m_lNodeCount++;
m_lNumChars += lPathLen;
//
// set the parent
//
if( pParent )
{
pNode->pParent = pParent;
}
//
// is this a protected directory
//
pNode->fDisableDirectory = fDisable;
End:
TraceFunctLeave();
return( pNode );
}
//
// CFLDatBuilder::CreateList - Allocates a file list entry.
//
LPFL_FILELIST
CFLDatBuilder::CreateList()
{
LPFL_FILELIST pList=NULL;
TraceFunctEnter("CFLDatBuilder::CreateList");
pList = (LPFL_FILELIST) HeapAlloc( m_hHeapToUse, 0, sizeof( FL_FILELIST) );
if ( pList )
{
memset( pList, 0, sizeof(LPFL_FILELIST) );
}
TraceFunctLeave();
return( pList );
}
//
// CFLDatBuidler::AddfileToList
// This method calls CreateList() and allocates a filelist node.
// It then allocates memoery for the file name and copies it over.
// It then links it into the pList file list.
//
// -> If *pList is null, it increments the number of file lists in system.
// This is important as most nodes don't have file lists and we shouldn't
// reserve space for them.
// -> Like CreateNode(), this functions also adds to the number of
// global allocated characters ( m_lNumChars )
// -> Increments the total number of files ( m_lFiles ), this number
// is used by the HASHLIST in order to see how m any physical entries
// to allocate.
// -> This functions also nodes to the nods own NumofCharacere and NumFiles
// counters. This is used to create it's own individual hash list.
//
BOOL
CFLDatBuilder::AddFileToList(
LPFLTREE_NODE pNode,
LPFL_FILELIST *pList,
LPTSTR szFile,
TCHAR chType)
{
LPFL_FILELIST pNewList=NULL;
LPTSTR pNewString=NULL;
LONG lFileNameLength;
TraceFunctEnter("CFLDatBuilder::AddFileToList");
_ASSERT(pList);
_ASSERT(szFile);
if( (pNewList = CreateList() ) == NULL)
{
ErrorTrace(FILEID, "Error allocating memory", 0);
goto cleanup;
}
lFileNameLength = _tcslen( szFile );
if( (pNewString = _MyStrDup( szFile ) ) == NULL )
{
ErrorTrace(FILEID,"Error allocating memory",0);
goto cleanup;
}
pNewList->szFileName = pNewString;
pNewList->chType = chType;
//
// this is a whole new list
//
if( *pList == NULL )
{
m_lFileListCount++;
}
m_lNumFiles++;
m_lNumChars += lFileNameLength;
pNode->lNumFilesHashed++;
pNode->lFileDataSize += lFileNameLength;
pNewList->pNext = *pList;
*pList = pNewList;
TraceFunctLeave();
return TRUE;
cleanup:
SAFEDELETE( pNewString );
SAFEDELETE( pNewList );
TraceFunctLeave();
return FALSE;
}
//
// CFLDatBuilder::AddTreeNode
// This method is the core of the FL tree building process.
// It takes a full path of a filename (or directory) and recurses down
// the tree. If one of the intermediary nodes required by end node
// (i.e a directory on the way to our final directory), it adds
// it to the tree with the default type. if another directory is added
// which explicitly references that directory, its type is changed to
// the explicit type.
//
// Files are a special case since they are linked lists off direcory nodes.
//
BOOL
CFLDatBuilder::AddTreeNode(
LPFLTREE_NODE *pParent,
LPTSTR szFullPath,
TCHAR chType,
LONG lNumElements,
LONG lLevel,
BOOL fFile,
BOOL fDisable)
{
TCHAR szBuf[MAX_PATH];
LPFLTREE_NODE pNodePointer, pTempNode, pNewNode;
BOOL fResult=FALSE;
TraceFunctEnter("CFLDatBuilder::AddTreeNode");
//
// we've hit the end of the recursion.
//
if( lLevel == lNumElements )
{
return(TRUE);
}
//
// make sure everything is null
//
pNodePointer = pTempNode = pNewNode = NULL;
//
// Get this element of the path structure
//
if( GetField( szFullPath, szBuf, lLevel, _TEXT('\\') ) == 0)
{
ErrorTrace(FILEID, "Error extracting path element.", 0 );
goto cleanup;
}
//
// We are adding a file!
//
if( (lLevel == (lNumElements - 1) ) && fFile )
{
if( AddFileToList( *pParent,
&(*pParent)->pFileList,
szBuf,
chType ) == FALSE )
{
ErrorTrace(FILEID, "Error adding a file to the filelist.", 0 );
goto cleanup;
}
TraceFunctLeave();
return(TRUE);
}
if( *pParent )
{
//
// lets see if i exist as sibling any where along the line.
//
if( lLevel == 0 )
{
//
// at level 0, we don't really have a parent->child relationship
// manually set the pointer
//
pNodePointer = *pParent;
}
else
{
//
// start searching for siblings
//
pNodePointer = (*pParent)->pChild;
}
for( ; pNodePointer != NULL; pNodePointer = pNodePointer->pSibling)
{
//
// okay, we've already hashed this entry !
//
if( _tcsicmp( pNodePointer->szPath, szBuf ) == 0 )
{
if( lLevel == (lNumElements-1) )
{
//
// In this case, we at the leaf node on this addition
// but it has been addded before implicitly
// as a default node. we need to change this type to
// our explicity type;
//
pNodePointer->chType = chType;
//
// brijeshk: we would have already created this
// node ONLY if this node is a DIRECTORY
// need to change the default protected attribute
// to specified value as well
//
pNodePointer->fDisableDirectory = fDisable;
fResult = TRUE;
}
else
{
fResult = AddTreeNode(
&pNodePointer,
szFullPath,
chType,
lNumElements,
lLevel + 1,
fFile,
fDisable );
}
TraceFunctLeave();
return( fResult );
}
pTempNode = pNodePointer;
}
}
if( (pNewNode = CreateNode(szBuf,
chType,
*pParent,
fDisable) ) == NULL)
{
ErrorTrace(FILEID, "Error allocating memory", 0);
goto cleanup;
}
//
// We are a node implicitly created on the chain, set it to
// the unknown type instead of the end node type.
//
if( lLevel != (lNumElements-1) )
{
pNewNode->chType = NODE_TYPE_UNKNOWN;
//
// brijeshk: if we are an implicitly created node, then we need
// to set the disable attribute to default (FALSE)
// otherwise, protecting the directory c:\A\B would also
// protect c:\ and A.
//
pNewNode->fDisableDirectory = FALSE;
}
//
// Are we the first root
//
if( *pParent == NULL )
{
*pParent = pNewNode;
}
else if( (*pParent)->pChild == NULL )
{
//
// We are the child off the root
//
(*pParent)->pChild = pNewNode;
}
else if( pTempNode )
{
//
// We are a sibling at this level, pTempNode is the last sibling
// in the list
// just tack pNewNode onto the end/
//
pTempNode->pSibling = pNewNode;
pNewNode->pSibling = NULL;
}
else
{
ErrorTrace(
FILEID,
"Uxpected error condition in AddTreeNode: no link determined",0);
goto cleanup;
}
//
// Parse the new level.
//
fResult = AddTreeNode(
&(pNewNode),
szFullPath,
chType,
lNumElements,
lLevel + 1,
fFile,
fDisable );
cleanup:
TraceFunctLeave();
return( fResult );
}
BOOL
CFLDatBuilder::AddRegistrySnapshotEntry(
LPTSTR pszPath)
{
HKEY hKey;
BOOL fRet = FALSE;
if ( s_bSnapShotInit == FALSE )
{
//
// Delete the snapshot key
//
RegDeleteKey( HKEY_LOCAL_MACHINE, s_cszSnapshotKey );
s_nSnapShotEntries = 0;
//
// Add the snapshot key
//
if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
s_cszSnapshotKey,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL) == ERROR_SUCCESS)
{
s_bSnapShotInit = TRUE;
RegCloseKey( hKey );
}
}
//
// Set the value in the key
//
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
s_cszSnapshotKey,
0,
KEY_READ|KEY_WRITE,
&hKey ) == ERROR_SUCCESS )
{
TCHAR szSnapshotName[ MAX_PATH ];
s_nSnapShotEntries++;
_stprintf(szSnapshotName, TEXT("snap#%d"), s_nSnapShotEntries);
RegSetValueEx( hKey,
szSnapshotName,
0,
REG_SZ,
(const BYTE * )pszPath,
(_tcslen(pszPath) + 1)*sizeof(TCHAR) );
RegCloseKey( hKey );
fRet = TRUE;
}
return fRet;
}
//
// CFLDatBuilder::AddMetaDriveFileDir -
//
BOOL CFLDatBuilder::AddMetaDriveFileDir(
LPTSTR szInPath,
TCHAR chType,
BOOL fFile,
BOOL fDisable )
{
BOOL fRet = FALSE;
TCHAR szFile[MAX_BUFFER];
TCHAR szOutFile[MAX_BUFFER];
LONG lNumTokens=0;
TraceFunctEnter("AddMetaDriveFileDir");
if (szInPath &&
szInPath[0]==TEXT('*'))
{
//
// if type is 's' make it exclude and add to the registry
// setting fro snapshotted files
//
if ( chType == TEXT('s') )
{
AddRegistrySnapshotEntry( szInPath );
chType = TEXT('e');
}
_tcscpy( szFile, szInPath );
#ifdef USE_NTDEVICENAMES
if(szFile[1] == TEXT(':') )
{
_stprintf(szOutFile,
_TEXT("NTROOT\\%s\\%s"),
ALLVOLUMES_PATH_T,
szFile+3);
CharUpper( szOutFile );
}
else
#endif
{
_stprintf(szOutFile,
_TEXT("NTROOT\\%s\\%s"),
ALLVOLUMES_PATH_T,
szFile );
}
lNumTokens = CountTokens( szOutFile, _TEXT('\\') );
if( AddTreeNode(
&m_pRoot,
szOutFile,
chType,
lNumTokens,
0,
fFile,
fDisable ) == FALSE )
{
ErrorTrace(FILEID,
"Error adding tree node in metadrive fileadd.",0);
goto cleanup;
}
fRet = TRUE;
}
cleanup:
TraceFunctLeave();
return fRet;
}
//
// CFLDatBuilder::VerifyVxdDat
//
BOOL
CFLDatBuilder::VerifyVxdDat(
LPCTSTR pszFile)
{
DWORD dwSize = 0;
HANDLE hFile=NULL;
TraceFunctEnter("VerifyVxdDat");
if( (hFile = CreateFile( pszFile,
GENERIC_READ,
0, // exclusive file accces
NULL, //security attributes
OPEN_EXISTING, // don't make it if it don't exist
FILE_FLAG_RANDOM_ACCESS,
NULL ) ) == NULL )
{
ErrorTrace(FILEID, "Error opening %s to verify FLDAT", pszFile );
goto cleanup;
}
dwSize = GetFileSize( hFile, NULL);
if( (dwSize == 0xFFFFFFFF) || (dwSize == 0) )
{
ErrorTrace(FILEID, "%s: 0 size file, unable to verify.", pszFile );
goto cleanup;
}
CloseHandle( hFile );
TraceFunctLeave();
return TRUE;
cleanup:
if( hFile )
{
CloseHandle( hFile );
}
TraceFunctLeave();
return FALSE;
}
//
// Merge FileNotToBackup information into the Dat File
//
BOOL
CFLDatBuilder::MergeSfcDllCacheInfo( )
{
BOOL fRet;
//
// Try to get the value from the key first
//
fRet = AddNodeForKeyValue( HKEY_LOCAL_MACHINE,
s_cszWinLogonKey,
TEXT("SfcDllCache") );
if ( fRet == FALSE )
{
TCHAR SfcPath[MAX_PATH + 1];
TCHAR SfcFullPath[MAX_PATH + 1];
LONG lNumTokens = 0;
_stprintf( SfcPath, TEXT("%%WINDIR%%\\system32\\dllcache"));
ExpandEnvironmentStrings( SfcPath,
SfcFullPath,
MAX_PATH );
SfcFullPath[MAX_PATH] = 0;
ConvertToInternalFormat( SfcFullPath, SfcPath );
SfcPath[MAX_PATH] = 0;
lNumTokens = CountTokens( SfcPath, _TEXT('\\') );
fRet = AddTreeNode(&m_pRoot,
SfcPath,
TEXT('e'),
lNumTokens,
0,
FALSE,
FALSE );
}
return fRet;
}
//
// Merge FileNotToBackup information into the Dat File
//
BOOL
CFLDatBuilder::MergeFilesNotToBackupInfo( )
{
TCHAR ValueName[ MAX_PATH+1 ];
TCHAR ValueData[ MAX_PATH+1 ];
DWORD ValueType = 0;
DWORD cbValueName = 0;
DWORD cbValueData = 0;
DWORD cbValueType = 0;
LONG lNumTokens = 0;
BOOL bExtension = FALSE, bRecursive = FALSE, bInvalidPattern = FALSE;
HKEY hKey;
PTCHAR ptr = NULL;
TraceFunctEnter("CFLDatBuilder::MergeFilesNotToBackupInfo");
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
s_cszFilesNotToBackup,
0,
KEY_READ,
&hKey ) == ERROR_SUCCESS )
{
DWORD dwIndex = 0;
while ( TRUE )
{
bExtension = FALSE;
bRecursive = FALSE;
bInvalidPattern = FALSE;
*ValueName = 0;
cbValueName = sizeof(ValueName)/sizeof(TCHAR);
*ValueData = 0;
cbValueData = sizeof(ValueData);
if ( RegEnumValue( hKey,
dwIndex,
ValueName,
&cbValueName,
0,
&ValueType,
(PBYTE)ValueData,
&cbValueData ) != ERROR_SUCCESS )
{
break;
}
// trace(0, "Opened Registry Key %S\n", ValueData);
//
// We are interested in only string types
//
if ( ValueType != REG_EXPAND_SZ &&
ValueType != REG_SZ &&
ValueType != REG_MULTI_SZ )
{
dwIndex++;
continue;
}
CharUpper( ValueData );
//
// Look for any invalid patterns in the value data
//
for (int i=0; i<INVALID_PATTERNS; i++)
{
if (_tcsstr( ValueData, ArrInvalidPatterns[i]) != NULL)
{
bInvalidPattern = TRUE;
}
}
if (bInvalidPattern)
{
dwIndex++;
continue;
}
//
// Check for recursive flag /s
//
if ( (ptr = _tcsstr( ValueData, TEXT("/S"))) != NULL )
{
*ptr = 0;
bRecursive = TRUE;
}
//
// trim any trailing spaces, tabs or "\\"
//
ptr = ValueData + _tcslen(ValueData) - 1;
while ( ptr > ValueData )
{
if ( *ptr == TEXT(' ') ||
*ptr == TEXT('\t') ||
*ptr == TEXT('\\') ||
*ptr == TEXT('*') )
{
*ptr = 0;
}
else
{
break;
}
ptr--;
}
//
// Check if the path has extensions also
//
#if 0
if ( _tcsrchr( ValueData, TEXT('.') ) != NULL )
{
bExtension = TRUE;
}
#else
ptr = ValueData + _tcslen(ValueData) - 1;
while ( ptr > ValueData )
{
if ( *ptr == TEXT('\\') )
{
break;
}
else if ( *ptr == TEXT('.') )
{
bExtension = TRUE;
break;
}
ptr--;
}
#endif
if ( ( bExtension && bRecursive ) ||
( !bExtension && !bRecursive) )
{
dwIndex++;
continue;
}
//
// Check if the path starts with a "\\"
//
if ( ValueData[0] == TEXT('\\') )
{
_stprintf( ValueName, TEXT("*:%s"), ValueData );
ExpandEnvironmentStrings( ValueName,
ValueData,
MAX_PATH );
if (_tcsstr( ValueData, TEXT("~")) != NULL )
{
LPTSTR pFilePart = NULL;
//
// Convert into full path
//
if (ExpandShortNames(ValueData,
sizeof(ValueData),
ValueName,
sizeof(ValueName)))
{
_tcscpy( ValueData, ValueName );
}
}
// trace(0, "Adding - %S\n\n", ValueData );
AddMetaDriveFileDir(
ValueData,
TEXT('e'),
bExtension,
FALSE);
}
else
{
TCHAR szDeviceName[ MAX_PATH ];
*szDeviceName=0;
_tcscpy( ValueName, ValueData );
ExpandEnvironmentStrings( ValueName,
ValueData,
MAX_PATH );
if (_tcsstr( ValueData, TEXT("~")) != NULL )
{
LPTSTR pFilePart = NULL;
//
// Convert into full path
//
if (ExpandShortNames(ValueData,
sizeof(ValueData),
ValueName,
sizeof(ValueName)))
{
_tcscpy( ValueData, ValueName );
}
}
ConvertToInternalFormat( ValueData, ValueName );
lNumTokens = CountTokens( ValueName, _TEXT('\\') );
// trace(0, "Adding - %S\n\n", ValueName );
AddTreeNode(
&m_pRoot,
ValueName,
TEXT('e'),
lNumTokens,
0,
bExtension,
FALSE );
}
dwIndex++;
}
RegCloseKey( hKey );
}
TraceFunctLeave();
return TRUE;
}
BOOL
CFLDatBuilder::AddNodeForKeyValue(
HKEY hKeyUser,
LPCTSTR pszSubKey,
LPCTSTR pszValue
)
{
BOOL fRet = FALSE;
HKEY hKeyEnv;
TCHAR szDeviceName[ MAX_PATH ];
TCHAR szBuf [ MAX_PATH ];
TCHAR szBuf2 [ MAX_PATH ];
DWORD cbBuf;
DWORD cbBuf2;
LONG lNumTokens=0;
DWORD Type, dwErr;
TraceFunctEnter("CFLDatBuilder::AddNodeForKeyValue");
dwErr = RegOpenKeyEx( hKeyUser,
pszSubKey,
0,
KEY_READ,
&hKeyEnv );
if ( dwErr == ERROR_SUCCESS )
{
//
// Read and add the value for TEMP from the user profile
//
cbBuf = sizeof( szBuf );
dwErr = RegQueryValueEx( hKeyEnv,
pszValue,
NULL,
&Type,
(PBYTE)szBuf,
&cbBuf );
RegCloseKey( hKeyEnv );
if ( dwErr != ERROR_SUCCESS )
{
trace( 0, "Cannot open :%S", pszValue );
goto Exit;
}
ExpandEnvironmentStrings ( szBuf,
szBuf2,
sizeof( szBuf2 ) / sizeof( TCHAR ) );
ConvertToInternalFormat ( szBuf2, szBuf );
lNumTokens = CountTokens( szBuf, _TEXT('\\') );
// trace(0, "Adding - %S\n\n", szBuf );
fRet = AddTreeNode( &m_pRoot,
szBuf,
TEXT('e'),
lNumTokens,
0,
FALSE,
FALSE );
}
Exit:
TraceFunctLeave();
return fRet;
}
BOOL
CFLDatBuilder::AddUserProfileInfo(
HKEY hKeyUser,
LPCTSTR pszUserProfile
)
{
HKEY hKeyEnv;
DWORD dwErr;
TCHAR OldUserProfileEnv[ MAX_PATH ];
LPTSTR pszOldUserProfileEnv = NULL;
TraceFunctEnter("CFLDatBuilder::AddUserProfileInfo");
//
// Save the current value of %UserProfile% in the env
//
*OldUserProfileEnv = 0;
if ( GetEnvironmentVariable( s_cszUserProfileEnv,
OldUserProfileEnv,
sizeof( OldUserProfileEnv )/sizeof(TCHAR))>0 )
{
pszOldUserProfileEnv = OldUserProfileEnv;
}
SetEnvironmentVariable( s_cszUserProfileEnv,
pszUserProfile );
AddNodeForKeyValue( hKeyUser,
TEXT("Environment"),
TEXT("TEMP") );
AddNodeForKeyValue( hKeyUser,
TEXT("Environment"),
TEXT("TMP") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("Favorites") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("Cache") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("Cookies") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("Personal") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("nethood") );
AddNodeForKeyValue( hKeyUser,
s_cszUserShellFolderKey,
TEXT("history") );
//
// Put back the user Profile Env variable
//
SetEnvironmentVariable ( s_cszUserProfileEnv,
pszOldUserProfileEnv );
TraceFunctLeave();
return TRUE;
}
//
// This funtion merges the drive table info into the Xml Blob
//
BOOL
CFLDatBuilder::MergeDriveTableInfo( )
{
BOOL fRet = FALSE;
TCHAR szSystemDrive[MAX_PATH];
TCHAR *szBuf2 = NULL;
LONG lNumTokens = 0;
TraceFunctEnter("CFLDatBuilder::MergeDriveTableInfo");
szBuf2 = new TCHAR[MAX_BUFFER+7];
if (! szBuf2)
{
ErrorTrace(0, "Cannot allocate memory for szBuf2");
goto cleanup;
}
//
// Enumerate the drive table information and merge it into
// the filelist
//
if (GetSystemDrive(szSystemDrive))
{
TCHAR szPath[MAX_PATH];
CDriveTable dt;
SDriveTableEnumContext dtec = {NULL, 0};
MakeRestorePath(szPath, szSystemDrive, s_cszDriveTable);
//
// remove terminating slash
//
if (szPath[_tcslen( szPath ) - 1] == _TEXT('\\'))
szPath[_tcslen( szPath ) - 1] = 0;
if (dt.LoadDriveTable(szPath) == ERROR_SUCCESS)
{
CDataStore *pds;
pds = dt.FindFirstDrive (dtec);
while (pds)
{
BOOLEAN bDisable = FALSE;
DWORD dwFlags = pds->GetFlags();
if ( !(dwFlags & SR_DRIVE_MONITORED) )
{
bDisable = TRUE;
}
if (dwFlags & SR_DRIVE_FROZEN)
{
bDisable = TRUE;
}
if ( bDisable )
{
//
// Enter this information into the tree
//
swprintf(szBuf2,_TEXT("NTROOT%s"), pds->GetNTName());
//
// remove terminating slash
//
if (szBuf2[_tcslen( szBuf2 ) - 1] == _TEXT('\\'))
szBuf2[_tcslen( szBuf2 ) - 1] = 0;
CharUpper (szBuf2);
lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
if( AddTreeNode(
&m_pRoot,
szBuf2,
NODE_TYPE_UNKNOWN,
lNumTokens,
0,
FALSE,
bDisable ) == FALSE )
{
ErrorTrace(FILEID, "Error adding node.",0);
goto cleanup;
}
}
pds = dt.FindNextDrive (dtec);
}
}
fRet = TRUE;
}
cleanup:
if (szBuf2)
delete [] szBuf2;
TraceFunctLeave();
return fRet;
}
//
// This function merges per user information either from HKEY_USER or from
// the user hive on the disk
//
BOOL
CFLDatBuilder::MergeUserRegistryInfo(
LPCTSTR pszUserProfilePath,
LPCTSTR pszUserProfileHive,
LPCTSTR pszUserSid
)
{
BOOL fRet = TRUE;
HKEY hKeyUser;
DWORD dwErr;
TraceFunctEnter("CFLDatBuilder::MergeUserRegistryInfo");
// trace(0, "UserProfilePath: %S", pszUserProfilePath );
// trace(0, "UserProfileHive: %S", pszUserProfileHive );
//
// Try to open the user specific key from HKEY_USER
//
dwErr = RegOpenKeyEx( HKEY_USERS,
pszUserSid,
0,
KEY_READ,
&hKeyUser);
if ( dwErr == ERROR_SUCCESS )
{
//
// Succeeded : copy the setting from this key
//
AddUserProfileInfo( hKeyUser, pszUserProfilePath );
RegCloseKey( hKeyUser );
}
else
{
//
// Failed : Now load the hive for this user
//
dwErr = RegLoadKey( HKEY_LOCAL_MACHINE,
s_cszTempUserProfileKey,
pszUserProfileHive );
if ( dwErr == ERROR_SUCCESS )
{
// trace(0, "Loaded Hive : %S", pszUserProfileHive );
//
// Open temporary key where the hive was loaded
//
dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
s_cszTempUserProfileKey,
0,
KEY_READ,
&hKeyUser);
if ( dwErr == ERROR_SUCCESS )
{
AddUserProfileInfo( hKeyUser, pszUserProfilePath );
RegCloseKey( hKeyUser );
}
//
// Unload the hive from the temp key
//
RegUnLoadKey( HKEY_LOCAL_MACHINE,
s_cszTempUserProfileKey );
}
}
fRet = TRUE;
TraceFunctLeave();
return fRet;
}
//
// This function enumerats all the available user profiles and calls
// MergeUserRegistryInfo for each user.
//
BOOL
CFLDatBuilder::MergeAllUserRegistryInfo( )
{
BOOL fRet = FALSE;
TCHAR UserSid[ MAX_PATH ];
DWORD ValueType = 0;
DWORD cbUserSid = 0;
DWORD cbValueType = 0;
HKEY hKey;
PTCHAR ptr = NULL;
FILETIME ft;
DWORD dwErr;
TraceFunctEnter("CFLDatBuilder::MergeAllUserRegistryInfo");
dwErr = SetPrivilegeInAccessToken(SE_RESTORE_NAME);
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
s_cszProfileList,
0,
KEY_READ,
&hKey ) == ERROR_SUCCESS )
{
DWORD dwIndex = 0;
//
// Enumerate and get the Sids for each user.
//
while ( TRUE )
{
*UserSid = 0;
cbUserSid = sizeof(UserSid)/sizeof(TCHAR);
if ( RegEnumKeyEx( hKey,
dwIndex,
UserSid,
&cbUserSid,
0,
NULL,
0,
&ft ) != ERROR_SUCCESS )
{
break;
}
CharUpper( UserSid );
//
// Look for intersting values
//
if (cbUserSid > 0)
{
DWORD dwErr;
HKEY hKeyUser, hKeyEnv, hKeyProfileList;
TCHAR UserProfilePath[MAX_PATH];
TCHAR UserProfileHive[MAX_PATH];
DWORD cbUserProfilePath = 0;
// trace(0,"UserSid = %S", UserSid);
dwErr = RegOpenKeyEx( hKey,
UserSid,
0,
KEY_READ,
&hKeyProfileList );
if ( dwErr == ERROR_SUCCESS )
{
DWORD Type;
cbUserProfilePath = sizeof( UserProfilePath );
dwErr = RegQueryValueEx( hKeyProfileList,
s_cszProfileImagePath,
NULL,
&Type,
(PBYTE)UserProfilePath,
&cbUserProfilePath );
RegCloseKey( hKeyProfileList );
if ( dwErr != ERROR_SUCCESS )
{
trace(0, "Query ProfileImagePath failed: %d", dwErr );
dwIndex++;
continue;
}
}
else
{
trace(0, "Opening UserSid failed: %d", dwErr );
dwIndex++;
continue;
}
//
// Create NTUSER.Dat path from the user profile path
//
ExpandEnvironmentStrings( UserProfilePath,
UserProfileHive,
sizeof(UserProfileHive) /
sizeof(TCHAR) );
_tcscpy( UserProfilePath, UserProfileHive );
_tcscat( UserProfileHive, TEXT("\\NTUSER.DAT") );
MergeUserRegistryInfo( UserProfilePath,
UserProfileHive,
UserSid );
}
dwIndex++;
}
fRet = TRUE;
RegCloseKey( hKey );
}
else
{
trace( 0, "Failed to open %S", s_cszProfileList );
}
TraceFunctLeave();
return fRet;
}
//
// CFLDatBuilder::BuildTree
// This methods takes an XML file (the PCHealth Protected file)
// and outsputs a FLDAT file ( pszOutFile ).
// It basically just opens up the xml, iterates through
// all the files and then adds them to the tree. It then
// creates blobs based on the data gathered and then sends the
// tree to the CFLPathTree blob class which transforms the tree
// into the contigious blob format. It then writes it out.
//
// -> The method of actually passing the FLDAT file has not be defined,
// this function just demonstrates the process.
//
//
BOOL
CFLDatBuilder::BuildTree(
LPCTSTR pszFile,
LPCTSTR pszOutFile)
{
TCHAR *szBuf = NULL;
TCHAR *szBuf2 = NULL;
TCHAR chType;
LONG lLoop,lMax,lNumTokens;
BOOL fRet = FALSE;
s_bSnapShotInit = FALSE;
//
// ext list blob
//
CFLHashList ExtListBlob( m_hHeapToUse );
LONG lNumChars, lNumExt, lNumExtTotal;
//
// config blob
//
BlobHeader ConfigBlob;
//
// CFLPathTree blob
//
CFLPathTree PathTreeBlob( m_hHeapToUse );
//
// outfile
//
HANDLE hOutFile=NULL;
DWORD dwWritten;
//
// array opf all the file types, Include, Exclude, SNAPSHOT
//
TCHAR achType[3] = { _TEXT('i'), _TEXT('e'), _TEXT('s') };
LONG lTypeLoop;
//
// numeric counterpart of m_chDefaultType;
//
DWORD dwDefaultType;
//
// should we protect this directory
//
BOOL fDisable = FALSE;
TraceFunctEnter("CFLDatBuilder::BuildTree");
if( m_pRoot )
{
DeleteTree( m_pRoot );
m_pRoot = NULL;
}
if(m_XMLParser.Init(pszFile) == FALSE)
{
ErrorTrace(FILEID,
"There was an error parsing the protected XML file.",0);
goto cleanup;
}
szBuf = new TCHAR[MAX_BUFFER];
szBuf2 = new TCHAR[MAX_BUFFER+7];
if (! szBuf || ! szBuf2)
{
ErrorTrace(0, "Cannot allocate memory");
goto cleanup;
}
//
// Calculate the tree default type info
//
m_chDefaultType = m_XMLParser.GetDefaultType();
if( m_chDefaultType == _TEXT('I') )
dwDefaultType = NODE_TYPE_INCLUDE;
else if( m_chDefaultType == _TEXT('E') )
dwDefaultType = NODE_TYPE_EXCLUDE;
else
dwDefaultType = NODE_TYPE_UNKNOWN;
//
// Loop through the directory/files for each file type (include, exclude )
//
for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
{
//
// Find directories for the type
//
lMax = m_XMLParser.GetDirectoryCount( achType[lTypeLoop] );
for(lLoop = 0;lLoop < lMax;lLoop++)
{
fDisable = FALSE;
if( m_XMLParser.GetDirectory(
lLoop,
szBuf,
MAX_BUFFER,
achType[lTypeLoop],
&fDisable) != MAX_BUFFER )
{
ErrorTrace(FILEID, "Not enough buffer space.",0);
goto cleanup;
}
if( szBuf[0] == _TEXT('*') )
{
if( AddMetaDriveFileDir(
szBuf,
achType[lTypeLoop],
FALSE,
fDisable) == FALSE )
{
ErrorTrace(FILEID, "error adding meta drive directory.",0);
goto cleanup;
}
}
else
{
TCHAR szDeviceName[ MAX_PATH ];
*szDeviceName=0;
// ankor all nods at Root.. so tree actually looks
// like Root\C:\Windows etc
ConvertToInternalFormat( szBuf, szBuf2 );
lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
if( AddTreeNode(
&m_pRoot,
szBuf2,
achType[lTypeLoop],
lNumTokens,
0,
FALSE,
fDisable ) == FALSE )
{
ErrorTrace(FILEID, "Error adding node.",0);
goto cleanup;
}
}
}
//
// Find files for the type
//
lMax = m_XMLParser.GetFileCount( achType[lTypeLoop] );
for(lLoop = 0;lLoop < lMax;lLoop++)
{
if( m_XMLParser.GetFile(lLoop,
szBuf,
MAX_BUFFER,
achType[lTypeLoop] ) != MAX_BUFFER )
{
ErrorTrace(FILEID, "Not enough buffer space.",0);
goto cleanup;
}
if( szBuf[0] == _TEXT('*') )
{
if( AddMetaDriveFileDir( szBuf,
achType[lTypeLoop],
TRUE, FALSE ) == FALSE )
{
ErrorTrace(FILEID, "error adding meta drive file.",0);
goto cleanup;
}
}
else
{
int iType = lTypeLoop;
//
// if type is 's' make it exclude and add to the registry
// setting fro snapshotted files
//
if ( achType[lTypeLoop] == TEXT('s') )
{
AddRegistrySnapshotEntry( szBuf );
iType = 1; // exclude
}
//
// Ankor all nods at Root.. so tree actually looks like
// Root\C:\Windows etc
//
ConvertToInternalFormat( szBuf, szBuf2 );
lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
if( AddTreeNode(
&m_pRoot,
szBuf2,
achType[iType],
lNumTokens,
0,
TRUE,
FALSE ) == FALSE )
{
ErrorTrace(FILEID, "Error adding node.",0);
goto cleanup;
}
}
}
}
//
// Merge information from the drivetable in to the blob
//
if ( MergeDriveTableInfo() == FALSE )
{
ErrorTrace(FILEID, "Error merging drive table info.",0);
goto cleanup;
}
//
// Merge Information under FilesNotToBackup key in to the blob ...
//
if ( MergeFilesNotToBackupInfo() == FALSE )
{
ErrorTrace(FILEID, "Error merging FilesNotToBackup Info.",0);
goto cleanup;
}
//
// Merge Per user information from the registry / user hives
//
if ( MergeAllUserRegistryInfo() == FALSE )
{
ErrorTrace(FILEID, "Error merging user registry info.",0);
goto cleanup;
}
#if 0
//
// Commented out: We monitor sfc cache ...
// Merge information for sfcdllcache
//
if ( MergeSfcDllCacheInfo() == FALSE )
{
ErrorTrace(FILEID, "Error merging SfcDllCache info.",0);
goto cleanup;
}
#endif
//
// Build the path tree based on our tree and the data we collected
// about it ( filecounts, nodecounts, # chars, etc)
//
if( PathTreeBlob.BuildTree(
m_pRoot,
m_lNodeCount,
dwDefaultType,
m_lFileListCount,
m_lNumFiles,
CalculateNumberOfHashBuckets( m_pRoot ),
m_lNumChars) == FALSE )
{
ErrorTrace(FILEID, "Error buildign pathtree blob.",0);
goto cleanup;
}
//
// Okay, now build a ext list hash blob
//
lNumChars = 0;
lNumExtTotal = 0;
for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
{
lNumExt = m_XMLParser.GetExtCount( achType[ lTypeLoop ] );
lNumExtTotal += lNumExt;
for(lLoop = 0;lLoop < lNumExt ;lLoop++)
{
if( m_XMLParser.GetExt(
lLoop,
szBuf,
MAX_BUFFER,
achType[ lTypeLoop ] ) != MAX_BUFFER )
{
ErrorTrace(FILEID, "Not enough buffer space.",0);
goto cleanup;
}
lNumChars += _tcslen( szBuf );
}
}
ExtListBlob.Init( lNumExtTotal, lNumChars );
for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
{
lNumExt = m_XMLParser.GetExtCount( achType[ lTypeLoop ] );
for(lLoop = 0;lLoop < lNumExt; lLoop++)
{
m_XMLParser.GetExt(lLoop, szBuf, MAX_BUFFER, achType[ lTypeLoop ] );
ExtListBlob.AddFile( szBuf, achType[lTypeLoop] );
}
}
//
// now we have both blobs, lets write to disk
//
if( (hOutFile = CreateFile( pszOutFile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // security attributes
OPEN_ALWAYS,
FILE_FLAG_RANDOM_ACCESS,
NULL) // template file
) == INVALID_HANDLE_VALUE)
{
ErrorTrace( FILEID, "CreateFile Failed 0x%x", GetLastError());
goto cleanup;
}
//
// Prepare the header blob
//
ConfigBlob.m_dwMaxSize = sizeof(BlobHeader) +
PathTreeBlob.GetSize() +
ExtListBlob.GetSize();
ConfigBlob.m_dwVersion = BLOB_VERSION_NUM;
ConfigBlob.m_dwMagicNum = BLOB_MAGIC_NUM ;
ConfigBlob.m_dwBlbType = BLOB_TYPE_CONTAINER;
ConfigBlob.m_dwEntries = 2;
if ( WriteFile(hOutFile,
&ConfigBlob,
sizeof(BlobHeader),
&dwWritten, NULL) == 0)
{
ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
goto cleanup;
}
if ( WriteFile(hOutFile,
PathTreeBlob.GetBasePointer(),
PathTreeBlob.GetSize(),
&dwWritten, NULL) == 0)
{
ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
goto cleanup;
}
if ( WriteFile(hOutFile,
ExtListBlob.GetBasePointer(),
ExtListBlob.GetSize(),
&dwWritten, NULL) == 0)
{
ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
goto cleanup;
}
fRet = TRUE;
cleanup:
if (szBuf)
delete [] szBuf;
if (szBuf2)
delete [] szBuf2;
if( hOutFile )
{
CloseHandle( hOutFile );
}
ExtListBlob.CleanUpMemory();
PathTreeBlob.CleanUpMemory();
if( m_pRoot )
{
DeleteTree(m_pRoot);
m_pRoot = NULL;
}
TraceFunctLeave();
return(fRet);
}
//
// CFLDatBuilder::CountTokens
// CountTokens(LPTSTR szStr, TCHAR chDelim)
// Counts the number of tokens seperated by (chDelim) in a string.
//
LONG
CFLDatBuilder::CountTokens(
LPTSTR szStr,
TCHAR chDelim)
{
LONG lNumTokens=1;
TraceFunctEnter("CFLDatBuilder::CountTokens");
_ASSERT( szStr );
if( *szStr == 0 )
{
TraceFunctLeave();
return(0);
}
while( *szStr != 0 )
{
if( *szStr == chDelim )
{
lNumTokens++;
}
szStr = _tcsinc( szStr );
}
TraceFunctLeave();
return(lNumTokens);
}
//
// CFLDatBuilder::_MyStrDup( LPTSTR szIn )
// Same as _tcsdup or strdup but it does it our own local
// heap space.
//
LPTSTR
CFLDatBuilder::_MyStrDup(
LPTSTR szIn )
{
LONG lLen;
LPTSTR pszOut=NULL;
if( szIn )
{
lLen = _tcslen( szIn );
pszOut = (LPTSTR) HeapAlloc( m_hHeapToUse,
0,
(sizeof(TCHAR) * (lLen+1)) );
if( pszOut )
{
_tcscpy( pszOut, szIn );
}
}
return( pszOut );
}
//
// CFLDatBuilder::CalculateNumberOfHashBuckets
// Calculates the number of hash buckets needed by the dynamic hashes
// in the hashlist.
//
LONG
CFLDatBuilder::CalculateNumberOfHashBuckets(
LPFLTREE_NODE pRoot )
{
LONG lNumNeeded=0;
if( pRoot )
{
if( pRoot->pChild )
{
lNumNeeded += CalculateNumberOfHashBuckets( pRoot->pChild );
}
if( pRoot->pSibling )
{
lNumNeeded += CalculateNumberOfHashBuckets( pRoot->pSibling );
}
if( pRoot->lNumFilesHashed > 0 )
{
lNumNeeded += GetNextHighestPrime( pRoot->lNumFilesHashed );
}
}
return( lNumNeeded );
}
//
// Debugging Methods
//
//
// CFLDatBuilder::PrintList
//
void
CFLDatBuilder::PrintList(
LPFL_FILELIST pList,
LONG lLevel)
{
LONG lCount;
if( !pList )
{
return;
}
for(lCount = 0;lCount < lLevel;lCount++)
{
printf(" ");
}
printf(" f: %s\n", pList->szFileName );
PrintList(pList->pNext, lLevel );
}
void
CFLDatBuilder::PrintTree(
LPFLTREE_NODE pTree,
LONG lLevel)
{
LONG lCount;
if( pTree )
{
for(lCount = 0;lCount < lLevel;lCount++)
{
printf(" ");
}
printf("%s", pTree->szPath);
if( pTree->pFileList )
{
printf(" (%d) \n", pTree->lNumFilesHashed);
}
else
{
printf("\n");
}
PrintList( pTree->pFileList, lLevel );
PrintTree( pTree->pChild, lLevel + 1 );
PrintTree( pTree->pSibling, lLevel );
}
return;
}
//
// CFLDatBuilder::IsPrime
//
BOOL
CFLDatBuilder::IsPrime(
LONG lNumber)
{
LONG cl;
//
// prevent divide by 0 problems
//
if( lNumber == 0 )
{
return FALSE;
}
if( lNumber == 1 )
{
return TRUE;
}
for(cl = 2;cl < lNumber;cl++)
{
if( (lNumber % cl ) == 0 )
{
return FALSE;
}
}
return TRUE;
}
//
// CFLDatBuilder::GetNextHighestPrime
//
LONG
CFLDatBuilder::GetNextHighestPrime(
LONG lNumber )
{
LONG clLoop;
if( lNumber >= LARGEST_HASH_SIZE )
{
return( LARGEST_HASH_SIZE );
}
for( clLoop = lNumber; clLoop < LARGEST_HASH_SIZE;clLoop++)
{
if( IsPrime( clLoop ) )
{
return( clLoop );
}
}
// nothing found, return large hash size.
return( LARGEST_HASH_SIZE );
}
//
// Some C helper API ( should be removed ?? )
//
DWORD
HeapUsed(
HANDLE hHeap )
{
PROCESS_HEAP_ENTRY HeapEntry;
DWORD dwAllocSize=0;
HeapEntry.lpData = NULL;
while( HeapWalk( hHeap, &HeapEntry) != FALSE )
{
if( HeapEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY )
dwAllocSize += HeapEntry.cbData;
}
return( dwAllocSize );
}
//
// Convert to internal NT namespace format + additional formatiing for
// required to Add the tree node.
//
BOOL
CFLDatBuilder::ConvertToInternalFormat(
LPTSTR szFrom,
LPTSTR szTo
)
{
BOOL fRet = FALSE;
#ifdef USE_NTDEVICENAMES
if(szFrom[1] == TEXT(':') )
{
TCHAR szDeviceName[MAX_PATH];
szFrom[2] = 0;
QueryDosDevice( szFrom, szDeviceName, sizeof(szDeviceName) );
_stprintf(szTo,
_TEXT("NTROOT%s\\%s"),
szDeviceName,
szFrom+3 );
//
// remove terminating slash
//
if (szTo[_tcslen( szTo ) - 1] == _TEXT('\\'))
szTo[_tcslen( szTo ) - 1] = 0;
CharUpper( szTo );
}
else
#endif
{
_stprintf(szTo,_TEXT("NTROOT\\%s"), szFrom);
}
fRet = TRUE;
return fRet;
}
//
// Adjust the process privileges so that we can load other user's hives.
//
DWORD
CFLDatBuilder::SetPrivilegeInAccessToken(
LPCTSTR pszPrivilegeName
)
{
TraceFunctEnter("CSnapshot::SetPrivilegeInAccessToken");
HANDLE hProcess;
HANDLE hAccessToken=NULL;
LUID luidPrivilegeLUID;
TOKEN_PRIVILEGES tpTokenPrivilege;
DWORD dwReturn = ERROR_INTERNAL_ERROR, dwErr;
hProcess = GetCurrentProcess();
if (!hProcess)
{
dwReturn = GetLastError();
trace(0, "GetCurrentProcess failed ec=%d", dwReturn);
goto done;
}
if (!OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hAccessToken))
{
dwErr=GetLastError();
trace(0, "OpenProcessToken failed ec=%d", dwErr);
if (ERROR_SUCCESS != dwErr)
{
dwReturn = dwErr;
}
goto done;
}
if (!LookupPrivilegeValue(NULL,
pszPrivilegeName,
&luidPrivilegeLUID))
{
dwErr=GetLastError();
trace(0, "LookupPrivilegeValue failed ec=%d",dwErr);
if (ERROR_SUCCESS != dwErr)
{
dwReturn = dwErr;
}
goto done;
}
tpTokenPrivilege.PrivilegeCount = 1;
tpTokenPrivilege.Privileges[0].Luid = luidPrivilegeLUID;
tpTokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hAccessToken,
FALSE, // Do not disable all
&tpTokenPrivilege,
sizeof(TOKEN_PRIVILEGES),
NULL, // Ignore previous info
NULL)) // Ignore previous info
{
dwErr=GetLastError();
trace(0, "AdjustTokenPrivileges");
if (dwErr != NO_ERROR)
{
dwReturn = dwErr;
}
goto done;
}
dwReturn = ERROR_SUCCESS;
done:
if (hAccessToken != NULL)
{
CloseHandle(hAccessToken);
}
TraceFunctLeave();
return dwReturn;
}