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

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. flbuilder.cpp
  5. Abstract:
  6. This class uses the CXMLFileListParser, CFLHashList and CFLPathTree
  7. classses to take an a protected XML file and build a data file for the FL.
  8. Author:
  9. Kanwaljit Marok (kmarok) 01-May-2000
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include "srdefs.h"
  18. //#include <windows.h>
  19. //#include <windowsx.h>
  20. //#include <stdlib.h>
  21. //#include <stdio.h>
  22. #include <io.h>
  23. #include <tchar.h>
  24. #ifdef _ASSERT
  25. #undef _ASSERT
  26. #endif
  27. #include <commonlib.h>
  28. #include <atlbase.h>
  29. #include <msxml.h>
  30. #include "xmlparser.h"
  31. #include "flbuilder.h"
  32. #include "flpathtree.h"
  33. #include "flhashlist.h"
  34. #include "commonlibh.h"
  35. #include "datastormgr.h"
  36. #ifdef THIS_FILE
  37. #undef THIS_FILE
  38. #endif
  39. static char __szTraceSourceFile[] = __FILE__;
  40. #define THIS_FILE __szTraceSourceFile
  41. #define TRACE_FILEID 0
  42. #define FILEID 0
  43. #define SAFEDELETE(p) if (p) { HeapFree( m_hHeapToUse, 0, p); p = NULL;} else ;
  44. //
  45. // redefine a new max buf
  46. //
  47. #ifdef MAX_BUFFER
  48. #undef MAX_BUFFER
  49. #define MAX_BUFFER 1024
  50. #endif
  51. //
  52. // Some Registry keys used to merge registry info into the blob.
  53. //
  54. static TCHAR s_cszUserHivePrefix[] = TEXT("\\REGISTRY\\USER\\");
  55. static TCHAR s_cszUserHiveClassesSuffix[] = TEXT("_CLASSES");
  56. static TCHAR s_cszTempUserProfileKey[] = TEXT("FILELIST0102");
  57. static TCHAR s_cszProfileImagePath[] = TEXT("ProfileImagePath");
  58. static TCHAR s_cszUserHiveDefault[] = TEXT(".DEFAULT");
  59. static TCHAR s_cszUserProfileEnv [] = TEXT("USERPROFILE");
  60. static TCHAR s_cszFilesNotToBackup[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup");
  61. static TCHAR s_cszProfileList[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList");
  62. static TCHAR s_cszUserShellFolderKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders");
  63. static TCHAR s_cszWinLogonKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon");
  64. static TCHAR s_cszSnapshotKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore\\FilesToSnapshot");
  65. static INT s_nSnapShotEntries = 0;
  66. static BOOL s_bSnapShotInit = FALSE;
  67. //
  68. // Some invalid patterns found in FilesNotToBackup Key.
  69. //
  70. TCHAR ArrInvalidPatterns[][64] = { TEXT("*."),
  71. TEXT("%USERPROFILE%"),
  72. TEXT("%TEMP%")
  73. };
  74. #define INVALID_PATTERNS 3
  75. //
  76. // CFLDatBuilder Implementation
  77. //
  78. CFLDatBuilder::CFLDatBuilder()
  79. {
  80. m_lNodeCount = m_lFileListCount = m_lNumFiles = m_lNumChars = 0;
  81. m_pRoot = NULL;
  82. m_chDefaultType = _TEXT('i');
  83. if( ( m_hHeapToUse = HeapCreate( 0, 1048576 /* 1 meg */, 0 ) ) == NULL )
  84. {
  85. m_hHeapToUse = GetProcessHeap();
  86. }
  87. }
  88. CFLDatBuilder::~CFLDatBuilder()
  89. {
  90. if( m_hHeapToUse != GetProcessHeap() )
  91. {
  92. HeapDestroy( m_hHeapToUse );
  93. }
  94. }
  95. //
  96. // CFLDatBuilder::DeleteList - free'd up a a linked list of
  97. // FL_FILELIST structures and the attached strings.
  98. //
  99. BOOL
  100. CFLDatBuilder::DeleteList(
  101. LPFL_FILELIST pList
  102. )
  103. {
  104. LPFL_FILELIST pListNext;
  105. TraceFunctEnter("CFLDatBuilder::DeleteList");
  106. while( pList )
  107. {
  108. if( pList->szFileName )
  109. {
  110. HeapFree( m_hHeapToUse, 0, pList->szFileName );
  111. }
  112. pListNext = pList->pNext;
  113. HeapFree( m_hHeapToUse, 0, pList );
  114. pList = pListNext;
  115. }
  116. TraceFunctLeave();
  117. return TRUE;
  118. }
  119. //
  120. // CFLDatBuilder::DeleteTree - Recurses through a FLTREE_NODE, deletes
  121. // all the nods, allocated strings for path and file lists attached
  122. // to the nodes.
  123. //
  124. BOOL
  125. CFLDatBuilder::DeleteTree(
  126. LPFLTREE_NODE pTree
  127. )
  128. {
  129. TraceFunctEnter("CFLDatBuilder::DeleteTree");
  130. if( pTree )
  131. {
  132. if( pTree->szPath )
  133. {
  134. HeapFree( m_hHeapToUse, 0, pTree->szPath );
  135. }
  136. if( pTree->pFileList )
  137. {
  138. DeleteList( pTree->pFileList );
  139. }
  140. //
  141. // go depth first
  142. //
  143. if( pTree->pChild )
  144. {
  145. DeleteTree( pTree->pChild );
  146. }
  147. if( pTree->pSibling )
  148. {
  149. DeleteTree( pTree->pSibling );
  150. }
  151. HeapFree( m_hHeapToUse, 0, pTree );
  152. }
  153. TraceFunctLeave( );
  154. return TRUE;
  155. }
  156. //
  157. // CFLDatBuilder::CreateNode - Allocates space for a tree node and path
  158. // string and copies szPath into the newly allocated path. It also
  159. // sets the internal node parent pointer.
  160. // ->Increments the global ( m_lNodeCount ) node count.
  161. // ->Increments the global characters allocated ( m_lNumChars ) count
  162. // (These counts are used to reserve space in the FLDAT file)
  163. //
  164. LPFLTREE_NODE
  165. CFLDatBuilder::CreateNode(
  166. LPTSTR szPath,
  167. TCHAR chType,
  168. LPFLTREE_NODE pParent,
  169. BOOL fDisable)
  170. {
  171. LPFLTREE_NODE pNode=NULL;
  172. LONG lPathLen;
  173. TraceFunctEnter("CFLDatBuilder::CreateNode");
  174. pNode = (LPFLTREE_NODE) HeapAlloc( m_hHeapToUse, 0, sizeof(FLTREE_NODE) );
  175. if (pNode == NULL)
  176. {
  177. goto End;
  178. }
  179. memset( pNode, 0, sizeof( FLTREE_NODE ) );
  180. lPathLen = _tcslen( szPath );
  181. if ( (pNode->szPath = _MyStrDup( szPath ) ) == NULL)
  182. {
  183. HeapFree( m_hHeapToUse, 0, pNode);
  184. pNode = NULL;
  185. goto End;
  186. }
  187. pNode->chType = chType;
  188. //
  189. // give me a node number, used for indexing later.
  190. //
  191. pNode->lNodeNumber = m_lNodeCount++;
  192. m_lNumChars += lPathLen;
  193. //
  194. // set the parent
  195. //
  196. if( pParent )
  197. {
  198. pNode->pParent = pParent;
  199. }
  200. //
  201. // is this a protected directory
  202. //
  203. pNode->fDisableDirectory = fDisable;
  204. End:
  205. TraceFunctLeave();
  206. return( pNode );
  207. }
  208. //
  209. // CFLDatBuilder::CreateList - Allocates a file list entry.
  210. //
  211. LPFL_FILELIST
  212. CFLDatBuilder::CreateList()
  213. {
  214. LPFL_FILELIST pList=NULL;
  215. TraceFunctEnter("CFLDatBuilder::CreateList");
  216. pList = (LPFL_FILELIST) HeapAlloc( m_hHeapToUse, 0, sizeof( FL_FILELIST) );
  217. if ( pList )
  218. {
  219. memset( pList, 0, sizeof(LPFL_FILELIST) );
  220. }
  221. TraceFunctLeave();
  222. return( pList );
  223. }
  224. //
  225. // CFLDatBuidler::AddfileToList
  226. // This method calls CreateList() and allocates a filelist node.
  227. // It then allocates memoery for the file name and copies it over.
  228. // It then links it into the pList file list.
  229. //
  230. // -> If *pList is null, it increments the number of file lists in system.
  231. // This is important as most nodes don't have file lists and we shouldn't
  232. // reserve space for them.
  233. // -> Like CreateNode(), this functions also adds to the number of
  234. // global allocated characters ( m_lNumChars )
  235. // -> Increments the total number of files ( m_lFiles ), this number
  236. // is used by the HASHLIST in order to see how m any physical entries
  237. // to allocate.
  238. // -> This functions also nodes to the nods own NumofCharacere and NumFiles
  239. // counters. This is used to create it's own individual hash list.
  240. //
  241. BOOL
  242. CFLDatBuilder::AddFileToList(
  243. LPFLTREE_NODE pNode,
  244. LPFL_FILELIST *pList,
  245. LPTSTR szFile,
  246. TCHAR chType)
  247. {
  248. LPFL_FILELIST pNewList=NULL;
  249. LPTSTR pNewString=NULL;
  250. LONG lFileNameLength;
  251. TraceFunctEnter("CFLDatBuilder::AddFileToList");
  252. _ASSERT(pList);
  253. _ASSERT(szFile);
  254. if( (pNewList = CreateList() ) == NULL)
  255. {
  256. ErrorTrace(FILEID, "Error allocating memory", 0);
  257. goto cleanup;
  258. }
  259. lFileNameLength = _tcslen( szFile );
  260. if( (pNewString = _MyStrDup( szFile ) ) == NULL )
  261. {
  262. ErrorTrace(FILEID,"Error allocating memory",0);
  263. goto cleanup;
  264. }
  265. pNewList->szFileName = pNewString;
  266. pNewList->chType = chType;
  267. //
  268. // this is a whole new list
  269. //
  270. if( *pList == NULL )
  271. {
  272. m_lFileListCount++;
  273. }
  274. m_lNumFiles++;
  275. m_lNumChars += lFileNameLength;
  276. pNode->lNumFilesHashed++;
  277. pNode->lFileDataSize += lFileNameLength;
  278. pNewList->pNext = *pList;
  279. *pList = pNewList;
  280. TraceFunctLeave();
  281. return TRUE;
  282. cleanup:
  283. SAFEDELETE( pNewString );
  284. SAFEDELETE( pNewList );
  285. TraceFunctLeave();
  286. return FALSE;
  287. }
  288. //
  289. // CFLDatBuilder::AddTreeNode
  290. // This method is the core of the FL tree building process.
  291. // It takes a full path of a filename (or directory) and recurses down
  292. // the tree. If one of the intermediary nodes required by end node
  293. // (i.e a directory on the way to our final directory), it adds
  294. // it to the tree with the default type. if another directory is added
  295. // which explicitly references that directory, its type is changed to
  296. // the explicit type.
  297. //
  298. // Files are a special case since they are linked lists off direcory nodes.
  299. //
  300. BOOL
  301. CFLDatBuilder::AddTreeNode(
  302. LPFLTREE_NODE *pParent,
  303. LPTSTR szFullPath,
  304. TCHAR chType,
  305. LONG lNumElements,
  306. LONG lLevel,
  307. BOOL fFile,
  308. BOOL fDisable)
  309. {
  310. TCHAR szBuf[MAX_PATH];
  311. LPFLTREE_NODE pNodePointer, pTempNode, pNewNode;
  312. BOOL fResult=FALSE;
  313. TraceFunctEnter("CFLDatBuilder::AddTreeNode");
  314. //
  315. // we've hit the end of the recursion.
  316. //
  317. if( lLevel == lNumElements )
  318. {
  319. return(TRUE);
  320. }
  321. //
  322. // make sure everything is null
  323. //
  324. pNodePointer = pTempNode = pNewNode = NULL;
  325. //
  326. // Get this element of the path structure
  327. //
  328. if( GetField( szFullPath, szBuf, lLevel, _TEXT('\\') ) == 0)
  329. {
  330. ErrorTrace(FILEID, "Error extracting path element.", 0 );
  331. goto cleanup;
  332. }
  333. //
  334. // We are adding a file!
  335. //
  336. if( (lLevel == (lNumElements - 1) ) && fFile )
  337. {
  338. if( AddFileToList( *pParent,
  339. &(*pParent)->pFileList,
  340. szBuf,
  341. chType ) == FALSE )
  342. {
  343. ErrorTrace(FILEID, "Error adding a file to the filelist.", 0 );
  344. goto cleanup;
  345. }
  346. TraceFunctLeave();
  347. return(TRUE);
  348. }
  349. if( *pParent )
  350. {
  351. //
  352. // lets see if i exist as sibling any where along the line.
  353. //
  354. if( lLevel == 0 )
  355. {
  356. //
  357. // at level 0, we don't really have a parent->child relationship
  358. // manually set the pointer
  359. //
  360. pNodePointer = *pParent;
  361. }
  362. else
  363. {
  364. //
  365. // start searching for siblings
  366. //
  367. pNodePointer = (*pParent)->pChild;
  368. }
  369. for( ; pNodePointer != NULL; pNodePointer = pNodePointer->pSibling)
  370. {
  371. //
  372. // okay, we've already hashed this entry !
  373. //
  374. if( _tcsicmp( pNodePointer->szPath, szBuf ) == 0 )
  375. {
  376. if( lLevel == (lNumElements-1) )
  377. {
  378. //
  379. // In this case, we at the leaf node on this addition
  380. // but it has been addded before implicitly
  381. // as a default node. we need to change this type to
  382. // our explicity type;
  383. //
  384. pNodePointer->chType = chType;
  385. //
  386. // brijeshk: we would have already created this
  387. // node ONLY if this node is a DIRECTORY
  388. // need to change the default protected attribute
  389. // to specified value as well
  390. //
  391. pNodePointer->fDisableDirectory = fDisable;
  392. fResult = TRUE;
  393. }
  394. else
  395. {
  396. fResult = AddTreeNode(
  397. &pNodePointer,
  398. szFullPath,
  399. chType,
  400. lNumElements,
  401. lLevel + 1,
  402. fFile,
  403. fDisable );
  404. }
  405. TraceFunctLeave();
  406. return( fResult );
  407. }
  408. pTempNode = pNodePointer;
  409. }
  410. }
  411. if( (pNewNode = CreateNode(szBuf,
  412. chType,
  413. *pParent,
  414. fDisable) ) == NULL)
  415. {
  416. ErrorTrace(FILEID, "Error allocating memory", 0);
  417. goto cleanup;
  418. }
  419. //
  420. // We are a node implicitly created on the chain, set it to
  421. // the unknown type instead of the end node type.
  422. //
  423. if( lLevel != (lNumElements-1) )
  424. {
  425. pNewNode->chType = NODE_TYPE_UNKNOWN;
  426. //
  427. // brijeshk: if we are an implicitly created node, then we need
  428. // to set the disable attribute to default (FALSE)
  429. // otherwise, protecting the directory c:\A\B would also
  430. // protect c:\ and A.
  431. //
  432. pNewNode->fDisableDirectory = FALSE;
  433. }
  434. //
  435. // Are we the first root
  436. //
  437. if( *pParent == NULL )
  438. {
  439. *pParent = pNewNode;
  440. }
  441. else if( (*pParent)->pChild == NULL )
  442. {
  443. //
  444. // We are the child off the root
  445. //
  446. (*pParent)->pChild = pNewNode;
  447. }
  448. else if( pTempNode )
  449. {
  450. //
  451. // We are a sibling at this level, pTempNode is the last sibling
  452. // in the list
  453. // just tack pNewNode onto the end/
  454. //
  455. pTempNode->pSibling = pNewNode;
  456. pNewNode->pSibling = NULL;
  457. }
  458. else
  459. {
  460. ErrorTrace(
  461. FILEID,
  462. "Uxpected error condition in AddTreeNode: no link determined",0);
  463. goto cleanup;
  464. }
  465. //
  466. // Parse the new level.
  467. //
  468. fResult = AddTreeNode(
  469. &(pNewNode),
  470. szFullPath,
  471. chType,
  472. lNumElements,
  473. lLevel + 1,
  474. fFile,
  475. fDisable );
  476. cleanup:
  477. TraceFunctLeave();
  478. return( fResult );
  479. }
  480. BOOL
  481. CFLDatBuilder::AddRegistrySnapshotEntry(
  482. LPTSTR pszPath)
  483. {
  484. HKEY hKey;
  485. BOOL fRet = FALSE;
  486. if ( s_bSnapShotInit == FALSE )
  487. {
  488. //
  489. // Delete the snapshot key
  490. //
  491. RegDeleteKey( HKEY_LOCAL_MACHINE, s_cszSnapshotKey );
  492. s_nSnapShotEntries = 0;
  493. //
  494. // Add the snapshot key
  495. //
  496. if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  497. s_cszSnapshotKey,
  498. 0,
  499. TEXT(""),
  500. REG_OPTION_NON_VOLATILE,
  501. KEY_ALL_ACCESS,
  502. NULL,
  503. &hKey,
  504. NULL) == ERROR_SUCCESS)
  505. {
  506. s_bSnapShotInit = TRUE;
  507. RegCloseKey( hKey );
  508. }
  509. }
  510. //
  511. // Set the value in the key
  512. //
  513. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  514. s_cszSnapshotKey,
  515. 0,
  516. KEY_READ|KEY_WRITE,
  517. &hKey ) == ERROR_SUCCESS )
  518. {
  519. TCHAR szSnapshotName[ MAX_PATH ];
  520. s_nSnapShotEntries++;
  521. _stprintf(szSnapshotName, TEXT("snap#%d"), s_nSnapShotEntries);
  522. RegSetValueEx( hKey,
  523. szSnapshotName,
  524. 0,
  525. REG_SZ,
  526. (const BYTE * )pszPath,
  527. (_tcslen(pszPath) + 1)*sizeof(TCHAR) );
  528. RegCloseKey( hKey );
  529. fRet = TRUE;
  530. }
  531. return fRet;
  532. }
  533. //
  534. // CFLDatBuilder::AddMetaDriveFileDir -
  535. //
  536. BOOL CFLDatBuilder::AddMetaDriveFileDir(
  537. LPTSTR szInPath,
  538. TCHAR chType,
  539. BOOL fFile,
  540. BOOL fDisable )
  541. {
  542. BOOL fRet = FALSE;
  543. TCHAR szFile[MAX_BUFFER];
  544. TCHAR szOutFile[MAX_BUFFER];
  545. LONG lNumTokens=0;
  546. TraceFunctEnter("AddMetaDriveFileDir");
  547. if (szInPath &&
  548. szInPath[0]==TEXT('*'))
  549. {
  550. //
  551. // if type is 's' make it exclude and add to the registry
  552. // setting fro snapshotted files
  553. //
  554. if ( chType == TEXT('s') )
  555. {
  556. AddRegistrySnapshotEntry( szInPath );
  557. chType = TEXT('e');
  558. }
  559. _tcscpy( szFile, szInPath );
  560. #ifdef USE_NTDEVICENAMES
  561. if(szFile[1] == TEXT(':') )
  562. {
  563. _stprintf(szOutFile,
  564. _TEXT("NTROOT\\%s\\%s"),
  565. ALLVOLUMES_PATH_T,
  566. szFile+3);
  567. CharUpper( szOutFile );
  568. }
  569. else
  570. #endif
  571. {
  572. _stprintf(szOutFile,
  573. _TEXT("NTROOT\\%s\\%s"),
  574. ALLVOLUMES_PATH_T,
  575. szFile );
  576. }
  577. lNumTokens = CountTokens( szOutFile, _TEXT('\\') );
  578. if( AddTreeNode(
  579. &m_pRoot,
  580. szOutFile,
  581. chType,
  582. lNumTokens,
  583. 0,
  584. fFile,
  585. fDisable ) == FALSE )
  586. {
  587. ErrorTrace(FILEID,
  588. "Error adding tree node in metadrive fileadd.",0);
  589. goto cleanup;
  590. }
  591. fRet = TRUE;
  592. }
  593. cleanup:
  594. TraceFunctLeave();
  595. return fRet;
  596. }
  597. //
  598. // CFLDatBuilder::VerifyVxdDat
  599. //
  600. BOOL
  601. CFLDatBuilder::VerifyVxdDat(
  602. LPCTSTR pszFile)
  603. {
  604. DWORD dwSize = 0;
  605. HANDLE hFile=NULL;
  606. TraceFunctEnter("VerifyVxdDat");
  607. if( (hFile = CreateFile( pszFile,
  608. GENERIC_READ,
  609. 0, // exclusive file accces
  610. NULL, //security attributes
  611. OPEN_EXISTING, // don't make it if it don't exist
  612. FILE_FLAG_RANDOM_ACCESS,
  613. NULL ) ) == NULL )
  614. {
  615. ErrorTrace(FILEID, "Error opening %s to verify FLDAT", pszFile );
  616. goto cleanup;
  617. }
  618. dwSize = GetFileSize( hFile, NULL);
  619. if( (dwSize == 0xFFFFFFFF) || (dwSize == 0) )
  620. {
  621. ErrorTrace(FILEID, "%s: 0 size file, unable to verify.", pszFile );
  622. goto cleanup;
  623. }
  624. CloseHandle( hFile );
  625. TraceFunctLeave();
  626. return TRUE;
  627. cleanup:
  628. if( hFile )
  629. {
  630. CloseHandle( hFile );
  631. }
  632. TraceFunctLeave();
  633. return FALSE;
  634. }
  635. //
  636. // Merge FileNotToBackup information into the Dat File
  637. //
  638. BOOL
  639. CFLDatBuilder::MergeSfcDllCacheInfo( )
  640. {
  641. BOOL fRet;
  642. //
  643. // Try to get the value from the key first
  644. //
  645. fRet = AddNodeForKeyValue( HKEY_LOCAL_MACHINE,
  646. s_cszWinLogonKey,
  647. TEXT("SfcDllCache") );
  648. if ( fRet == FALSE )
  649. {
  650. TCHAR SfcPath[MAX_PATH + 1];
  651. TCHAR SfcFullPath[MAX_PATH + 1];
  652. LONG lNumTokens = 0;
  653. _stprintf( SfcPath, TEXT("%%WINDIR%%\\system32\\dllcache"));
  654. ExpandEnvironmentStrings( SfcPath,
  655. SfcFullPath,
  656. MAX_PATH );
  657. SfcFullPath[MAX_PATH] = 0;
  658. ConvertToInternalFormat( SfcFullPath, SfcPath );
  659. SfcPath[MAX_PATH] = 0;
  660. lNumTokens = CountTokens( SfcPath, _TEXT('\\') );
  661. fRet = AddTreeNode(&m_pRoot,
  662. SfcPath,
  663. TEXT('e'),
  664. lNumTokens,
  665. 0,
  666. FALSE,
  667. FALSE );
  668. }
  669. return fRet;
  670. }
  671. //
  672. // Merge FileNotToBackup information into the Dat File
  673. //
  674. BOOL
  675. CFLDatBuilder::MergeFilesNotToBackupInfo( )
  676. {
  677. TCHAR ValueName[ MAX_PATH+1 ];
  678. TCHAR ValueData[ MAX_PATH+1 ];
  679. DWORD ValueType = 0;
  680. DWORD cbValueName = 0;
  681. DWORD cbValueData = 0;
  682. DWORD cbValueType = 0;
  683. LONG lNumTokens = 0;
  684. BOOL bExtension = FALSE, bRecursive = FALSE, bInvalidPattern = FALSE;
  685. HKEY hKey;
  686. PTCHAR ptr = NULL;
  687. TraceFunctEnter("CFLDatBuilder::MergeFilesNotToBackupInfo");
  688. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  689. s_cszFilesNotToBackup,
  690. 0,
  691. KEY_READ,
  692. &hKey ) == ERROR_SUCCESS )
  693. {
  694. DWORD dwIndex = 0;
  695. while ( TRUE )
  696. {
  697. bExtension = FALSE;
  698. bRecursive = FALSE;
  699. bInvalidPattern = FALSE;
  700. *ValueName = 0;
  701. cbValueName = sizeof(ValueName)/sizeof(TCHAR);
  702. *ValueData = 0;
  703. cbValueData = sizeof(ValueData);
  704. if ( RegEnumValue( hKey,
  705. dwIndex,
  706. ValueName,
  707. &cbValueName,
  708. 0,
  709. &ValueType,
  710. (PBYTE)ValueData,
  711. &cbValueData ) != ERROR_SUCCESS )
  712. {
  713. break;
  714. }
  715. // trace(0, "Opened Registry Key %S\n", ValueData);
  716. //
  717. // We are interested in only string types
  718. //
  719. if ( ValueType != REG_EXPAND_SZ &&
  720. ValueType != REG_SZ &&
  721. ValueType != REG_MULTI_SZ )
  722. {
  723. dwIndex++;
  724. continue;
  725. }
  726. CharUpper( ValueData );
  727. //
  728. // Look for any invalid patterns in the value data
  729. //
  730. for (int i=0; i<INVALID_PATTERNS; i++)
  731. {
  732. if (_tcsstr( ValueData, ArrInvalidPatterns[i]) != NULL)
  733. {
  734. bInvalidPattern = TRUE;
  735. }
  736. }
  737. if (bInvalidPattern)
  738. {
  739. dwIndex++;
  740. continue;
  741. }
  742. //
  743. // Check for recursive flag /s
  744. //
  745. if ( (ptr = _tcsstr( ValueData, TEXT("/S"))) != NULL )
  746. {
  747. *ptr = 0;
  748. bRecursive = TRUE;
  749. }
  750. //
  751. // trim any trailing spaces, tabs or "\\"
  752. //
  753. ptr = ValueData + _tcslen(ValueData) - 1;
  754. while ( ptr > ValueData )
  755. {
  756. if ( *ptr == TEXT(' ') ||
  757. *ptr == TEXT('\t') ||
  758. *ptr == TEXT('\\') ||
  759. *ptr == TEXT('*') )
  760. {
  761. *ptr = 0;
  762. }
  763. else
  764. {
  765. break;
  766. }
  767. ptr--;
  768. }
  769. //
  770. // Check if the path has extensions also
  771. //
  772. #if 0
  773. if ( _tcsrchr( ValueData, TEXT('.') ) != NULL )
  774. {
  775. bExtension = TRUE;
  776. }
  777. #else
  778. ptr = ValueData + _tcslen(ValueData) - 1;
  779. while ( ptr > ValueData )
  780. {
  781. if ( *ptr == TEXT('\\') )
  782. {
  783. break;
  784. }
  785. else if ( *ptr == TEXT('.') )
  786. {
  787. bExtension = TRUE;
  788. break;
  789. }
  790. ptr--;
  791. }
  792. #endif
  793. if ( ( bExtension && bRecursive ) ||
  794. ( !bExtension && !bRecursive) )
  795. {
  796. dwIndex++;
  797. continue;
  798. }
  799. //
  800. // Check if the path starts with a "\\"
  801. //
  802. if ( ValueData[0] == TEXT('\\') )
  803. {
  804. _stprintf( ValueName, TEXT("*:%s"), ValueData );
  805. ExpandEnvironmentStrings( ValueName,
  806. ValueData,
  807. MAX_PATH );
  808. if (_tcsstr( ValueData, TEXT("~")) != NULL )
  809. {
  810. LPTSTR pFilePart = NULL;
  811. //
  812. // Convert into full path
  813. //
  814. if (ExpandShortNames(ValueData,
  815. sizeof(ValueData),
  816. ValueName,
  817. sizeof(ValueName)))
  818. {
  819. _tcscpy( ValueData, ValueName );
  820. }
  821. }
  822. // trace(0, "Adding - %S\n\n", ValueData );
  823. AddMetaDriveFileDir(
  824. ValueData,
  825. TEXT('e'),
  826. bExtension,
  827. FALSE);
  828. }
  829. else
  830. {
  831. TCHAR szDeviceName[ MAX_PATH ];
  832. *szDeviceName=0;
  833. _tcscpy( ValueName, ValueData );
  834. ExpandEnvironmentStrings( ValueName,
  835. ValueData,
  836. MAX_PATH );
  837. if (_tcsstr( ValueData, TEXT("~")) != NULL )
  838. {
  839. LPTSTR pFilePart = NULL;
  840. //
  841. // Convert into full path
  842. //
  843. if (ExpandShortNames(ValueData,
  844. sizeof(ValueData),
  845. ValueName,
  846. sizeof(ValueName)))
  847. {
  848. _tcscpy( ValueData, ValueName );
  849. }
  850. }
  851. ConvertToInternalFormat( ValueData, ValueName );
  852. lNumTokens = CountTokens( ValueName, _TEXT('\\') );
  853. // trace(0, "Adding - %S\n\n", ValueName );
  854. AddTreeNode(
  855. &m_pRoot,
  856. ValueName,
  857. TEXT('e'),
  858. lNumTokens,
  859. 0,
  860. bExtension,
  861. FALSE );
  862. }
  863. dwIndex++;
  864. }
  865. RegCloseKey( hKey );
  866. }
  867. TraceFunctLeave();
  868. return TRUE;
  869. }
  870. BOOL
  871. CFLDatBuilder::AddNodeForKeyValue(
  872. HKEY hKeyUser,
  873. LPCTSTR pszSubKey,
  874. LPCTSTR pszValue
  875. )
  876. {
  877. BOOL fRet = FALSE;
  878. HKEY hKeyEnv;
  879. TCHAR szDeviceName[ MAX_PATH ];
  880. TCHAR szBuf [ MAX_PATH ];
  881. TCHAR szBuf2 [ MAX_PATH ];
  882. DWORD cbBuf;
  883. DWORD cbBuf2;
  884. LONG lNumTokens=0;
  885. DWORD Type, dwErr;
  886. TraceFunctEnter("CFLDatBuilder::AddNodeForKeyValue");
  887. dwErr = RegOpenKeyEx( hKeyUser,
  888. pszSubKey,
  889. 0,
  890. KEY_READ,
  891. &hKeyEnv );
  892. if ( dwErr == ERROR_SUCCESS )
  893. {
  894. //
  895. // Read and add the value for TEMP from the user profile
  896. //
  897. cbBuf = sizeof( szBuf );
  898. dwErr = RegQueryValueEx( hKeyEnv,
  899. pszValue,
  900. NULL,
  901. &Type,
  902. (PBYTE)szBuf,
  903. &cbBuf );
  904. RegCloseKey( hKeyEnv );
  905. if ( dwErr != ERROR_SUCCESS )
  906. {
  907. trace( 0, "Cannot open :%S", pszValue );
  908. goto Exit;
  909. }
  910. ExpandEnvironmentStrings ( szBuf,
  911. szBuf2,
  912. sizeof( szBuf2 ) / sizeof( TCHAR ) );
  913. ConvertToInternalFormat ( szBuf2, szBuf );
  914. lNumTokens = CountTokens( szBuf, _TEXT('\\') );
  915. // trace(0, "Adding - %S\n\n", szBuf );
  916. fRet = AddTreeNode( &m_pRoot,
  917. szBuf,
  918. TEXT('e'),
  919. lNumTokens,
  920. 0,
  921. FALSE,
  922. FALSE );
  923. }
  924. Exit:
  925. TraceFunctLeave();
  926. return fRet;
  927. }
  928. BOOL
  929. CFLDatBuilder::AddUserProfileInfo(
  930. HKEY hKeyUser,
  931. LPCTSTR pszUserProfile
  932. )
  933. {
  934. HKEY hKeyEnv;
  935. DWORD dwErr;
  936. TCHAR OldUserProfileEnv[ MAX_PATH ];
  937. LPTSTR pszOldUserProfileEnv = NULL;
  938. TraceFunctEnter("CFLDatBuilder::AddUserProfileInfo");
  939. //
  940. // Save the current value of %UserProfile% in the env
  941. //
  942. *OldUserProfileEnv = 0;
  943. if ( GetEnvironmentVariable( s_cszUserProfileEnv,
  944. OldUserProfileEnv,
  945. sizeof( OldUserProfileEnv )/sizeof(TCHAR))>0 )
  946. {
  947. pszOldUserProfileEnv = OldUserProfileEnv;
  948. }
  949. SetEnvironmentVariable( s_cszUserProfileEnv,
  950. pszUserProfile );
  951. AddNodeForKeyValue( hKeyUser,
  952. TEXT("Environment"),
  953. TEXT("TEMP") );
  954. AddNodeForKeyValue( hKeyUser,
  955. TEXT("Environment"),
  956. TEXT("TMP") );
  957. AddNodeForKeyValue( hKeyUser,
  958. s_cszUserShellFolderKey,
  959. TEXT("Favorites") );
  960. AddNodeForKeyValue( hKeyUser,
  961. s_cszUserShellFolderKey,
  962. TEXT("Cache") );
  963. AddNodeForKeyValue( hKeyUser,
  964. s_cszUserShellFolderKey,
  965. TEXT("Cookies") );
  966. AddNodeForKeyValue( hKeyUser,
  967. s_cszUserShellFolderKey,
  968. TEXT("Personal") );
  969. AddNodeForKeyValue( hKeyUser,
  970. s_cszUserShellFolderKey,
  971. TEXT("nethood") );
  972. AddNodeForKeyValue( hKeyUser,
  973. s_cszUserShellFolderKey,
  974. TEXT("history") );
  975. //
  976. // Put back the user Profile Env variable
  977. //
  978. SetEnvironmentVariable ( s_cszUserProfileEnv,
  979. pszOldUserProfileEnv );
  980. TraceFunctLeave();
  981. return TRUE;
  982. }
  983. //
  984. // This funtion merges the drive table info into the Xml Blob
  985. //
  986. BOOL
  987. CFLDatBuilder::MergeDriveTableInfo( )
  988. {
  989. BOOL fRet = FALSE;
  990. TCHAR szSystemDrive[MAX_PATH];
  991. TCHAR *szBuf2 = NULL;
  992. LONG lNumTokens = 0;
  993. TraceFunctEnter("CFLDatBuilder::MergeDriveTableInfo");
  994. szBuf2 = new TCHAR[MAX_BUFFER+7];
  995. if (! szBuf2)
  996. {
  997. ErrorTrace(0, "Cannot allocate memory for szBuf2");
  998. goto cleanup;
  999. }
  1000. //
  1001. // Enumerate the drive table information and merge it into
  1002. // the filelist
  1003. //
  1004. if (GetSystemDrive(szSystemDrive))
  1005. {
  1006. TCHAR szPath[MAX_PATH];
  1007. CDriveTable dt;
  1008. SDriveTableEnumContext dtec = {NULL, 0};
  1009. MakeRestorePath(szPath, szSystemDrive, s_cszDriveTable);
  1010. //
  1011. // remove terminating slash
  1012. //
  1013. if (szPath[_tcslen( szPath ) - 1] == _TEXT('\\'))
  1014. szPath[_tcslen( szPath ) - 1] = 0;
  1015. if (dt.LoadDriveTable(szPath) == ERROR_SUCCESS)
  1016. {
  1017. CDataStore *pds;
  1018. pds = dt.FindFirstDrive (dtec);
  1019. while (pds)
  1020. {
  1021. BOOLEAN bDisable = FALSE;
  1022. DWORD dwFlags = pds->GetFlags();
  1023. if ( !(dwFlags & SR_DRIVE_MONITORED) )
  1024. {
  1025. bDisable = TRUE;
  1026. }
  1027. if (dwFlags & SR_DRIVE_FROZEN)
  1028. {
  1029. bDisable = TRUE;
  1030. }
  1031. if ( bDisable )
  1032. {
  1033. //
  1034. // Enter this information into the tree
  1035. //
  1036. swprintf(szBuf2,_TEXT("NTROOT%s"), pds->GetNTName());
  1037. //
  1038. // remove terminating slash
  1039. //
  1040. if (szBuf2[_tcslen( szBuf2 ) - 1] == _TEXT('\\'))
  1041. szBuf2[_tcslen( szBuf2 ) - 1] = 0;
  1042. CharUpper (szBuf2);
  1043. lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
  1044. if( AddTreeNode(
  1045. &m_pRoot,
  1046. szBuf2,
  1047. NODE_TYPE_UNKNOWN,
  1048. lNumTokens,
  1049. 0,
  1050. FALSE,
  1051. bDisable ) == FALSE )
  1052. {
  1053. ErrorTrace(FILEID, "Error adding node.",0);
  1054. goto cleanup;
  1055. }
  1056. }
  1057. pds = dt.FindNextDrive (dtec);
  1058. }
  1059. }
  1060. fRet = TRUE;
  1061. }
  1062. cleanup:
  1063. if (szBuf2)
  1064. delete [] szBuf2;
  1065. TraceFunctLeave();
  1066. return fRet;
  1067. }
  1068. //
  1069. // This function merges per user information either from HKEY_USER or from
  1070. // the user hive on the disk
  1071. //
  1072. BOOL
  1073. CFLDatBuilder::MergeUserRegistryInfo(
  1074. LPCTSTR pszUserProfilePath,
  1075. LPCTSTR pszUserProfileHive,
  1076. LPCTSTR pszUserSid
  1077. )
  1078. {
  1079. BOOL fRet = TRUE;
  1080. HKEY hKeyUser;
  1081. DWORD dwErr;
  1082. TraceFunctEnter("CFLDatBuilder::MergeUserRegistryInfo");
  1083. // trace(0, "UserProfilePath: %S", pszUserProfilePath );
  1084. // trace(0, "UserProfileHive: %S", pszUserProfileHive );
  1085. //
  1086. // Try to open the user specific key from HKEY_USER
  1087. //
  1088. dwErr = RegOpenKeyEx( HKEY_USERS,
  1089. pszUserSid,
  1090. 0,
  1091. KEY_READ,
  1092. &hKeyUser);
  1093. if ( dwErr == ERROR_SUCCESS )
  1094. {
  1095. //
  1096. // Succeeded : copy the setting from this key
  1097. //
  1098. AddUserProfileInfo( hKeyUser, pszUserProfilePath );
  1099. RegCloseKey( hKeyUser );
  1100. }
  1101. else
  1102. {
  1103. //
  1104. // Failed : Now load the hive for this user
  1105. //
  1106. dwErr = RegLoadKey( HKEY_LOCAL_MACHINE,
  1107. s_cszTempUserProfileKey,
  1108. pszUserProfileHive );
  1109. if ( dwErr == ERROR_SUCCESS )
  1110. {
  1111. // trace(0, "Loaded Hive : %S", pszUserProfileHive );
  1112. //
  1113. // Open temporary key where the hive was loaded
  1114. //
  1115. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1116. s_cszTempUserProfileKey,
  1117. 0,
  1118. KEY_READ,
  1119. &hKeyUser);
  1120. if ( dwErr == ERROR_SUCCESS )
  1121. {
  1122. AddUserProfileInfo( hKeyUser, pszUserProfilePath );
  1123. RegCloseKey( hKeyUser );
  1124. }
  1125. //
  1126. // Unload the hive from the temp key
  1127. //
  1128. RegUnLoadKey( HKEY_LOCAL_MACHINE,
  1129. s_cszTempUserProfileKey );
  1130. }
  1131. }
  1132. fRet = TRUE;
  1133. TraceFunctLeave();
  1134. return fRet;
  1135. }
  1136. //
  1137. // This function enumerats all the available user profiles and calls
  1138. // MergeUserRegistryInfo for each user.
  1139. //
  1140. BOOL
  1141. CFLDatBuilder::MergeAllUserRegistryInfo( )
  1142. {
  1143. BOOL fRet = FALSE;
  1144. TCHAR UserSid[ MAX_PATH ];
  1145. DWORD ValueType = 0;
  1146. DWORD cbUserSid = 0;
  1147. DWORD cbValueType = 0;
  1148. HKEY hKey;
  1149. PTCHAR ptr = NULL;
  1150. FILETIME ft;
  1151. DWORD dwErr;
  1152. TraceFunctEnter("CFLDatBuilder::MergeAllUserRegistryInfo");
  1153. dwErr = SetPrivilegeInAccessToken(SE_RESTORE_NAME);
  1154. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1155. s_cszProfileList,
  1156. 0,
  1157. KEY_READ,
  1158. &hKey ) == ERROR_SUCCESS )
  1159. {
  1160. DWORD dwIndex = 0;
  1161. //
  1162. // Enumerate and get the Sids for each user.
  1163. //
  1164. while ( TRUE )
  1165. {
  1166. *UserSid = 0;
  1167. cbUserSid = sizeof(UserSid)/sizeof(TCHAR);
  1168. if ( RegEnumKeyEx( hKey,
  1169. dwIndex,
  1170. UserSid,
  1171. &cbUserSid,
  1172. 0,
  1173. NULL,
  1174. 0,
  1175. &ft ) != ERROR_SUCCESS )
  1176. {
  1177. break;
  1178. }
  1179. CharUpper( UserSid );
  1180. //
  1181. // Look for intersting values
  1182. //
  1183. if (cbUserSid > 0)
  1184. {
  1185. DWORD dwErr;
  1186. HKEY hKeyUser, hKeyEnv, hKeyProfileList;
  1187. TCHAR UserProfilePath[MAX_PATH];
  1188. TCHAR UserProfileHive[MAX_PATH];
  1189. DWORD cbUserProfilePath = 0;
  1190. // trace(0,"UserSid = %S", UserSid);
  1191. dwErr = RegOpenKeyEx( hKey,
  1192. UserSid,
  1193. 0,
  1194. KEY_READ,
  1195. &hKeyProfileList );
  1196. if ( dwErr == ERROR_SUCCESS )
  1197. {
  1198. DWORD Type;
  1199. cbUserProfilePath = sizeof( UserProfilePath );
  1200. dwErr = RegQueryValueEx( hKeyProfileList,
  1201. s_cszProfileImagePath,
  1202. NULL,
  1203. &Type,
  1204. (PBYTE)UserProfilePath,
  1205. &cbUserProfilePath );
  1206. RegCloseKey( hKeyProfileList );
  1207. if ( dwErr != ERROR_SUCCESS )
  1208. {
  1209. trace(0, "Query ProfileImagePath failed: %d", dwErr );
  1210. dwIndex++;
  1211. continue;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. trace(0, "Opening UserSid failed: %d", dwErr );
  1217. dwIndex++;
  1218. continue;
  1219. }
  1220. //
  1221. // Create NTUSER.Dat path from the user profile path
  1222. //
  1223. ExpandEnvironmentStrings( UserProfilePath,
  1224. UserProfileHive,
  1225. sizeof(UserProfileHive) /
  1226. sizeof(TCHAR) );
  1227. _tcscpy( UserProfilePath, UserProfileHive );
  1228. _tcscat( UserProfileHive, TEXT("\\NTUSER.DAT") );
  1229. MergeUserRegistryInfo( UserProfilePath,
  1230. UserProfileHive,
  1231. UserSid );
  1232. }
  1233. dwIndex++;
  1234. }
  1235. fRet = TRUE;
  1236. RegCloseKey( hKey );
  1237. }
  1238. else
  1239. {
  1240. trace( 0, "Failed to open %S", s_cszProfileList );
  1241. }
  1242. TraceFunctLeave();
  1243. return fRet;
  1244. }
  1245. //
  1246. // CFLDatBuilder::BuildTree
  1247. // This methods takes an XML file (the PCHealth Protected file)
  1248. // and outsputs a FLDAT file ( pszOutFile ).
  1249. // It basically just opens up the xml, iterates through
  1250. // all the files and then adds them to the tree. It then
  1251. // creates blobs based on the data gathered and then sends the
  1252. // tree to the CFLPathTree blob class which transforms the tree
  1253. // into the contigious blob format. It then writes it out.
  1254. //
  1255. // -> The method of actually passing the FLDAT file has not be defined,
  1256. // this function just demonstrates the process.
  1257. //
  1258. //
  1259. BOOL
  1260. CFLDatBuilder::BuildTree(
  1261. LPCTSTR pszFile,
  1262. LPCTSTR pszOutFile)
  1263. {
  1264. TCHAR *szBuf = NULL;
  1265. TCHAR *szBuf2 = NULL;
  1266. TCHAR chType;
  1267. LONG lLoop,lMax,lNumTokens;
  1268. BOOL fRet = FALSE;
  1269. s_bSnapShotInit = FALSE;
  1270. //
  1271. // ext list blob
  1272. //
  1273. CFLHashList ExtListBlob( m_hHeapToUse );
  1274. LONG lNumChars, lNumExt, lNumExtTotal;
  1275. //
  1276. // config blob
  1277. //
  1278. BlobHeader ConfigBlob;
  1279. //
  1280. // CFLPathTree blob
  1281. //
  1282. CFLPathTree PathTreeBlob( m_hHeapToUse );
  1283. //
  1284. // outfile
  1285. //
  1286. HANDLE hOutFile=NULL;
  1287. DWORD dwWritten;
  1288. //
  1289. // array opf all the file types, Include, Exclude, SNAPSHOT
  1290. //
  1291. TCHAR achType[3] = { _TEXT('i'), _TEXT('e'), _TEXT('s') };
  1292. LONG lTypeLoop;
  1293. //
  1294. // numeric counterpart of m_chDefaultType;
  1295. //
  1296. DWORD dwDefaultType;
  1297. //
  1298. // should we protect this directory
  1299. //
  1300. BOOL fDisable = FALSE;
  1301. TraceFunctEnter("CFLDatBuilder::BuildTree");
  1302. if( m_pRoot )
  1303. {
  1304. DeleteTree( m_pRoot );
  1305. m_pRoot = NULL;
  1306. }
  1307. if(m_XMLParser.Init(pszFile) == FALSE)
  1308. {
  1309. ErrorTrace(FILEID,
  1310. "There was an error parsing the protected XML file.",0);
  1311. goto cleanup;
  1312. }
  1313. szBuf = new TCHAR[MAX_BUFFER];
  1314. szBuf2 = new TCHAR[MAX_BUFFER+7];
  1315. if (! szBuf || ! szBuf2)
  1316. {
  1317. ErrorTrace(0, "Cannot allocate memory");
  1318. goto cleanup;
  1319. }
  1320. //
  1321. // Calculate the tree default type info
  1322. //
  1323. m_chDefaultType = m_XMLParser.GetDefaultType();
  1324. if( m_chDefaultType == _TEXT('I') )
  1325. dwDefaultType = NODE_TYPE_INCLUDE;
  1326. else if( m_chDefaultType == _TEXT('E') )
  1327. dwDefaultType = NODE_TYPE_EXCLUDE;
  1328. else
  1329. dwDefaultType = NODE_TYPE_UNKNOWN;
  1330. //
  1331. // Loop through the directory/files for each file type (include, exclude )
  1332. //
  1333. for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
  1334. {
  1335. //
  1336. // Find directories for the type
  1337. //
  1338. lMax = m_XMLParser.GetDirectoryCount( achType[lTypeLoop] );
  1339. for(lLoop = 0;lLoop < lMax;lLoop++)
  1340. {
  1341. fDisable = FALSE;
  1342. if( m_XMLParser.GetDirectory(
  1343. lLoop,
  1344. szBuf,
  1345. MAX_BUFFER,
  1346. achType[lTypeLoop],
  1347. &fDisable) != MAX_BUFFER )
  1348. {
  1349. ErrorTrace(FILEID, "Not enough buffer space.",0);
  1350. goto cleanup;
  1351. }
  1352. if( szBuf[0] == _TEXT('*') )
  1353. {
  1354. if( AddMetaDriveFileDir(
  1355. szBuf,
  1356. achType[lTypeLoop],
  1357. FALSE,
  1358. fDisable) == FALSE )
  1359. {
  1360. ErrorTrace(FILEID, "error adding meta drive directory.",0);
  1361. goto cleanup;
  1362. }
  1363. }
  1364. else
  1365. {
  1366. TCHAR szDeviceName[ MAX_PATH ];
  1367. *szDeviceName=0;
  1368. // ankor all nods at Root.. so tree actually looks
  1369. // like Root\C:\Windows etc
  1370. ConvertToInternalFormat( szBuf, szBuf2 );
  1371. lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
  1372. if( AddTreeNode(
  1373. &m_pRoot,
  1374. szBuf2,
  1375. achType[lTypeLoop],
  1376. lNumTokens,
  1377. 0,
  1378. FALSE,
  1379. fDisable ) == FALSE )
  1380. {
  1381. ErrorTrace(FILEID, "Error adding node.",0);
  1382. goto cleanup;
  1383. }
  1384. }
  1385. }
  1386. //
  1387. // Find files for the type
  1388. //
  1389. lMax = m_XMLParser.GetFileCount( achType[lTypeLoop] );
  1390. for(lLoop = 0;lLoop < lMax;lLoop++)
  1391. {
  1392. if( m_XMLParser.GetFile(lLoop,
  1393. szBuf,
  1394. MAX_BUFFER,
  1395. achType[lTypeLoop] ) != MAX_BUFFER )
  1396. {
  1397. ErrorTrace(FILEID, "Not enough buffer space.",0);
  1398. goto cleanup;
  1399. }
  1400. if( szBuf[0] == _TEXT('*') )
  1401. {
  1402. if( AddMetaDriveFileDir( szBuf,
  1403. achType[lTypeLoop],
  1404. TRUE, FALSE ) == FALSE )
  1405. {
  1406. ErrorTrace(FILEID, "error adding meta drive file.",0);
  1407. goto cleanup;
  1408. }
  1409. }
  1410. else
  1411. {
  1412. int iType = lTypeLoop;
  1413. //
  1414. // if type is 's' make it exclude and add to the registry
  1415. // setting fro snapshotted files
  1416. //
  1417. if ( achType[lTypeLoop] == TEXT('s') )
  1418. {
  1419. AddRegistrySnapshotEntry( szBuf );
  1420. iType = 1; // exclude
  1421. }
  1422. //
  1423. // Ankor all nods at Root.. so tree actually looks like
  1424. // Root\C:\Windows etc
  1425. //
  1426. ConvertToInternalFormat( szBuf, szBuf2 );
  1427. lNumTokens = CountTokens( szBuf2, _TEXT('\\') );
  1428. if( AddTreeNode(
  1429. &m_pRoot,
  1430. szBuf2,
  1431. achType[iType],
  1432. lNumTokens,
  1433. 0,
  1434. TRUE,
  1435. FALSE ) == FALSE )
  1436. {
  1437. ErrorTrace(FILEID, "Error adding node.",0);
  1438. goto cleanup;
  1439. }
  1440. }
  1441. }
  1442. }
  1443. //
  1444. // Merge information from the drivetable in to the blob
  1445. //
  1446. if ( MergeDriveTableInfo() == FALSE )
  1447. {
  1448. ErrorTrace(FILEID, "Error merging drive table info.",0);
  1449. goto cleanup;
  1450. }
  1451. //
  1452. // Merge Information under FilesNotToBackup key in to the blob ...
  1453. //
  1454. if ( MergeFilesNotToBackupInfo() == FALSE )
  1455. {
  1456. ErrorTrace(FILEID, "Error merging FilesNotToBackup Info.",0);
  1457. goto cleanup;
  1458. }
  1459. //
  1460. // Merge Per user information from the registry / user hives
  1461. //
  1462. if ( MergeAllUserRegistryInfo() == FALSE )
  1463. {
  1464. ErrorTrace(FILEID, "Error merging user registry info.",0);
  1465. goto cleanup;
  1466. }
  1467. #if 0
  1468. //
  1469. // Commented out: We monitor sfc cache ...
  1470. // Merge information for sfcdllcache
  1471. //
  1472. if ( MergeSfcDllCacheInfo() == FALSE )
  1473. {
  1474. ErrorTrace(FILEID, "Error merging SfcDllCache info.",0);
  1475. goto cleanup;
  1476. }
  1477. #endif
  1478. //
  1479. // Build the path tree based on our tree and the data we collected
  1480. // about it ( filecounts, nodecounts, # chars, etc)
  1481. //
  1482. if( PathTreeBlob.BuildTree(
  1483. m_pRoot,
  1484. m_lNodeCount,
  1485. dwDefaultType,
  1486. m_lFileListCount,
  1487. m_lNumFiles,
  1488. CalculateNumberOfHashBuckets( m_pRoot ),
  1489. m_lNumChars) == FALSE )
  1490. {
  1491. ErrorTrace(FILEID, "Error buildign pathtree blob.",0);
  1492. goto cleanup;
  1493. }
  1494. //
  1495. // Okay, now build a ext list hash blob
  1496. //
  1497. lNumChars = 0;
  1498. lNumExtTotal = 0;
  1499. for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
  1500. {
  1501. lNumExt = m_XMLParser.GetExtCount( achType[ lTypeLoop ] );
  1502. lNumExtTotal += lNumExt;
  1503. for(lLoop = 0;lLoop < lNumExt ;lLoop++)
  1504. {
  1505. if( m_XMLParser.GetExt(
  1506. lLoop,
  1507. szBuf,
  1508. MAX_BUFFER,
  1509. achType[ lTypeLoop ] ) != MAX_BUFFER )
  1510. {
  1511. ErrorTrace(FILEID, "Not enough buffer space.",0);
  1512. goto cleanup;
  1513. }
  1514. lNumChars += _tcslen( szBuf );
  1515. }
  1516. }
  1517. ExtListBlob.Init( lNumExtTotal, lNumChars );
  1518. for(lTypeLoop = 0; lTypeLoop < 3;lTypeLoop++)
  1519. {
  1520. lNumExt = m_XMLParser.GetExtCount( achType[ lTypeLoop ] );
  1521. for(lLoop = 0;lLoop < lNumExt; lLoop++)
  1522. {
  1523. m_XMLParser.GetExt(lLoop, szBuf, MAX_BUFFER, achType[ lTypeLoop ] );
  1524. ExtListBlob.AddFile( szBuf, achType[lTypeLoop] );
  1525. }
  1526. }
  1527. //
  1528. // now we have both blobs, lets write to disk
  1529. //
  1530. if( (hOutFile = CreateFile( pszOutFile,
  1531. GENERIC_READ | GENERIC_WRITE,
  1532. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1533. NULL, // security attributes
  1534. OPEN_ALWAYS,
  1535. FILE_FLAG_RANDOM_ACCESS,
  1536. NULL) // template file
  1537. ) == INVALID_HANDLE_VALUE)
  1538. {
  1539. ErrorTrace( FILEID, "CreateFile Failed 0x%x", GetLastError());
  1540. goto cleanup;
  1541. }
  1542. //
  1543. // Prepare the header blob
  1544. //
  1545. ConfigBlob.m_dwMaxSize = sizeof(BlobHeader) +
  1546. PathTreeBlob.GetSize() +
  1547. ExtListBlob.GetSize();
  1548. ConfigBlob.m_dwVersion = BLOB_VERSION_NUM;
  1549. ConfigBlob.m_dwMagicNum = BLOB_MAGIC_NUM ;
  1550. ConfigBlob.m_dwBlbType = BLOB_TYPE_CONTAINER;
  1551. ConfigBlob.m_dwEntries = 2;
  1552. if ( WriteFile(hOutFile,
  1553. &ConfigBlob,
  1554. sizeof(BlobHeader),
  1555. &dwWritten, NULL) == 0)
  1556. {
  1557. ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
  1558. goto cleanup;
  1559. }
  1560. if ( WriteFile(hOutFile,
  1561. PathTreeBlob.GetBasePointer(),
  1562. PathTreeBlob.GetSize(),
  1563. &dwWritten, NULL) == 0)
  1564. {
  1565. ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
  1566. goto cleanup;
  1567. }
  1568. if ( WriteFile(hOutFile,
  1569. ExtListBlob.GetBasePointer(),
  1570. ExtListBlob.GetSize(),
  1571. &dwWritten, NULL) == 0)
  1572. {
  1573. ErrorTrace( FILEID, "WriteFile Failed 0x%x", GetLastError());
  1574. goto cleanup;
  1575. }
  1576. fRet = TRUE;
  1577. cleanup:
  1578. if (szBuf)
  1579. delete [] szBuf;
  1580. if (szBuf2)
  1581. delete [] szBuf2;
  1582. if( hOutFile )
  1583. {
  1584. CloseHandle( hOutFile );
  1585. }
  1586. ExtListBlob.CleanUpMemory();
  1587. PathTreeBlob.CleanUpMemory();
  1588. if( m_pRoot )
  1589. {
  1590. DeleteTree(m_pRoot);
  1591. m_pRoot = NULL;
  1592. }
  1593. TraceFunctLeave();
  1594. return(fRet);
  1595. }
  1596. //
  1597. // CFLDatBuilder::CountTokens
  1598. // CountTokens(LPTSTR szStr, TCHAR chDelim)
  1599. // Counts the number of tokens seperated by (chDelim) in a string.
  1600. //
  1601. LONG
  1602. CFLDatBuilder::CountTokens(
  1603. LPTSTR szStr,
  1604. TCHAR chDelim)
  1605. {
  1606. LONG lNumTokens=1;
  1607. TraceFunctEnter("CFLDatBuilder::CountTokens");
  1608. _ASSERT( szStr );
  1609. if( *szStr == 0 )
  1610. {
  1611. TraceFunctLeave();
  1612. return(0);
  1613. }
  1614. while( *szStr != 0 )
  1615. {
  1616. if( *szStr == chDelim )
  1617. {
  1618. lNumTokens++;
  1619. }
  1620. szStr = _tcsinc( szStr );
  1621. }
  1622. TraceFunctLeave();
  1623. return(lNumTokens);
  1624. }
  1625. //
  1626. // CFLDatBuilder::_MyStrDup( LPTSTR szIn )
  1627. // Same as _tcsdup or strdup but it does it our own local
  1628. // heap space.
  1629. //
  1630. LPTSTR
  1631. CFLDatBuilder::_MyStrDup(
  1632. LPTSTR szIn )
  1633. {
  1634. LONG lLen;
  1635. LPTSTR pszOut=NULL;
  1636. if( szIn )
  1637. {
  1638. lLen = _tcslen( szIn );
  1639. pszOut = (LPTSTR) HeapAlloc( m_hHeapToUse,
  1640. 0,
  1641. (sizeof(TCHAR) * (lLen+1)) );
  1642. if( pszOut )
  1643. {
  1644. _tcscpy( pszOut, szIn );
  1645. }
  1646. }
  1647. return( pszOut );
  1648. }
  1649. //
  1650. // CFLDatBuilder::CalculateNumberOfHashBuckets
  1651. // Calculates the number of hash buckets needed by the dynamic hashes
  1652. // in the hashlist.
  1653. //
  1654. LONG
  1655. CFLDatBuilder::CalculateNumberOfHashBuckets(
  1656. LPFLTREE_NODE pRoot )
  1657. {
  1658. LONG lNumNeeded=0;
  1659. if( pRoot )
  1660. {
  1661. if( pRoot->pChild )
  1662. {
  1663. lNumNeeded += CalculateNumberOfHashBuckets( pRoot->pChild );
  1664. }
  1665. if( pRoot->pSibling )
  1666. {
  1667. lNumNeeded += CalculateNumberOfHashBuckets( pRoot->pSibling );
  1668. }
  1669. if( pRoot->lNumFilesHashed > 0 )
  1670. {
  1671. lNumNeeded += GetNextHighestPrime( pRoot->lNumFilesHashed );
  1672. }
  1673. }
  1674. return( lNumNeeded );
  1675. }
  1676. //
  1677. // Debugging Methods
  1678. //
  1679. //
  1680. // CFLDatBuilder::PrintList
  1681. //
  1682. void
  1683. CFLDatBuilder::PrintList(
  1684. LPFL_FILELIST pList,
  1685. LONG lLevel)
  1686. {
  1687. LONG lCount;
  1688. if( !pList )
  1689. {
  1690. return;
  1691. }
  1692. for(lCount = 0;lCount < lLevel;lCount++)
  1693. {
  1694. printf(" ");
  1695. }
  1696. printf(" f: %s\n", pList->szFileName );
  1697. PrintList(pList->pNext, lLevel );
  1698. }
  1699. void
  1700. CFLDatBuilder::PrintTree(
  1701. LPFLTREE_NODE pTree,
  1702. LONG lLevel)
  1703. {
  1704. LONG lCount;
  1705. if( pTree )
  1706. {
  1707. for(lCount = 0;lCount < lLevel;lCount++)
  1708. {
  1709. printf(" ");
  1710. }
  1711. printf("%s", pTree->szPath);
  1712. if( pTree->pFileList )
  1713. {
  1714. printf(" (%d) \n", pTree->lNumFilesHashed);
  1715. }
  1716. else
  1717. {
  1718. printf("\n");
  1719. }
  1720. PrintList( pTree->pFileList, lLevel );
  1721. PrintTree( pTree->pChild, lLevel + 1 );
  1722. PrintTree( pTree->pSibling, lLevel );
  1723. }
  1724. return;
  1725. }
  1726. //
  1727. // CFLDatBuilder::IsPrime
  1728. //
  1729. BOOL
  1730. CFLDatBuilder::IsPrime(
  1731. LONG lNumber)
  1732. {
  1733. LONG cl;
  1734. //
  1735. // prevent divide by 0 problems
  1736. //
  1737. if( lNumber == 0 )
  1738. {
  1739. return FALSE;
  1740. }
  1741. if( lNumber == 1 )
  1742. {
  1743. return TRUE;
  1744. }
  1745. for(cl = 2;cl < lNumber;cl++)
  1746. {
  1747. if( (lNumber % cl ) == 0 )
  1748. {
  1749. return FALSE;
  1750. }
  1751. }
  1752. return TRUE;
  1753. }
  1754. //
  1755. // CFLDatBuilder::GetNextHighestPrime
  1756. //
  1757. LONG
  1758. CFLDatBuilder::GetNextHighestPrime(
  1759. LONG lNumber )
  1760. {
  1761. LONG clLoop;
  1762. if( lNumber >= LARGEST_HASH_SIZE )
  1763. {
  1764. return( LARGEST_HASH_SIZE );
  1765. }
  1766. for( clLoop = lNumber; clLoop < LARGEST_HASH_SIZE;clLoop++)
  1767. {
  1768. if( IsPrime( clLoop ) )
  1769. {
  1770. return( clLoop );
  1771. }
  1772. }
  1773. // nothing found, return large hash size.
  1774. return( LARGEST_HASH_SIZE );
  1775. }
  1776. //
  1777. // Some C helper API ( should be removed ?? )
  1778. //
  1779. DWORD
  1780. HeapUsed(
  1781. HANDLE hHeap )
  1782. {
  1783. PROCESS_HEAP_ENTRY HeapEntry;
  1784. DWORD dwAllocSize=0;
  1785. HeapEntry.lpData = NULL;
  1786. while( HeapWalk( hHeap, &HeapEntry) != FALSE )
  1787. {
  1788. if( HeapEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY )
  1789. dwAllocSize += HeapEntry.cbData;
  1790. }
  1791. return( dwAllocSize );
  1792. }
  1793. //
  1794. // Convert to internal NT namespace format + additional formatiing for
  1795. // required to Add the tree node.
  1796. //
  1797. BOOL
  1798. CFLDatBuilder::ConvertToInternalFormat(
  1799. LPTSTR szFrom,
  1800. LPTSTR szTo
  1801. )
  1802. {
  1803. BOOL fRet = FALSE;
  1804. #ifdef USE_NTDEVICENAMES
  1805. if(szFrom[1] == TEXT(':') )
  1806. {
  1807. TCHAR szDeviceName[MAX_PATH];
  1808. szFrom[2] = 0;
  1809. QueryDosDevice( szFrom, szDeviceName, sizeof(szDeviceName) );
  1810. _stprintf(szTo,
  1811. _TEXT("NTROOT%s\\%s"),
  1812. szDeviceName,
  1813. szFrom+3 );
  1814. //
  1815. // remove terminating slash
  1816. //
  1817. if (szTo[_tcslen( szTo ) - 1] == _TEXT('\\'))
  1818. szTo[_tcslen( szTo ) - 1] = 0;
  1819. CharUpper( szTo );
  1820. }
  1821. else
  1822. #endif
  1823. {
  1824. _stprintf(szTo,_TEXT("NTROOT\\%s"), szFrom);
  1825. }
  1826. fRet = TRUE;
  1827. return fRet;
  1828. }
  1829. //
  1830. // Adjust the process privileges so that we can load other user's hives.
  1831. //
  1832. DWORD
  1833. CFLDatBuilder::SetPrivilegeInAccessToken(
  1834. LPCTSTR pszPrivilegeName
  1835. )
  1836. {
  1837. TraceFunctEnter("CSnapshot::SetPrivilegeInAccessToken");
  1838. HANDLE hProcess;
  1839. HANDLE hAccessToken=NULL;
  1840. LUID luidPrivilegeLUID;
  1841. TOKEN_PRIVILEGES tpTokenPrivilege;
  1842. DWORD dwReturn = ERROR_INTERNAL_ERROR, dwErr;
  1843. hProcess = GetCurrentProcess();
  1844. if (!hProcess)
  1845. {
  1846. dwReturn = GetLastError();
  1847. trace(0, "GetCurrentProcess failed ec=%d", dwReturn);
  1848. goto done;
  1849. }
  1850. if (!OpenProcessToken(hProcess,
  1851. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1852. &hAccessToken))
  1853. {
  1854. dwErr=GetLastError();
  1855. trace(0, "OpenProcessToken failed ec=%d", dwErr);
  1856. if (ERROR_SUCCESS != dwErr)
  1857. {
  1858. dwReturn = dwErr;
  1859. }
  1860. goto done;
  1861. }
  1862. if (!LookupPrivilegeValue(NULL,
  1863. pszPrivilegeName,
  1864. &luidPrivilegeLUID))
  1865. {
  1866. dwErr=GetLastError();
  1867. trace(0, "LookupPrivilegeValue failed ec=%d",dwErr);
  1868. if (ERROR_SUCCESS != dwErr)
  1869. {
  1870. dwReturn = dwErr;
  1871. }
  1872. goto done;
  1873. }
  1874. tpTokenPrivilege.PrivilegeCount = 1;
  1875. tpTokenPrivilege.Privileges[0].Luid = luidPrivilegeLUID;
  1876. tpTokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1877. if (!AdjustTokenPrivileges(hAccessToken,
  1878. FALSE, // Do not disable all
  1879. &tpTokenPrivilege,
  1880. sizeof(TOKEN_PRIVILEGES),
  1881. NULL, // Ignore previous info
  1882. NULL)) // Ignore previous info
  1883. {
  1884. dwErr=GetLastError();
  1885. trace(0, "AdjustTokenPrivileges");
  1886. if (dwErr != NO_ERROR)
  1887. {
  1888. dwReturn = dwErr;
  1889. }
  1890. goto done;
  1891. }
  1892. dwReturn = ERROR_SUCCESS;
  1893. done:
  1894. if (hAccessToken != NULL)
  1895. {
  1896. CloseHandle(hAccessToken);
  1897. }
  1898. TraceFunctLeave();
  1899. return dwReturn;
  1900. }