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.

790 lines
20 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * respoint.cpp
  7. *
  8. * Abstract:
  9. * CRestorePoint, CRestorePointEnum class functions
  10. *
  11. * Revision History:
  12. * Brijesh Krishnaswami (brijeshk) 03/17/2000
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include "precomp.h"
  17. #include "srapi.h"
  18. #ifdef THIS_FILE
  19. #undef THIS_FILE
  20. #endif
  21. static char __szTraceSourceFile[] = __FILE__;
  22. #define THIS_FILE __szTraceSourceFile
  23. // constructors
  24. // use this constructor to read in an existing rp
  25. // then need to call Read() to initialize rp members
  26. CRestorePoint::CRestorePoint()
  27. {
  28. m_pRPInfo = NULL;
  29. lstrcpy(m_szRPDir, L"");
  30. m_itCurChgLogEntry = m_ChgLogList.end();
  31. m_fForward = TRUE;
  32. m_fDefunct = FALSE;
  33. }
  34. // initialize
  35. BOOL
  36. CRestorePoint::Load(RESTOREPOINTINFOW *prpinfo)
  37. {
  38. if (prpinfo)
  39. {
  40. if (! m_pRPInfo)
  41. {
  42. m_pRPInfo = (RESTOREPOINTINFOW *) SRMemAlloc(sizeof(RESTOREPOINTINFOW));
  43. if (! m_pRPInfo)
  44. return FALSE;
  45. }
  46. CopyMemory(m_pRPInfo, prpinfo, sizeof(RESTOREPOINTINFOW));
  47. }
  48. return TRUE;
  49. }
  50. // destructor
  51. // call FindClose here
  52. // if no enumeration was done, this is a no-op
  53. CRestorePoint::~CRestorePoint()
  54. {
  55. if (m_pRPInfo)
  56. SRMemFree(m_pRPInfo);
  57. FindClose();
  58. }
  59. // return first/last change log entry in this restore point
  60. // assumes Read() has already been called
  61. DWORD
  62. CRestorePoint::FindFirstChangeLogEntry(
  63. LPWSTR pszDrive,
  64. BOOL fForward,
  65. CChangeLogEntry& cle)
  66. {
  67. DWORD dwRc = ERROR_SUCCESS;
  68. WCHAR szChgLogPrefix[MAX_PATH];
  69. WIN32_FIND_DATA FindData;
  70. INT64 llSeqNum;
  71. WCHAR szPath[MAX_PATH];
  72. TENTER("CRestorePoint::FindFirstChangeLogEntry");
  73. m_fForward = fForward;
  74. lstrcpy(m_szDrive, pszDrive);
  75. // read the first/last change log in this restore point
  76. // all entries inside a change log will always be read in forward order
  77. MakeRestorePath(szPath, m_szDrive, m_szRPDir);
  78. wsprintf(szChgLogPrefix, L"%s\\%s", szPath, s_cszChangeLogPrefix);
  79. if (! m_FindFile._FindFirstFile(szChgLogPrefix,
  80. s_cszChangeLogSuffix,
  81. &FindData,
  82. m_fForward,
  83. FALSE))
  84. {
  85. TRACE(0, "No changelog in %S", szPath);
  86. dwRc = ERROR_NO_MORE_ITEMS;
  87. goto done;
  88. }
  89. lstrcat(szPath, L"\\");
  90. lstrcat(szPath, FindData.cFileName);
  91. // build list of entries in increasing order of sequence number
  92. dwRc = BuildList(szPath);
  93. if (ERROR_SUCCESS != dwRc)
  94. {
  95. TRACE(0, "! BuildList : %ld", dwRc);
  96. goto done;
  97. }
  98. TRACE(0, "Enumerating %S in %S", FindData.cFileName, m_szRPDir);
  99. // if there was no entry in this change log, go to the next
  100. if (m_ChgLogList.empty())
  101. {
  102. dwRc = FindNextChangeLogEntry(cle);
  103. goto done;
  104. }
  105. // get the first/last entry
  106. if (m_fForward)
  107. {
  108. m_itCurChgLogEntry = m_ChgLogList.begin();
  109. }
  110. else
  111. {
  112. m_itCurChgLogEntry = m_ChgLogList.end();
  113. m_itCurChgLogEntry--;
  114. }
  115. // read in the change log entry into the object
  116. cle.Load(*m_itCurChgLogEntry, m_szRPDir);
  117. done:
  118. TLEAVE();
  119. return dwRc;
  120. }
  121. // return next/prev change log entry in this restore point
  122. // assumes Read() has already been called
  123. DWORD
  124. CRestorePoint::FindNextChangeLogEntry(
  125. CChangeLogEntry& cle)
  126. {
  127. DWORD dwRc = ERROR_SUCCESS;
  128. WCHAR szPath[MAX_PATH];
  129. WCHAR szChgLogPrefix[MAX_PATH];
  130. WIN32_FIND_DATA FindData;
  131. INT64 llSeqNum;
  132. TENTER("CRestorePoint::FindNextChangeLogEntry");
  133. // go to the next entry in the list
  134. m_fForward ? m_itCurChgLogEntry++ : m_itCurChgLogEntry--;
  135. // check if we've reached the end of this change log
  136. // end is the same for both forward and reverse enumeration
  137. if (m_itCurChgLogEntry == m_ChgLogList.end())
  138. {
  139. // if so, read the next change log into memory
  140. // nuke the current list
  141. FindClose();
  142. MakeRestorePath(szPath, m_szDrive, m_szRPDir);
  143. wsprintf(szChgLogPrefix, L"%s\\%s", szPath, s_cszChangeLogPrefix);
  144. if (FALSE == m_FindFile._FindNextFile(szChgLogPrefix,
  145. s_cszChangeLogSuffix,
  146. &FindData))
  147. {
  148. dwRc = ERROR_NO_MORE_ITEMS;
  149. TRACE(0, "No more change logs");
  150. goto done;
  151. }
  152. lstrcat(szPath, L"\\");
  153. lstrcat(szPath, FindData.cFileName);
  154. dwRc = BuildList(szPath);
  155. if (ERROR_SUCCESS != dwRc)
  156. {
  157. TRACE(0, "BuildList : error=%ld", dwRc);
  158. goto done;
  159. }
  160. TRACE(0, "Enumerating %S in %S", FindData.cFileName, m_szRPDir);
  161. if (m_ChgLogList.empty())
  162. {
  163. dwRc = FindNextChangeLogEntry(cle);
  164. goto done;
  165. }
  166. // get the first/last entry
  167. if (m_fForward)
  168. {
  169. m_itCurChgLogEntry = m_ChgLogList.begin();
  170. }
  171. else
  172. {
  173. m_itCurChgLogEntry = m_ChgLogList.end();
  174. m_itCurChgLogEntry--;
  175. }
  176. }
  177. // read in the change log entry fields into the object
  178. cle.Load(*m_itCurChgLogEntry, m_szRPDir);
  179. done:
  180. TLEAVE();
  181. return dwRc;
  182. }
  183. DWORD
  184. CRestorePoint::BuildList(
  185. LPWSTR pszChgLog)
  186. {
  187. DWORD dwRc = ERROR_INTERNAL_ERROR;
  188. HANDLE hChgLog = INVALID_HANDLE_VALUE;
  189. DWORD dwRead;
  190. DWORD dwEntrySize;
  191. PVOID pBlob = NULL;
  192. SR_LOG_ENTRY* pEntry = NULL;
  193. PSR_LOG_HEADER pLogHeader = NULL;
  194. DWORD cbSize;
  195. TENTER("CChangeLogEntry::BuildList");
  196. hChgLog = CreateFile(pszChgLog, // file name
  197. GENERIC_READ, // access mode
  198. FILE_SHARE_READ, // share mode
  199. NULL, // SD
  200. OPEN_EXISTING, // how to create
  201. FILE_ATTRIBUTE_NORMAL, // file attributes
  202. NULL);
  203. if (INVALID_HANDLE_VALUE == hChgLog)
  204. {
  205. dwRc = GetLastError();
  206. TRACE(0, "! CreateFile on %S : %ld", pszChgLog, dwRc);
  207. goto done;
  208. }
  209. // read header size
  210. if (FALSE == ReadFile(hChgLog,
  211. &cbSize,
  212. sizeof(DWORD),
  213. &dwRead,
  214. NULL) || dwRead == 0 || cbSize == 0)
  215. {
  216. // if the file could not be read,
  217. // assume that it is a 0-sized log, and go to the next log
  218. dwRc = GetLastError();
  219. TRACE(0, "Zero sized log : %ld", pszChgLog, dwRc);
  220. dwRc = ERROR_SUCCESS;
  221. goto done;
  222. }
  223. pLogHeader = (SR_LOG_HEADER *) SRMemAlloc(cbSize);
  224. if (! pLogHeader)
  225. {
  226. TRACE(0, "Out of memory");
  227. goto done;
  228. }
  229. // read header
  230. pLogHeader->Header.RecordSize = cbSize;
  231. if (FALSE == ReadFile(hChgLog,
  232. (PVOID) ( ((BYTE *) pLogHeader) + sizeof(DWORD)),
  233. cbSize - sizeof(DWORD),
  234. &dwRead,
  235. NULL))
  236. {
  237. dwRc = GetLastError();
  238. TRACE(0, "! ReadFile on %S : %ld", pszChgLog, dwRc);
  239. goto done;
  240. }
  241. // check log's integrity
  242. if( pLogHeader->LogVersion != SR_LOG_VERSION ||
  243. pLogHeader->MagicNum != SR_LOG_MAGIC_NUMBER )
  244. {
  245. TRACE(0, "! LogHeader for %S : invalid or corrupt", pszChgLog);
  246. goto done;
  247. }
  248. // now read the entries
  249. do
  250. {
  251. // get the size of the entry
  252. if (FALSE == ReadFile(hChgLog, &dwEntrySize, sizeof(DWORD), &dwRead, NULL))
  253. {
  254. TRACE(0, "ReadFile failed, error=%ld", GetLastError());
  255. break;
  256. }
  257. if (0 == dwRead) // end of file
  258. {
  259. TRACE(0, "End of file");
  260. dwRc = ERROR_NO_MORE_ITEMS;
  261. break;
  262. }
  263. if (dwRead != sizeof(DWORD)) // error reading entry
  264. {
  265. TRACE(0, "Readfile could not read a DWORD");
  266. break;
  267. }
  268. if (0 == dwEntrySize) // reached the last entry
  269. {
  270. TRACE(0, "No more entries");
  271. dwRc = ERROR_NO_MORE_ITEMS;
  272. break;
  273. }
  274. // get the entry itself
  275. pEntry = (SR_LOG_ENTRY *) SRMemAlloc(dwEntrySize);
  276. if (! pEntry)
  277. {
  278. TRACE(0, "Out of memory");
  279. break;
  280. }
  281. pEntry->Header.RecordSize = dwEntrySize;
  282. // skip the size field
  283. pBlob = (PVOID) ((PBYTE) pEntry + sizeof(dwEntrySize));
  284. if (FALSE == ReadFile(hChgLog, pBlob, dwEntrySize - sizeof(dwEntrySize), &dwRead, NULL))
  285. {
  286. TRACE(0, "! ReadFile on %S : %ld", pszChgLog, GetLastError());
  287. break;
  288. }
  289. if (dwRead != dwEntrySize - sizeof(dwEntrySize)) // error reading entry
  290. {
  291. TRACE(0, "! Readfile: ToRead=%ld, Read=%ld bytes",
  292. dwEntrySize - sizeof(dwEntrySize), dwRead);
  293. break;
  294. }
  295. // insert entry into list
  296. dwRc = InsertEntryIntoList(pEntry);
  297. } while (ERROR_SUCCESS == dwRc);
  298. if (ERROR_NO_MORE_ITEMS == dwRc)
  299. {
  300. dwRc = ERROR_SUCCESS;
  301. }
  302. done:
  303. if (INVALID_HANDLE_VALUE != hChgLog)
  304. CloseHandle(hChgLog);
  305. SRMemFree(pLogHeader);
  306. TLEAVE();
  307. return dwRc;
  308. }
  309. // release memory and empty the list
  310. DWORD CRestorePoint::FindClose()
  311. {
  312. // nuke the list
  313. for (m_itCurChgLogEntry = m_ChgLogList.begin();
  314. m_itCurChgLogEntry != m_ChgLogList.end();
  315. m_itCurChgLogEntry++)
  316. {
  317. SRMemFree(*m_itCurChgLogEntry);
  318. }
  319. m_ChgLogList.clear();
  320. return ERROR_SUCCESS;
  321. }
  322. // insert change log entry into list
  323. DWORD
  324. CRestorePoint::InsertEntryIntoList(
  325. SR_LOG_ENTRY* pEntry)
  326. {
  327. TENTER("CRestorePoint::InsertEntryIntoList");
  328. m_ChgLogList.push_back(pEntry);
  329. TLEAVE();
  330. return ERROR_SUCCESS;
  331. }
  332. // populate members
  333. DWORD
  334. CRestorePoint::ReadLog()
  335. {
  336. DWORD dwRc = ERROR_SUCCESS;
  337. WCHAR szLog[MAX_PATH];
  338. WCHAR szSystemDrive[MAX_PATH];
  339. DWORD dwRead;
  340. TENTER("CRestorePoint::ReadLog");
  341. // construct path of rp.log
  342. GetSystemDrive(szSystemDrive);
  343. MakeRestorePath(szLog, szSystemDrive, m_szRPDir);
  344. lstrcat(szLog, L"\\");
  345. lstrcat(szLog, s_cszRestorePointLogName);
  346. HANDLE hFile = CreateFile (szLog, // file name
  347. GENERIC_READ, // file access
  348. FILE_SHARE_READ, // share mode
  349. NULL, // SD
  350. OPEN_EXISTING, // how to create
  351. 0, // file attributes
  352. NULL); // handle to template file
  353. if (INVALID_HANDLE_VALUE == hFile)
  354. {
  355. dwRc = GetLastError();
  356. trace(0, "! CreateFile on %S : %ld", szLog, dwRc);
  357. goto done;
  358. }
  359. // read the restore point info
  360. if (! m_pRPInfo)
  361. {
  362. m_pRPInfo = (RESTOREPOINTINFOW *) SRMemAlloc(sizeof(RESTOREPOINTINFOW));
  363. if (! m_pRPInfo)
  364. {
  365. dwRc = ERROR_OUTOFMEMORY;
  366. trace(0, "SRMemAlloc failed");
  367. goto done;
  368. }
  369. }
  370. if (FALSE == ReadFile(hFile, m_pRPInfo, sizeof(RESTOREPOINTINFOW), &dwRead, NULL) ||
  371. dwRead != sizeof(RESTOREPOINTINFOW))
  372. {
  373. dwRc = GetLastError();
  374. trace(0, "! ReadFile on %S : %ld", szLog, dwRc);
  375. goto done;
  376. }
  377. m_fDefunct = (m_pRPInfo->dwRestorePtType == CANCELLED_OPERATION);
  378. // read the creation time
  379. if (FALSE == ReadFile(hFile, &m_Time, sizeof(m_Time), &dwRead, NULL) ||
  380. dwRead != sizeof(m_Time))
  381. {
  382. dwRc = GetLastError();
  383. trace(0, "! ReadFile on %S : %ld", szLog, dwRc);
  384. goto done;
  385. }
  386. done:
  387. if (INVALID_HANDLE_VALUE != hFile)
  388. CloseHandle(hFile);
  389. TLEAVE();
  390. return dwRc;
  391. }
  392. DWORD
  393. CRestorePoint::WriteLog()
  394. {
  395. DWORD dwRc = ERROR_SUCCESS;
  396. WCHAR szLog[MAX_PATH];
  397. WCHAR szSystemDrive[MAX_PATH];
  398. DWORD dwWritten;
  399. HANDLE hFile = INVALID_HANDLE_VALUE;
  400. TENTER("CRestorePoint::WriteLog");
  401. if (! m_pRPInfo)
  402. {
  403. ASSERT(0);
  404. dwRc = ERROR_INTERNAL_ERROR;
  405. goto done;
  406. }
  407. // set the creation time to the current time
  408. GetSystemTimeAsFileTime(&m_Time);
  409. // construct path of rp.log
  410. GetSystemDrive(szSystemDrive);
  411. MakeRestorePath(szLog, szSystemDrive, m_szRPDir);
  412. lstrcat(szLog, L"\\");
  413. lstrcat(szLog, s_cszRestorePointLogName);
  414. hFile = CreateFile (szLog, // file name
  415. GENERIC_WRITE, // file access
  416. 0, // share mode
  417. NULL, // SD
  418. CREATE_ALWAYS, // how to create
  419. FILE_FLAG_WRITE_THROUGH, // file attributes
  420. NULL); // handle to template file
  421. if (INVALID_HANDLE_VALUE == hFile)
  422. {
  423. dwRc = GetLastError();
  424. trace(0, "! CreateFile on %S : %ld", szLog, dwRc);
  425. goto done;
  426. }
  427. // write the restore point info
  428. if (FALSE == WriteFile(hFile, m_pRPInfo, sizeof(RESTOREPOINTINFOW), &dwWritten, NULL))
  429. {
  430. dwRc = GetLastError();
  431. trace(0, "! WriteFile on %S : %ld", szLog, dwRc);
  432. goto done;
  433. }
  434. // write the creation time
  435. if (FALSE == WriteFile(hFile, &m_Time, sizeof(m_Time), &dwWritten, NULL))
  436. {
  437. dwRc = GetLastError();
  438. trace(0, "! WriteFile on %S : %ld", szLog, dwRc);
  439. goto done;
  440. }
  441. done:
  442. if (INVALID_HANDLE_VALUE != hFile)
  443. CloseHandle(hFile);
  444. TLEAVE();
  445. return dwRc;
  446. }
  447. BOOL
  448. CRestorePoint::DeleteLog()
  449. {
  450. WCHAR szLog[MAX_PATH];
  451. WCHAR szSystemDrive[MAX_PATH];
  452. GetSystemDrive(szSystemDrive);
  453. MakeRestorePath(szLog, szSystemDrive, m_szRPDir);
  454. lstrcat(szLog, L"\\");
  455. lstrcat(szLog, s_cszRestorePointLogName);
  456. return DeleteFile(szLog);
  457. }
  458. DWORD
  459. CRestorePoint::Cancel()
  460. {
  461. if (m_pRPInfo)
  462. {
  463. m_pRPInfo->dwRestorePtType = CANCELLED_OPERATION;
  464. return WriteLog();
  465. }
  466. else
  467. {
  468. ASSERT(0);
  469. return ERROR_INTERNAL_ERROR;
  470. }
  471. }
  472. DWORD
  473. CRestorePoint::GetNum()
  474. {
  475. return GetID(m_szRPDir);
  476. }
  477. // read the size of the restore point folder from file
  478. DWORD CRestorePoint::ReadSize (const WCHAR *pwszDrive, INT64 *pllSize)
  479. {
  480. DWORD dwErr = ERROR_SUCCESS;
  481. DWORD cbRead = 0;
  482. WCHAR wcsPath[MAX_PATH];
  483. MakeRestorePath(wcsPath, pwszDrive, m_szRPDir);
  484. lstrcat(wcsPath, L"\\");
  485. lstrcat (wcsPath, s_cszRestorePointSize);
  486. HANDLE hFile = CreateFileW ( wcsPath, // file name
  487. GENERIC_READ, // file access
  488. FILE_SHARE_READ, // share mode
  489. NULL, // SD
  490. OPEN_EXISTING, // how to create
  491. 0, // file attributes
  492. NULL); // handle to template file
  493. if (INVALID_HANDLE_VALUE == hFile)
  494. {
  495. dwErr = GetLastError();
  496. return dwErr;
  497. }
  498. if (FALSE == ReadFile (hFile, (BYTE *) pllSize, sizeof(*pllSize),
  499. &cbRead, NULL))
  500. {
  501. dwErr = GetLastError();
  502. }
  503. CloseHandle (hFile);
  504. return dwErr;
  505. }
  506. // write the size of the restore point folder to file
  507. DWORD CRestorePoint::WriteSize (const WCHAR *pwszDrive, INT64 llSize)
  508. {
  509. DWORD dwErr = ERROR_SUCCESS;
  510. DWORD cbWritten = 0;
  511. WCHAR wcsPath[MAX_PATH];
  512. MakeRestorePath(wcsPath, pwszDrive, m_szRPDir);
  513. lstrcat(wcsPath, L"\\");
  514. lstrcat (wcsPath, s_cszRestorePointSize);
  515. HANDLE hFile = CreateFileW ( wcsPath, // file name
  516. GENERIC_WRITE, // file access
  517. 0, // share mode
  518. NULL, // SD
  519. CREATE_ALWAYS, // how to create
  520. 0, // file attributes
  521. NULL); // handle to template file
  522. if (INVALID_HANDLE_VALUE == hFile)
  523. {
  524. dwErr = GetLastError();
  525. return dwErr;
  526. }
  527. if (FALSE == WriteFile (hFile, (BYTE *) &llSize, sizeof(llSize),
  528. &cbWritten, NULL))
  529. {
  530. dwErr = GetLastError();
  531. }
  532. CloseHandle (hFile);
  533. return dwErr;
  534. }
  535. // populate a changelogentry object
  536. void
  537. CChangeLogEntry::Load(SR_LOG_ENTRY *pentry, LPWSTR pszRPDir)
  538. {
  539. PSR_LOG_DEBUG_INFO pDebugRec = NULL;
  540. _pentry = pentry;
  541. _pszPath1 = _pszPath2 = _pszTemp = _pszProcess = _pszShortName = NULL;
  542. _pbAcl = NULL;
  543. _cbAcl = 0;
  544. _fAclInline = FALSE;
  545. lstrcpy(_pszRPDir, pszRPDir);
  546. BYTE *pRec = (PBYTE) & _pentry->SubRecords;
  547. //
  548. // get source path
  549. //
  550. _pszPath1 = (LPWSTR) (pRec + sizeof(RECORD_HEADER));
  551. //
  552. // get temp path if exists
  553. //
  554. if (_pentry->EntryFlags & ENTRYFLAGS_TEMPPATH)
  555. {
  556. pRec += RECORD_SIZE(pRec);
  557. _pszTemp = (LPWSTR) (pRec + sizeof(RECORD_HEADER));
  558. }
  559. //
  560. // get second path if exists
  561. //
  562. if (_pentry->EntryFlags & ENTRYFLAGS_SECONDPATH)
  563. {
  564. pRec += RECORD_SIZE(pRec);
  565. _pszPath2 = (LPWSTR) (pRec + sizeof(RECORD_HEADER));
  566. }
  567. //
  568. // get acl info if exists
  569. //
  570. if (_pentry->EntryFlags & ENTRYFLAGS_ACLINFO)
  571. {
  572. pRec += RECORD_SIZE(pRec);
  573. if (RECORD_TYPE(pRec) == RecordTypeAclInline)
  574. {
  575. _fAclInline = TRUE;
  576. }
  577. _pbAcl = (BYTE *) (pRec + sizeof(RECORD_HEADER));
  578. _cbAcl = RECORD_SIZE(pRec) - sizeof(RECORD_HEADER);
  579. }
  580. //
  581. // get debug info if exists
  582. //
  583. if (_pentry->EntryFlags & ENTRYFLAGS_DEBUGINFO)
  584. {
  585. pRec += RECORD_SIZE(pRec);
  586. pDebugRec = (PSR_LOG_DEBUG_INFO) pRec;
  587. _pszProcess = (LPWSTR) (pDebugRec->ProcessName);
  588. }
  589. //
  590. // get shortname if exists
  591. //
  592. if (_pentry->EntryFlags & ENTRYFLAGS_SHORTNAME)
  593. {
  594. pRec += RECORD_SIZE(pRec);
  595. _pszShortName = (LPWSTR) (pRec + sizeof(RECORD_HEADER));
  596. }
  597. return;
  598. }
  599. // this function will check if any filepath length exceeds
  600. // the max length that restore supports
  601. // if so, it will return FALSE
  602. BOOL
  603. CChangeLogEntry::CheckPathLengths()
  604. {
  605. if (_pszPath1 && lstrlen(_pszPath1) > SR_MAX_FILENAME_PATH-1)
  606. return FALSE;
  607. if (_pszPath2 && lstrlen(_pszPath2) > SR_MAX_FILENAME_PATH-1)
  608. return FALSE;
  609. if (_pszTemp && lstrlen(_pszTemp) > SR_MAX_FILENAME_PATH-1)
  610. return FALSE;
  611. return TRUE;
  612. }