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.

1961 lines
58 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. mapentry.cpp
  5. Abstract:
  6. This file contains the implementation of CRestoreMapEntry class
  7. derived classes for each operation types, and ::CreateRestoreMapEntry.
  8. Revision History:
  9. Seong Kook Khang (SKKhang) 06/22/00
  10. created
  11. ******************************************************************************/
  12. #include "stdwin.h"
  13. #include "rstrcore.h"
  14. #include "resource.h"
  15. #include "malloc.h"
  16. static LPCWSTR s_cszErr;
  17. inline BOOL IsLockedError( DWORD dwErr )
  18. {
  19. return( ( dwErr == ERROR_ACCESS_DENIED ) ||
  20. ( dwErr == ERROR_SHARING_VIOLATION ) ||
  21. ( dwErr == ERROR_USER_MAPPED_FILE ) ||
  22. ( dwErr == ERROR_LOCK_VIOLATION ) );
  23. }
  24. BOOL RenameLockedObject( LPCWSTR cszPath, LPWSTR szAlt )
  25. {
  26. TraceFunctEnter("RenameLockedObject");
  27. BOOL fRet = FALSE;
  28. //BUGBUG - following code is not guaranteeing the new name is unique.
  29. // In a rare instance, if same file name already exists in one of
  30. // the map entries, conflict might happen.
  31. if ( !::SRGetAltFileName( cszPath, szAlt ) )
  32. goto Exit;
  33. if ( !::MoveFile( cszPath, szAlt ) )
  34. {
  35. s_cszErr = ::GetSysErrStr();
  36. ErrorTrace(0, "::MoveFile failed - %ls", s_cszErr);
  37. ErrorTrace(0, " From Dst=%ls", cszPath);
  38. ErrorTrace(0, " To Src=%ls", szAlt);
  39. goto Exit;
  40. }
  41. fRet = TRUE;
  42. Exit:
  43. TraceFunctLeave();
  44. return( fRet );
  45. }
  46. /////////////////////////////////////////////////////////////////////////////
  47. //
  48. // Class Definitions
  49. //
  50. /////////////////////////////////////////////////////////////////////////////
  51. // Process Dependency Flags
  52. #define PDF_LOC 0x0001 // Dependency for location, e.g. Del & RENAME TO
  53. #define PDF_OBJ 0x0002 // Dependency for object, e.g. Add & Rename FROM
  54. #define PDF_BOTH (PDF_LOC|PDF_OBJ)
  55. /////////////////////////////////////////////////////////////////////////////
  56. class CRMEDirCreate : public CRestoreMapEntry
  57. {
  58. public:
  59. CRMEDirCreate( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszShortFileName);
  60. // operations - methods
  61. public:
  62. void Restore( CRestoreOperationManager* );
  63. };
  64. /////////////////////////////////////////////////////////////////////////////
  65. class CRMEDirDelete : public CRestoreMapEntry
  66. {
  67. public:
  68. CRMEDirDelete( INT64 llSeq, LPCWSTR cszSrc );
  69. // operations - methods
  70. public:
  71. void Restore( CRestoreOperationManager *pROMgr );
  72. void ProcessLocked();
  73. };
  74. /////////////////////////////////////////////////////////////////////////////
  75. class CRMEDirRename : public CRestoreMapEntry
  76. {
  77. public:
  78. CRMEDirRename( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst,
  79. LPCWSTR cszShortFileName);
  80. // operations - methods
  81. public:
  82. LPCWSTR GetPath2()
  83. { return( m_strDst ); }
  84. void Restore( CRestoreOperationManager *pROMgr );
  85. void ProcessLocked();
  86. };
  87. /////////////////////////////////////////////////////////////////////////////
  88. class CRMEFileCreate : public CRestoreMapEntry
  89. {
  90. public:
  91. CRMEFileCreate( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszTmp,
  92. LPCWSTR cszShortFileName);
  93. // operations - methods
  94. public:
  95. LPCWSTR GetPath2()
  96. { return( m_strTmp ); }
  97. void Restore( CRestoreOperationManager *pROMgr );
  98. void ProcessLocked();
  99. };
  100. /////////////////////////////////////////////////////////////////////////////
  101. class CRMEFileDelete : public CRestoreMapEntry
  102. {
  103. public:
  104. CRMEFileDelete( INT64 llSeq, LPCWSTR cszSrc );
  105. // operations - methods
  106. public:
  107. void Restore( CRestoreOperationManager *pROMgr );
  108. void ProcessLocked();
  109. };
  110. /////////////////////////////////////////////////////////////////////////////
  111. class CRMEFileModify : public CRestoreMapEntry
  112. {
  113. public:
  114. CRMEFileModify( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszTmp );
  115. // operations - methods
  116. public:
  117. LPCWSTR GetPath2()
  118. { return( m_strTmp ); }
  119. void Restore( CRestoreOperationManager* );
  120. void ProcessLocked();
  121. };
  122. /////////////////////////////////////////////////////////////////////////////
  123. class CRMEFileRename : public CRestoreMapEntry
  124. {
  125. public:
  126. CRMEFileRename( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst,
  127. LPCWSTR cszShortFileName );
  128. // operations - methods
  129. public:
  130. LPCWSTR GetPath2()
  131. { return( m_strDst ); }
  132. void Restore( CRestoreOperationManager *pROMgr );
  133. void ProcessLocked();
  134. };
  135. /////////////////////////////////////////////////////////////////////////////
  136. class CRMESetAcl : public CRestoreMapEntry
  137. {
  138. public:
  139. CRMESetAcl( INT64 llSeq, LPCWSTR cszSrc, LPBYTE pbAcl, DWORD cbAcl, BOOL fInline, LPCWSTR cszDSPath );
  140. //CRMESetAcl( LPCWSTR cszSrc, LPBYTE pbAcl, DWORD cbAcl );
  141. //CRMESetAcl( LPCWSTR cszSrc, LPCWSTR cszAcl );
  142. ~CRMESetAcl();
  143. // operations - methods
  144. public:
  145. void Restore( CRestoreOperationManager* );
  146. // attributes
  147. protected:
  148. CSRStr m_strAclPath; // string is empty if it's an inline Acl
  149. DWORD m_cbAcl;
  150. LPBYTE m_pbAcl; // this is actually a SECURITY_DESCRIPTOR (with
  151. // 20 bytes of header for self-relative format.)
  152. };
  153. /////////////////////////////////////////////////////////////////////////////
  154. class CRMESetAttrib : public CRestoreMapEntry
  155. {
  156. public:
  157. CRMESetAttrib( INT64 llSeq, LPCWSTR cszSrc, DWORD dwAttr );
  158. // operations - methods
  159. public:
  160. void Restore( CRestoreOperationManager* );
  161. };
  162. /////////////////////////////////////////////////////////////////////////////
  163. class CRMEMountDelete : public CRestoreMapEntry
  164. {
  165. public:
  166. CRMEMountDelete( INT64 llSeq, LPCWSTR cszSrc );
  167. // operations - methods
  168. public:
  169. void Restore( CRestoreOperationManager* );
  170. };
  171. /////////////////////////////////////////////////////////////////////////////
  172. class CRMEMountCreate : public CRestoreMapEntry
  173. {
  174. public:
  175. CRMEMountCreate( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst);
  176. // operations - methods
  177. public:
  178. void Restore( CRestoreOperationManager* );
  179. };
  180. /////////////////////////////////////////////////////////////////////////////
  181. //
  182. // CRestoreMapEntry
  183. //
  184. /////////////////////////////////////////////////////////////////////////////
  185. CRestoreMapEntry::CRestoreMapEntry( INT64 llSeq, DWORD dwOpr, LPCWSTR cszSrc )
  186. {
  187. m_llSeq = llSeq;
  188. m_dwOpr = dwOpr;
  189. m_dwAttr = 0;
  190. m_strSrc = cszSrc;
  191. m_dwRes = RSTRRES_UNKNOWN;
  192. m_dwErr = 0;
  193. }
  194. /////////////////////////////////////////////////////////////////////////////
  195. void
  196. CRestoreMapEntry::ProcessLockedAlt()
  197. {
  198. TraceFunctEnter("CRestoreMapEntry::ProcessLockedAlt");
  199. if ( !MoveFileDelay( m_strAlt, NULL ) )
  200. m_dwRes = RSTRRES_FAIL;
  201. TraceFunctLeave();
  202. }
  203. /////////////////////////////////////////////////////////////////////////////
  204. BOOL
  205. CRestoreMapEntry::Release()
  206. {
  207. delete this;
  208. return( TRUE );
  209. }
  210. /////////////////////////////////////////////////////////////////////////////
  211. BOOL
  212. CRestoreMapEntry::ClearAccess( LPCWSTR cszPath )
  213. {
  214. (void)::SetFileAttributes( cszPath, FILE_ATTRIBUTE_NORMAL );
  215. return( TRUE );
  216. }
  217. /////////////////////////////////////////////////////////////////////////////
  218. BOOL
  219. CRestoreMapEntry::MoveFileDelay( LPCWSTR cszSrc, LPCWSTR cszDst )
  220. {
  221. TraceFunctEnter("CRestoreMapEntry::MoveFileDelay");
  222. BOOL fRet = FALSE;
  223. if ( !::MoveFileEx( cszSrc, cszDst, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING ) )
  224. {
  225. m_dwErr = ::GetLastError();
  226. s_cszErr = ::GetSysErrStr(m_dwErr);
  227. ErrorTrace(0, "::MoveFileEx() failed - %ls", s_cszErr);
  228. ErrorTrace(0, " From Src=%ls to Dst=%ls", cszSrc, cszDst);
  229. goto Exit;
  230. }
  231. fRet = TRUE;
  232. Exit:
  233. TraceFunctLeave();
  234. return( TRUE );
  235. }
  236. /////////////////////////////////////////////////////////////////////////////
  237. void
  238. CRestoreMapEntry::ProcessDependency( CRestoreOperationManager *pROMgr, DWORD dwFlags )
  239. {
  240. TraceFunctEnter("CRestoreMapEntry::ProcessDependency");
  241. CRestoreMapEntry *pEnt;
  242. if ( dwFlags & PDF_LOC )
  243. if ( pROMgr->FindDependentMapEntry( m_strSrc, TRUE, &pEnt ) )
  244. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  245. if ( dwFlags & PDF_OBJ )
  246. if ( pROMgr->FindDependentMapEntry( m_strDst, FALSE, &pEnt ) )
  247. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  248. TraceFunctLeave();
  249. }
  250. /////////////////////////////////////////////////////////////////////////////
  251. //
  252. // CRMEDirCreate
  253. //
  254. /////////////////////////////////////////////////////////////////////////////
  255. CRMEDirCreate::CRMEDirCreate( INT64 llSeq, LPCWSTR cszSrc,
  256. LPCWSTR cszShortFileName )
  257. : CRestoreMapEntry( llSeq, OPR_DIR_CREATE, cszSrc )
  258. {
  259. m_strShortFileName = cszShortFileName;
  260. }
  261. /////////////////////////////////////////////////////////////////////////////
  262. //
  263. // RSTRRES_EXISTS if directory already exists.
  264. // RSTRRES_FAIL if file of same name already exists. (BUGBUG)
  265. // RSTRRES_FAIL if CreateDirectory API fails because of any other reasons.
  266. // RSTRRES_OK if directory is created successfully.
  267. //
  268. void CRMEDirCreate::Restore( CRestoreOperationManager *pROMgr )
  269. {
  270. TraceFunctEnter("CRMEDirCreate::Restore");
  271. LPCWSTR cszSrc;
  272. DWORD dwAttr;
  273. BOOL fCollision = FALSE;
  274. cszSrc = m_strSrc;
  275. DebugTrace(0, "DirCreate: Src=%ls", cszSrc);
  276. dwAttr = ::GetFileAttributes( cszSrc );
  277. if ( dwAttr != 0xFFFFFFFF )
  278. {
  279. if ( dwAttr & FILE_ATTRIBUTE_DIRECTORY )
  280. {
  281. m_dwRes = RSTRRES_EXISTS;
  282. DebugTrace(0, "The directory already exists...");
  283. //BUGBUG - Need to copy meta data...?
  284. goto Exit;
  285. }
  286. else
  287. {
  288. // let's rename the conflicting file to an alternate name, and keep going
  289. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  290. LPCWSTR cszMount;
  291. DebugTrace(0, "Entry already exists, but is not a directory!!!");
  292. DebugTrace(0, " Src=%ls", cszSrc);
  293. if (FALSE == RenameLockedObject(cszSrc, szAlt))
  294. {
  295. ErrorTrace(0, "! RenameLockedObject");
  296. m_dwRes = RSTRRES_FAIL;
  297. goto Exit;
  298. }
  299. m_strAlt = szAlt;
  300. fCollision = TRUE;
  301. }
  302. }
  303. // The following function creates all sub directories under the
  304. // specified filename.
  305. // we will ignore the error code from this function since the
  306. // directory may be able to be created anyway.
  307. CreateBaseDirectory(cszSrc);
  308. // now create the directory
  309. if ( !::CreateDirectory( cszSrc, NULL ) )
  310. {
  311. DWORD dwErr = SRCreateSubdirectory (cszSrc, NULL); // try renaming
  312. if (dwErr != ERROR_SUCCESS)
  313. {
  314. m_dwErr = dwErr;
  315. s_cszErr = ::GetSysErrStr( m_dwErr );
  316. m_dwRes = RSTRRES_FAIL;
  317. ErrorTrace(0, "SRCreateSubdirectory failed - %ls", s_cszErr);
  318. ErrorTrace(0, " Src=%ls", cszSrc);
  319. goto Exit;
  320. }
  321. }
  322. // also set the short file name for the directory.
  323. SetShortFileName(cszSrc, m_strShortFileName);
  324. if (fCollision)
  325. {
  326. m_dwRes = RSTRRES_COLLISION;
  327. }
  328. else
  329. {
  330. m_dwRes = RSTRRES_OK;
  331. }
  332. Exit:
  333. TraceFunctLeave();
  334. }
  335. /////////////////////////////////////////////////////////////////////////////
  336. //
  337. // CRMEDirDelete
  338. //
  339. /////////////////////////////////////////////////////////////////////////////
  340. CRMEDirDelete::CRMEDirDelete( INT64 llSeq, LPCWSTR cszSrc )
  341. : CRestoreMapEntry( llSeq, OPR_DIR_DELETE, cszSrc )
  342. {
  343. }
  344. /////////////////////////////////////////////////////////////////////////////
  345. //
  346. // RSTRRES_NOTFOUND if directory does not exist.
  347. // RSTRRES_LOCKED if directory itself or one of file/dir inside is locked.
  348. // RSTRRES_IGNORE if directory is not empty and requires dependency scan.
  349. // RSTRRES_FAIL if RemoveDirectory API fails because of any other reasons.
  350. // RSTRRES_OK if directory is deleted successfully.
  351. //
  352. void CRMEDirDelete::Restore( CRestoreOperationManager *pROMgr )
  353. {
  354. TraceFunctEnter("CRMEDirDelete::Restore");
  355. LPCWSTR cszSrc;
  356. cszSrc = m_strSrc;
  357. DebugTrace(0, "DirDelete: Src=%ls", cszSrc);
  358. if ( ::GetFileAttributes( cszSrc ) == 0xFFFFFFFF )
  359. {
  360. m_dwRes = RSTRRES_NOTFOUND;
  361. DebugTrace(0, "The directory not found...");
  362. goto Exit;
  363. }
  364. // RemoveDirectory might fail if the directory is read-only.
  365. (void)::ClearFileAttribute( cszSrc, FILE_ATTRIBUTE_READONLY );
  366. // Ignore even if it fails, as delete might succeed.
  367. if ( !::RemoveDirectory( cszSrc ) )
  368. {
  369. //BUGBUG - distinguish the reason of failure...
  370. m_dwErr = ::GetLastError();
  371. s_cszErr = ::GetSysErrStr( m_dwErr );
  372. ErrorTrace(0, "::RemoveDirectory failed - %ls", s_cszErr);
  373. ErrorTrace(0, " Src=%ls", cszSrc);
  374. if ( ::IsLockedError(m_dwErr) )
  375. {
  376. ProcessDependency( pROMgr, PDF_LOC );
  377. m_dwRes = RSTRRES_LOCKED;
  378. goto Exit;
  379. }
  380. if ( m_dwErr == ERROR_DIR_NOT_EMPTY )
  381. {
  382. // Temporary Hack, just set result to RSTRRES_IGNORE to initiate
  383. // dependency scanning.
  384. m_dwRes = RSTRRES_IGNORE;
  385. }
  386. else
  387. m_dwRes = RSTRRES_FAIL;
  388. #if 0
  389. // Scan for dependency...
  390. if ( FALSE /*dependency exists*/ )
  391. {
  392. DebugTrace(0, "Conflict detected, renaming to %ls", L"xxx");
  393. // Rename to prevent conflict
  394. if ( TRUE /*rename succeeded*/ )
  395. {
  396. m_dwRes = RSTRRES_CONFLICT;
  397. }
  398. else
  399. {
  400. //BUGBUG - this will overwrite LastError from RemoveDirectory...
  401. m_dwErr = ::GetLastError();
  402. s_cszErr = ::GetSysErrStr( m_dwErr );
  403. ErrorTrace(0, "::MoveFile failed - %ls", s_cszErr);
  404. m_dwRes = RSTRRES_FAIL;
  405. }
  406. }
  407. else
  408. {
  409. m_dwRes = RSTRRES_IGNORE;
  410. }
  411. #endif
  412. goto Exit;
  413. }
  414. m_dwRes = RSTRRES_OK;
  415. Exit:
  416. TraceFunctLeave();
  417. }
  418. void CRMEDirDelete::ProcessLocked()
  419. {
  420. TraceFunctEnter("CRMEDirDelete::ProcessLocked");
  421. if ( !MoveFileDelay( m_strSrc, NULL ) )
  422. m_dwRes = RSTRRES_FAIL;
  423. TraceFunctLeave();
  424. }
  425. /////////////////////////////////////////////////////////////////////////////
  426. //
  427. // CRMEDirRename
  428. //
  429. /////////////////////////////////////////////////////////////////////////////
  430. CRMEDirRename::CRMEDirRename( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst,
  431. LPCWSTR cszShortFileName )
  432. : CRestoreMapEntry( llSeq, OPR_DIR_RENAME, cszSrc )
  433. {
  434. m_strDst = cszDst;
  435. m_strShortFileName = cszShortFileName;
  436. }
  437. /////////////////////////////////////////////////////////////////////////////
  438. //
  439. // RSTRRES_FAIL if source directory does not exist.
  440. // RSTRRES_COLLISION if target directory/file already exists.
  441. // RSTRRES_LOCKED if source directory itself or one of file/dir inside is locked.
  442. // RSTRRES_FAIL if MoveFile API fails because of any other reasons.
  443. // RSTRRES_OK if directory is renamed successfully.
  444. //
  445. // NOTE: Src and Dst are same with original operation. Which means,
  446. // restore should rename Dst to Src.
  447. //
  448. void CRMEDirRename::Restore( CRestoreOperationManager *pROMgr )
  449. {
  450. TraceFunctEnter("CRMEDirRename::Restore");
  451. LPCWSTR cszSrc, cszDst;
  452. DWORD dwAttr;
  453. CRestoreMapEntry *pEntNext;
  454. BOOL fCollision = FALSE;
  455. cszSrc = m_strSrc;
  456. cszDst = m_strDst;
  457. DebugTrace(0, "DirRename: Src=%ls, Dst=%ls", cszSrc, cszDst);
  458. if ( ::GetFileAttributes( cszDst ) == 0xFFFFFFFF )
  459. {
  460. m_dwErr = ERROR_NOT_FOUND;
  461. m_dwRes = RSTRRES_FAIL;
  462. ErrorTrace(0, "The current directory not found...");
  463. ErrorTrace(0, " Dst=%ls", cszDst);
  464. goto Exit;
  465. }
  466. dwAttr = ::GetFileAttributes( cszSrc );
  467. if ( dwAttr != 0xFFFFFFFF )
  468. {
  469. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  470. DebugTrace(0, "Entry already exists, but is not a directory!!!");
  471. if (FALSE == RenameLockedObject(cszSrc, szAlt))
  472. {
  473. ErrorTrace(0, "! RenameLockedObject");
  474. m_dwRes = RSTRRES_FAIL;
  475. goto Exit;
  476. }
  477. m_strAlt = szAlt;
  478. fCollision = TRUE;
  479. }
  480. // Check the next entry to see if this is a folder creation using
  481. // explorer. Note, only the immediately next entry will be checked,
  482. // to prevent any confusion or complications due to a dependency.
  483. if ( pROMgr->GetNextMapEntry( &pEntNext ) )
  484. if ( pEntNext->GetOpCode() == OPR_DIR_DELETE )
  485. if ( ::StrCmpI( cszSrc, pEntNext->GetPath1() ) == 0 )
  486. {
  487. // Found match, just update path name of the next entry...
  488. pEntNext->UpdateSrc( cszDst );
  489. m_dwRes = RSTRRES_IGNORE;
  490. goto Exit;
  491. }
  492. if ( !::MoveFile( cszDst, cszSrc ) )
  493. {
  494. m_dwErr = ::GetLastError();
  495. s_cszErr = ::GetSysErrStr( m_dwErr );
  496. ErrorTrace(0, "::MoveFile failed - %ls", s_cszErr);
  497. ErrorTrace(0, " From Dst=%ls to Src=%ls", cszDst, cszSrc);
  498. if ( ::IsLockedError(m_dwErr) )
  499. {
  500. ProcessDependency( pROMgr, PDF_BOTH );
  501. m_dwRes = RSTRRES_LOCKED;
  502. }
  503. else
  504. m_dwRes = RSTRRES_FAIL;
  505. goto Exit;
  506. }
  507. // also set the short file name for the directory.
  508. SetShortFileName(cszSrc, m_strShortFileName);
  509. if (fCollision)
  510. m_dwRes = RSTRRES_COLLISION;
  511. else
  512. m_dwRes = RSTRRES_OK;
  513. Exit:
  514. TraceFunctLeave();
  515. }
  516. void CRMEDirRename::ProcessLocked()
  517. {
  518. TraceFunctEnter("CRMEDirRename::ProcessLocked");
  519. if ( !MoveFileDelay( m_strDst, m_strSrc ) )
  520. m_dwRes = RSTRRES_FAIL;
  521. TraceFunctLeave();
  522. }
  523. /////////////////////////////////////////////////////////////////////////////
  524. //
  525. // CRMEFileCreate
  526. //
  527. /////////////////////////////////////////////////////////////////////////////
  528. CRMEFileCreate::CRMEFileCreate( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszTmp,
  529. LPCWSTR cszShortFileName)
  530. : CRestoreMapEntry( llSeq, OPR_FILE_ADD, cszSrc )
  531. {
  532. m_strTmp = cszTmp;
  533. m_strShortFileName = cszShortFileName;
  534. }
  535. /////////////////////////////////////////////////////////////////////////////
  536. //
  537. // RSTRRES_OPTIMIZED if filter didn't make temp file for optimization purpose.
  538. // RSTRRES_FAIL if SRCopyFile fails because of any other reasons.
  539. // RSTRRES_OK if file is created successfully.
  540. //
  541. void CRMEFileCreate::Restore( CRestoreOperationManager *pROMgr )
  542. {
  543. TraceFunctEnter("CRMEFileCreate::Restore");
  544. LPCWSTR cszSrc, cszTmp;
  545. DWORD dwRet;
  546. BOOL fCollision = FALSE;
  547. DWORD dwAttr;
  548. // If filter didn't make temp file because there's corresponding
  549. // file delete entry, simply ignore this entry.
  550. if ( m_strTmp.Length() == 0 )
  551. {
  552. m_dwRes = RSTRRES_OPTIMIZED;
  553. goto Exit;
  554. }
  555. cszSrc = m_strSrc;
  556. cszTmp = m_strTmp;
  557. DebugTrace(0, "FileCreate: Src=%ls", cszSrc);
  558. DebugTrace(0, "FileCreate: Tmp=%ls", cszTmp);
  559. // if the file already exists, rename existing and
  560. // continue - renamed file will be reported on result page
  561. dwAttr = ::GetFileAttributes( cszSrc );
  562. if ( dwAttr != 0xFFFFFFFF )
  563. {
  564. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  565. DebugTrace(0, "Entry already exists!");
  566. if (FALSE == RenameLockedObject(cszSrc, szAlt))
  567. {
  568. ErrorTrace(0, "! RenameLockedObject");
  569. m_dwRes = RSTRRES_FAIL;
  570. goto Exit;
  571. }
  572. m_strAlt = szAlt;
  573. fCollision = TRUE;
  574. }
  575. // create the parent directory if it does not exist
  576. CreateBaseDirectory(cszSrc);
  577. dwRet = ::SRCopyFile( cszTmp, cszSrc );
  578. if ( dwRet != ERROR_SUCCESS )
  579. {
  580. m_dwRes = RSTRRES_FAIL;
  581. m_dwErr = dwRet;
  582. goto Exit;
  583. }
  584. // also set the short file name for the File
  585. SetShortFileName(cszSrc, m_strShortFileName);
  586. if (fCollision)
  587. m_dwRes = RSTRRES_COLLISION;
  588. else
  589. m_dwRes = RSTRRES_OK;
  590. Exit:
  591. TraceFunctLeave();
  592. }
  593. void CRMEFileCreate::ProcessLocked()
  594. {
  595. TraceFunctEnter("CRMEFileCreate::ProcessLocked");
  596. LPCWSTR cszSrc, cszTmp;
  597. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  598. DWORD dwErr;
  599. cszSrc = m_strSrc;
  600. cszTmp = m_strTmp;
  601. DebugTrace(0, "Processlocked: Src=%ls", cszSrc);
  602. DebugTrace(0, "Processlocked: Tmp=%ls", cszTmp);
  603. if ( !::SRGetAltFileName( cszSrc, szAlt ) )
  604. goto Exit;
  605. DebugTrace(0, "Processlocked: Alt=%ls", szAlt);
  606. dwErr = ::SRCopyFile( cszTmp, szAlt );
  607. if ( dwErr != ERROR_SUCCESS )
  608. {
  609. goto Exit;
  610. }
  611. if ( !MoveFileDelay( szAlt, cszSrc ) )
  612. m_dwRes = RSTRRES_FAIL;
  613. Exit:
  614. TraceFunctLeave();
  615. }
  616. /////////////////////////////////////////////////////////////////////////////
  617. //
  618. // CRMEFileDelete
  619. //
  620. /////////////////////////////////////////////////////////////////////////////
  621. CRMEFileDelete::CRMEFileDelete( INT64 llSeq, LPCWSTR cszSrc )
  622. : CRestoreMapEntry( llSeq, OPR_FILE_DELETE, cszSrc )
  623. {
  624. }
  625. /////////////////////////////////////////////////////////////////////////////
  626. //
  627. // RSTRRES_NOTFOUND if file does not exist.
  628. // RSTRRES_LOCKED_ALT if file is locked but can be renamed.
  629. // RSTRRES_LOCKED if file is locked and cannot be renamed.
  630. // RSTRRES_FAIL if DeleteFile API fails because of any other reasons.
  631. // RSTRRES_OK if file is deleted successfully.
  632. //
  633. void CRMEFileDelete::Restore( CRestoreOperationManager *pROMgr )
  634. {
  635. TraceFunctEnter("CRMEFileDelete::Restore");
  636. LPCWSTR cszSrc;
  637. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  638. cszSrc = m_strSrc;
  639. DebugTrace(0, "FileDelete: Src=%ls", cszSrc);
  640. if ( ::GetFileAttributes( cszSrc ) == 0xFFFFFFFF )
  641. {
  642. m_dwRes = RSTRRES_NOTFOUND;
  643. DebugTrace(0, "The file not found...");
  644. goto Exit;
  645. }
  646. (void)::ClearFileAttribute( cszSrc, FILE_ATTRIBUTE_READONLY );
  647. // Ignore even if it fails, because delete might succeed.
  648. if ( !::DeleteFile( cszSrc ) )
  649. {
  650. m_dwErr = ::GetLastError();
  651. s_cszErr = ::GetSysErrStr( m_dwErr );
  652. ErrorTrace(0, "::DeleteFile failed - '%ls'", s_cszErr);
  653. if ( ::IsLockedError(m_dwErr) )
  654. {
  655. if ( ::RenameLockedObject( cszSrc, szAlt ) )
  656. {
  657. m_strAlt = szAlt;
  658. m_dwRes = RSTRRES_LOCKED_ALT;
  659. }
  660. else
  661. {
  662. CRestoreMapEntry *pEnt;
  663. // check for any dependent operations that will fail
  664. // since this restore operation cannot proceed.
  665. if ( pROMgr->FindDependentMapEntry( m_strSrc, FALSE, &pEnt ) )
  666. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  667. m_dwRes = RSTRRES_LOCKED;
  668. }
  669. }
  670. else
  671. m_dwRes = RSTRRES_FAIL;
  672. goto Exit;
  673. }
  674. m_dwRes = RSTRRES_OK;
  675. Exit:
  676. TraceFunctLeave();
  677. }
  678. void CRMEFileDelete::ProcessLocked()
  679. {
  680. TraceFunctEnter("CRMEFileDelete::ProcessLocked");
  681. if ( !MoveFileDelay( m_strSrc, NULL ) )
  682. m_dwRes = RSTRRES_FAIL;
  683. TraceFunctLeave();
  684. }
  685. /////////////////////////////////////////////////////////////////////////////
  686. //
  687. // CRMEFileModify
  688. //
  689. /////////////////////////////////////////////////////////////////////////////
  690. CRMEFileModify::CRMEFileModify( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszTmp )
  691. : CRestoreMapEntry( llSeq, OPR_FILE_MODIFY, cszSrc )
  692. {
  693. m_strTmp = cszTmp;
  694. }
  695. /////////////////////////////////////////////////////////////////////////////
  696. //
  697. // RSTRRES_LOCKED_ALT if target file is locked but can be renamed.
  698. // RSTRRES_FAIL if target file is renamed but SRCopyFile still fails.
  699. // RSTRRES_LOCKED if target file is locked and cannot be renamed.
  700. // RSTRRES_FAIL if SRCopyFile fails because of any other reasons.
  701. // RSTRRES_OK if file is updated successfully.
  702. //
  703. void CRMEFileModify::Restore( CRestoreOperationManager *pROMgr )
  704. {
  705. TraceFunctEnter("CRMEFileModify::Restore");
  706. LPCWSTR cszSrc, cszTmp;
  707. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  708. cszSrc = m_strSrc;
  709. cszTmp = m_strTmp;
  710. DebugTrace(0, "FileModify: Src=%ls", cszSrc);
  711. DebugTrace(0, "FileModify: Tmp=%ls", cszTmp);
  712. // create the parent directory if it does not exist
  713. CreateBaseDirectory(cszSrc);
  714. m_dwErr = ::SRCopyFile( cszTmp, cszSrc );
  715. if ( m_dwErr != ERROR_SUCCESS )
  716. {
  717. if ( ::IsLockedError(m_dwErr) )
  718. {
  719. if ( ::RenameLockedObject( cszSrc, szAlt ) )
  720. {
  721. m_dwErr = ::SRCopyFile( cszTmp, cszSrc );
  722. if ( m_dwErr == ERROR_SUCCESS )
  723. {
  724. m_strAlt = szAlt;
  725. m_dwRes = RSTRRES_LOCKED_ALT;
  726. }
  727. else
  728. m_dwRes = RSTRRES_FAIL;
  729. }
  730. else
  731. {
  732. CRestoreMapEntry *pEnt;
  733. // Copy Tmp to Alt, we already have szAlt path name.
  734. m_dwErr = ::SRCopyFile( cszTmp, szAlt );
  735. if ( m_dwErr != ERROR_SUCCESS )
  736. {
  737. m_dwRes = RSTRRES_FAIL;
  738. goto Exit;
  739. }
  740. m_strAlt = szAlt;
  741. // check for any dependent operations that will fail
  742. // since this restore operation cannot proceed.
  743. if ( pROMgr->FindDependentMapEntry( m_strSrc, TRUE, &pEnt ) )
  744. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  745. m_dwRes = RSTRRES_LOCKED;
  746. }
  747. }
  748. else
  749. m_dwRes = RSTRRES_FAIL;
  750. goto Exit;
  751. }
  752. m_dwRes = RSTRRES_OK;
  753. Exit:
  754. TraceFunctLeave();
  755. }
  756. void CRMEFileModify::ProcessLocked()
  757. {
  758. TraceFunctEnter("CRMEFileModify::ProcessLocked");
  759. // the problem here is that the file m_strAlt may not exist if
  760. // the FileModify was triggered as a dependency of another
  761. // operation (can only be a rename). However, restore fails
  762. // before getting to this point - so this bug will be fixed for
  763. // longhorn unless reported by a customer.
  764. if ( !MoveFileDelay( m_strAlt, m_strSrc ) )
  765. m_dwRes = RSTRRES_FAIL;
  766. TraceFunctLeave();
  767. }
  768. /////////////////////////////////////////////////////////////////////////////
  769. //
  770. // CRMEFileRename
  771. //
  772. /////////////////////////////////////////////////////////////////////////////
  773. CRMEFileRename::CRMEFileRename( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst,
  774. LPCWSTR cszShortFileName)
  775. : CRestoreMapEntry( llSeq, OPR_FILE_RENAME, cszSrc )
  776. {
  777. m_strDst = cszDst;
  778. m_strShortFileName = cszShortFileName;
  779. }
  780. /////////////////////////////////////////////////////////////////////////////
  781. //
  782. // RSTRRES_FAIL if source file does not exist.
  783. // RSTRRES_COLLISION if target file/directory already exists.
  784. // RSTRRES_LOCKED if source file is locked.
  785. // RSTRRES_FAIL if MoveFile API fails because of any other reasons.
  786. // RSTRRES_OK if file is renamed successfully.
  787. //
  788. // NOTE: Src and Dst are same with original operation. Which means,
  789. // restore should rename Dst to Src.
  790. //
  791. void CRMEFileRename::Restore( CRestoreOperationManager *pROMgr )
  792. {
  793. TraceFunctEnter("CRMEFileRename::Restore");
  794. LPCWSTR cszSrc, cszDst;
  795. DWORD dwAttr;
  796. BOOL fCollision = FALSE;
  797. WCHAR szAlt[SR_MAX_FILENAME_LENGTH];
  798. cszSrc = m_strSrc;
  799. cszDst = m_strDst;
  800. DebugTrace(0, "FileRename: Src=%ls", cszSrc);
  801. DebugTrace(0, "FileRename: Dst=%ls", cszDst);
  802. if ( ::GetFileAttributes( cszDst ) == 0xFFFFFFFF )
  803. {
  804. m_dwErr = ERROR_NOT_FOUND;
  805. m_dwRes = RSTRRES_FAIL;
  806. ErrorTrace(0, "The current file not found...");
  807. ErrorTrace(0, " Dst=%ls", cszDst);
  808. goto Exit;
  809. }
  810. //
  811. // if source already exists, then need to get it out of the way
  812. //
  813. if ( ::StrCmpI( cszSrc, cszDst ) != 0 )
  814. {
  815. dwAttr = ::GetFileAttributes( cszSrc );
  816. if ( dwAttr != 0xFFFFFFFF )
  817. {
  818. DebugTrace(0, "The target file already exists...");
  819. //
  820. // take care of the case where source has same name as destination's short filename
  821. // we don't want to inadvertently shoot ourselves in the foot
  822. // so we rename it to an alternate name, and rename the alternate name to the original source
  823. //
  824. WIN32_FIND_DATA wfd;
  825. HANDLE hFile = INVALID_HANDLE_VALUE;
  826. BOOL fRenameAlt = FALSE;
  827. if ((hFile = FindFirstFile(cszDst, &wfd)) != INVALID_HANDLE_VALUE)
  828. {
  829. if ( ::StrCmpI(wfd.cAlternateFileName, PathFindFileName(cszSrc)) == 0)
  830. {
  831. fRenameAlt = TRUE;
  832. trace(0, "Source filename same as dest's shortname");
  833. // so construct a filename that will surely have a different short
  834. // filename than the source
  835. // prefix the unique name generated by restore with "sr" so that
  836. // this will get a different shortname
  837. WCHAR szModifiedDst[SR_MAX_FILENAME_LENGTH];
  838. lstrcpy(szModifiedDst, cszDst);
  839. LPWSTR pszDstPath = wcsrchr(szModifiedDst, L'\\');
  840. if (pszDstPath)
  841. {
  842. *pszDstPath = L'\0';
  843. }
  844. lstrcat(szModifiedDst, L"\\sr");
  845. lstrcat(szModifiedDst, PathFindFileName(cszDst));
  846. if (FALSE == SRGetAltFileName(szModifiedDst, szAlt))
  847. {
  848. ErrorTrace(0, "! SRGetAltFileName");
  849. m_dwRes = RSTRRES_FAIL;
  850. goto Exit;
  851. }
  852. trace(0, "szAlt for unique shortname: %S", szAlt);
  853. // now rename the original destination to this
  854. if (FALSE == MoveFile(cszDst, szAlt))
  855. {
  856. m_dwErr = GetLastError();
  857. ErrorTrace(0, "! MoveFile %ld: %S to %S", m_dwErr, cszDst, szAlt);
  858. m_dwRes = RSTRRES_FAIL;
  859. goto Exit;
  860. }
  861. // and setup this to be renamed to the original source
  862. cszDst = szAlt;
  863. fRenameAlt = TRUE;
  864. }
  865. FindClose(hFile);
  866. }
  867. else
  868. {
  869. trace(0, "! FindFirstFile : %ld", GetLastError());
  870. }
  871. if (! fRenameAlt)
  872. {
  873. if (FALSE == RenameLockedObject(cszSrc, szAlt))
  874. {
  875. ErrorTrace(0, "! RenameLockedObject");
  876. m_dwErr= ERROR_ALREADY_EXISTS;
  877. ProcessDependency( pROMgr, PDF_BOTH );
  878. m_dwRes = RSTRRES_LOCKED;
  879. goto Exit;
  880. }
  881. m_strAlt = szAlt;
  882. fCollision = TRUE;
  883. }
  884. }
  885. }
  886. // create the parent directory if it does not exist
  887. CreateBaseDirectory(cszSrc);
  888. if ( !::MoveFile( cszDst, cszSrc ) )
  889. {
  890. m_dwErr = ::GetLastError();
  891. s_cszErr = ::GetSysErrStr( m_dwErr );
  892. ErrorTrace(0, "::MoveFile failed - %ls", s_cszErr);
  893. ErrorTrace(0, " From Dst=%ls to Src=%ls", cszDst, cszSrc);
  894. if ( ::IsLockedError(m_dwErr) )
  895. {
  896. ProcessDependency( pROMgr, PDF_BOTH );
  897. m_dwRes = RSTRRES_LOCKED;
  898. }
  899. else
  900. m_dwRes = RSTRRES_FAIL;
  901. goto Exit;
  902. }
  903. // also set the short file name for the file
  904. SetShortFileName(cszSrc, m_strShortFileName);
  905. if (fCollision)
  906. m_dwRes = RSTRRES_COLLISION;
  907. else
  908. m_dwRes = RSTRRES_OK;
  909. Exit:
  910. TraceFunctLeave();
  911. }
  912. void CRMEFileRename::ProcessLocked()
  913. {
  914. TraceFunctEnter("CRMEFileRename::ProcessLocked");
  915. if ( !MoveFileDelay( m_strDst, m_strSrc ) )
  916. m_dwRes = RSTRRES_FAIL;
  917. TraceFunctLeave();
  918. }
  919. // This takes a filename of the type
  920. // \device\harddiskvolume1\system vol info\_restore{GUID}\rp1\s001.acl
  921. // and converts it to
  922. // \rp1\s001.acl
  923. void GetDSRelativeFileName(IN const WCHAR * pszFileName,
  924. OUT WCHAR * pszRelativeFileName )
  925. {
  926. TraceFunctEnter("GetDSRelativeFileName");
  927. WCHAR szFileNameCopy[MAX_PATH];
  928. WCHAR * pszCurrentPosition;
  929. WCHAR * pszLastSlash;
  930. DebugTrace(0, "Acl file is %S", pszFileName);
  931. // initially copy input into the output buffer. This is what will
  932. // be returned if there is an unexpected error
  933. lstrcpy(pszRelativeFileName, pszFileName);
  934. // copy the file into a temporary buffer
  935. lstrcpy(szFileNameCopy, pszRelativeFileName );
  936. // Look for the trailing \
  937. pszCurrentPosition= wcsrchr( szFileNameCopy, L'\\' );
  938. // bail if no \ was found or if we are at the start of the string
  939. if ( (NULL == pszCurrentPosition) ||
  940. (pszCurrentPosition == szFileNameCopy))
  941. {
  942. DebugTrace(0, "no \\ in the string");
  943. _ASSERT(0);
  944. goto cleanup;
  945. }
  946. pszLastSlash = pszCurrentPosition;
  947. // null terminate at the last slash so that we can find the next slash
  948. * pszLastSlash = L'\0';
  949. // Look for the next trailing \
  950. pszCurrentPosition= wcsrchr( szFileNameCopy, L'\\' );
  951. // bail if no \ was found or if we are at the start of the string
  952. if (NULL == pszCurrentPosition)
  953. {
  954. DebugTrace(0, "no second \\ in the string");
  955. _ASSERT(0);
  956. goto cleanup;
  957. }
  958. // restore the last slash
  959. * pszLastSlash = L'\\';
  960. // we have the relative path
  961. lstrcpy(pszRelativeFileName,pszCurrentPosition);
  962. cleanup:
  963. TraceFunctLeave();
  964. return;
  965. }
  966. /////////////////////////////////////////////////////////////////////////////
  967. //
  968. // CRMESetAcl
  969. //
  970. /////////////////////////////////////////////////////////////////////////////
  971. CRMESetAcl::CRMESetAcl( INT64 llSeq, LPCWSTR cszSrc, LPBYTE pbAcl, DWORD cbAcl, BOOL fInline, LPCWSTR cszDSPath )
  972. : CRestoreMapEntry( llSeq, OPR_SETACL, cszSrc )
  973. {
  974. if ( fInline )
  975. {
  976. m_cbAcl = cbAcl;
  977. m_pbAcl = new BYTE[cbAcl];
  978. if ( m_pbAcl != NULL )
  979. ::CopyMemory( m_pbAcl, pbAcl, cbAcl );
  980. }
  981. else
  982. {
  983. WCHAR szAclPath[MAX_PATH];
  984. WCHAR szRelativeAclFile[MAX_PATH];
  985. // in this case the path that the filter has given us looks like
  986. // \device\harddiskvolume1\system vol info\_restore{GUID}\rp1\s001.acl
  987. //
  988. // We need to change this file name to \rp1\s001.acl so that we
  989. // can prepend the DS path to this.
  990. GetDSRelativeFileName((LPCWSTR)pbAcl, szRelativeAclFile );
  991. ::lstrcpy( szAclPath, cszDSPath );
  992. ::PathAppend( szAclPath, (LPCWSTR)szRelativeAclFile);
  993. m_strAclPath = szAclPath;
  994. m_pbAcl = NULL;
  995. }
  996. }
  997. /*
  998. CRMESetAcl::CRMESetAcl( LPCWSTR cszSrc, LPBYTE pbAcl, DWORD cbAcl )
  999. : CRestoreMapEntry( OPR_SETACL, cszSrc )
  1000. {
  1001. m_cbAcl = cbAcl;
  1002. m_pbAcl = new BYTE[cbAcl];
  1003. if ( m_pbAcl != NULL )
  1004. ::CopyMemory( m_pbAcl, pbAcl, cbAcl );
  1005. }
  1006. CRMESetAcl::CRMESetAcl( LPCWSTR cszSrc, LPCWSTR cszAcl )
  1007. : CRestoreMapEntry( OPR_SETACL, cszSrc )
  1008. {
  1009. m_strAclPath = cszAcl;
  1010. m_pbAcl = NULL;
  1011. }
  1012. */
  1013. CRMESetAcl::~CRMESetAcl()
  1014. {
  1015. SAFE_DEL_ARRAY(m_pbAcl);
  1016. }
  1017. /////////////////////////////////////////////////////////////////////////////
  1018. void CRMESetAcl::Restore( CRestoreOperationManager* )
  1019. {
  1020. TraceFunctEnter("CRMESetAcl::Restore");
  1021. LPCWSTR cszErr;
  1022. LPCWSTR cszSrc, cszAcl;
  1023. SECURITY_INFORMATION SecurityInformation;
  1024. PISECURITY_DESCRIPTOR_RELATIVE pRelative;
  1025. cszSrc = m_strSrc;
  1026. cszAcl = m_strAclPath;
  1027. DebugTrace(0, "SetAcl: Src=%ls, path=%ls, cbAcl=%d", cszSrc, cszAcl, m_cbAcl);
  1028. // read content of Acl if it's not inline
  1029. if ( m_strAclPath.Length() > 0 )
  1030. {
  1031. HANDLE hfAcl;
  1032. DWORD dwRes;
  1033. hfAcl = ::CreateFile( cszAcl, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
  1034. if ( hfAcl == INVALID_HANDLE_VALUE )
  1035. {
  1036. m_dwErr = ::GetLastError();
  1037. m_dwRes = RSTRRES_FAIL;
  1038. s_cszErr = ::GetSysErrStr( m_dwErr );
  1039. ErrorTrace(0, "::CreateFile failed - %ls", s_cszErr);
  1040. ErrorTrace(0, " Acl=%ls", cszAcl);
  1041. goto Exit;
  1042. }
  1043. m_cbAcl = ::GetFileSize( hfAcl, NULL );
  1044. if ( m_cbAcl == 0xFFFFFFFF )
  1045. {
  1046. m_dwErr = ::GetLastError();
  1047. m_dwRes = RSTRRES_FAIL;
  1048. s_cszErr = ::GetSysErrStr( m_dwErr );
  1049. ErrorTrace(0, "::GetFileSize failed - %ls", s_cszErr);
  1050. ::CloseHandle( hfAcl );
  1051. goto Exit;
  1052. }
  1053. m_pbAcl = new BYTE[m_cbAcl];
  1054. if ( m_pbAcl == NULL )
  1055. {
  1056. m_dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1057. m_dwRes = RSTRRES_FAIL;
  1058. FatalTrace(0, "Insufficient memory...");
  1059. ::CloseHandle( hfAcl );
  1060. goto Exit;
  1061. }
  1062. if ( !::ReadFile( hfAcl, m_pbAcl, m_cbAcl, &dwRes, NULL ) )
  1063. {
  1064. m_dwErr = ::GetLastError();
  1065. m_dwRes = RSTRRES_FAIL;
  1066. s_cszErr = ::GetSysErrStr( m_dwErr );
  1067. ErrorTrace(0, "::ReadFile failed - %ls", s_cszErr);
  1068. ::CloseHandle( hfAcl );
  1069. goto Exit;
  1070. }
  1071. ::CloseHandle( hfAcl );
  1072. }
  1073. if ( m_pbAcl == NULL || m_cbAcl == 0 )
  1074. {
  1075. m_dwErr = ERROR_INTERNAL_ERROR;
  1076. m_dwRes = RSTRRES_FAIL;
  1077. ErrorTrace(0, "Null ACL...");
  1078. goto Exit;
  1079. }
  1080. (void)::TakeOwnership( cszSrc, FALSE );
  1081. // Ignore any error because taking ownership might not be necessary.
  1082. //
  1083. // set the security info flags according to the data we have stored
  1084. // in the self-relative sd.
  1085. //
  1086. pRelative = (PISECURITY_DESCRIPTOR_RELATIVE)m_pbAcl;
  1087. if ((pRelative->Revision != SECURITY_DESCRIPTOR_REVISION) ||
  1088. ((pRelative->Control & SE_SELF_RELATIVE) != SE_SELF_RELATIVE))
  1089. {
  1090. m_dwErr = ERROR_INTERNAL_ERROR;
  1091. m_dwRes = RSTRRES_FAIL;
  1092. ErrorTrace(0, "BAD SD FORMAT...");
  1093. goto Exit;
  1094. }
  1095. //
  1096. // paulmcd: 1/24/01
  1097. // put all four flags on. this way we always blast all four there.
  1098. // this will not create the exact same SD on the file, as we
  1099. // might have an SE_SACL_PRESENT control flag, but no SACL, but
  1100. // it will always create the semantically equivelant SD and will
  1101. // delete anything that should not be there.
  1102. //
  1103. SecurityInformation = OWNER_SECURITY_INFORMATION
  1104. |GROUP_SECURITY_INFORMATION
  1105. |DACL_SECURITY_INFORMATION
  1106. |SACL_SECURITY_INFORMATION;
  1107. //
  1108. // paulmcd: copied from base\win32\client\backup.c
  1109. //
  1110. // If the security descriptor has AUTO_INHERITED set,
  1111. // set the appropriate REQ bits.
  1112. //
  1113. if (pRelative->Control & SE_DACL_AUTO_INHERITED) {
  1114. pRelative->Control |= SE_DACL_AUTO_INHERIT_REQ;
  1115. }
  1116. if (pRelative->Control & SE_SACL_AUTO_INHERITED) {
  1117. pRelative->Control |= SE_SACL_AUTO_INHERIT_REQ;
  1118. }
  1119. if ( !::SetFileSecurity( cszSrc,
  1120. SecurityInformation,
  1121. (PSECURITY_DESCRIPTOR)m_pbAcl ) )
  1122. {
  1123. m_dwErr = ::GetLastError();
  1124. m_dwRes = RSTRRES_FAIL;
  1125. s_cszErr = ::GetSysErrStr( m_dwErr );
  1126. ErrorTrace(0, "::SetFileSecurity failed - %ls", s_cszErr);
  1127. ErrorTrace(0, " Src=%ls", cszSrc);
  1128. goto Exit;
  1129. }
  1130. m_dwRes = RSTRRES_OK;
  1131. Exit:
  1132. // delete Acl if it's not inline
  1133. if ( m_strAclPath.Length() > 0 )
  1134. SAFE_DEL_ARRAY(m_pbAcl);
  1135. TraceFunctLeave();
  1136. }
  1137. /////////////////////////////////////////////////////////////////////////////
  1138. //
  1139. // CRMESetAttrib
  1140. //
  1141. /////////////////////////////////////////////////////////////////////////////
  1142. CRMESetAttrib::CRMESetAttrib( INT64 llSeq, LPCWSTR cszSrc, DWORD dwAttr )
  1143. : CRestoreMapEntry( llSeq, OPR_SETATTRIB, cszSrc )
  1144. {
  1145. m_dwAttr = dwAttr;
  1146. }
  1147. /////////////////////////////////////////////////////////////////////////////
  1148. void CRMESetAttrib::Restore( CRestoreOperationManager* )
  1149. {
  1150. TraceFunctEnter("CRMESetAttrib::Restore");
  1151. LPCWSTR cszSrc;
  1152. cszSrc = m_strSrc;
  1153. DebugTrace(0, "SetAttrib: Src=%ls, Attr=%08X", cszSrc, m_dwAttr);
  1154. if ( !::SetFileAttributes( cszSrc, m_dwAttr ) )
  1155. {
  1156. m_dwErr = ::GetLastError();
  1157. m_dwRes = RSTRRES_IGNORE;
  1158. s_cszErr = ::GetSysErrStr( m_dwErr );
  1159. ErrorTrace(0, "::SetFileAttributes failed - %ls", s_cszErr);
  1160. ErrorTrace(0, " Src=%ls, Attr=%08X", cszSrc, m_dwAttr);
  1161. goto Exit;
  1162. }
  1163. m_dwRes = RSTRRES_OK;
  1164. Exit:
  1165. TraceFunctLeave();
  1166. }
  1167. /////////////////////////////////////////////////////////////////////////////
  1168. //
  1169. // CRMEMountDelete
  1170. //
  1171. /////////////////////////////////////////////////////////////////////////////
  1172. CRMEMountDelete::CRMEMountDelete( INT64 llSeq, LPCWSTR cszSrc )
  1173. : CRestoreMapEntry( llSeq, SrEventMountDelete, cszSrc )
  1174. {
  1175. }
  1176. /////////////////////////////////////////////////////////////////////////////
  1177. void CRMEMountDelete::Restore( CRestoreOperationManager* )
  1178. {
  1179. TraceFunctEnter("CRMEMountDelete::Restore");
  1180. WCHAR * cszSrc;
  1181. DWORD dwBufReqd;
  1182. // allocate space for the buffer since we have to append \\ to
  1183. // the mount directory. Extra chars are for the trailing \\ and
  1184. // the \0
  1185. dwBufReqd = (lstrlen(m_strSrc) + 5) * sizeof(WCHAR);
  1186. cszSrc = (WCHAR *) alloca(dwBufReqd);
  1187. if (NULL == cszSrc)
  1188. {
  1189. ErrorTrace(0, "alloca for size %d failed", dwBufReqd);
  1190. m_dwRes = RSTRRES_FAIL;
  1191. goto Exit;
  1192. }
  1193. lstrcpy(cszSrc, m_strSrc);
  1194. if (cszSrc[lstrlen(cszSrc) - 1] != L'\\')
  1195. {
  1196. wcscat(cszSrc, L"\\");
  1197. }
  1198. DebugTrace(0, "MountDelete: Src=%S", cszSrc);
  1199. if ( FALSE == DoesDirExist( cszSrc ) )
  1200. {
  1201. m_dwRes = RSTRRES_NOTFOUND;
  1202. DebugTrace(0, "The file not found...");
  1203. goto Exit;
  1204. }
  1205. (void)::ClearFileAttribute( cszSrc, FILE_ATTRIBUTE_READONLY );
  1206. // Ignore even if it fails, because delete might succeed.
  1207. if ( !::DeleteVolumeMountPoint(cszSrc))
  1208. {
  1209. m_dwErr = ::GetLastError();
  1210. // we can ignore this error for restore purposes
  1211. m_dwRes = RSTRRES_IGNORE;
  1212. s_cszErr = ::GetSysErrStr( m_dwErr );
  1213. ErrorTrace(0, "::DeleteVolumeMountPoint failed - '%ls'", s_cszErr);
  1214. goto Exit;
  1215. }
  1216. m_dwRes = RSTRRES_OK;
  1217. Exit:
  1218. TraceFunctLeave();
  1219. }
  1220. /////////////////////////////////////////////////////////////////////////////
  1221. //
  1222. // CRMEMountCreate
  1223. //
  1224. /////////////////////////////////////////////////////////////////////////////
  1225. CRMEMountCreate::CRMEMountCreate( INT64 llSeq, LPCWSTR cszSrc, LPCWSTR cszDst)
  1226. : CRestoreMapEntry( llSeq, SrEventMountCreate, cszSrc )
  1227. {
  1228. m_strDst = cszDst;
  1229. }
  1230. /////////////////////////////////////////////////////////////////////////////
  1231. void CRMEMountCreate::Restore( CRestoreOperationManager* )
  1232. {
  1233. TraceFunctEnter("CRMEMountCreate::Restore");
  1234. WCHAR * cszSrc;
  1235. WCHAR * cszVolumeName;
  1236. DWORD dwBufReqd;
  1237. // allocate space for the buffer since we have to append \\ to
  1238. // the mount directory. Extra chars are for the trailing \\ and
  1239. // the \0
  1240. dwBufReqd = (lstrlen(m_strSrc) + 5) * sizeof(WCHAR);
  1241. cszSrc = (WCHAR *) alloca(dwBufReqd);
  1242. if (NULL == cszSrc)
  1243. {
  1244. ErrorTrace(0, "alloca for size %d failed", dwBufReqd);
  1245. m_dwRes = RSTRRES_FAIL;
  1246. goto Exit;
  1247. }
  1248. lstrcpy(cszSrc, m_strSrc);
  1249. if (cszSrc[lstrlen(cszSrc) - 1] != L'\\')
  1250. {
  1251. wcscat(cszSrc, L"\\");
  1252. }
  1253. // allocate space for the volume name since we have to append \\ to
  1254. // the volume name. Extra chars are for the trailing \\ and
  1255. // the \0
  1256. dwBufReqd = (lstrlen(m_strDst) + 5) * sizeof(WCHAR);
  1257. cszVolumeName = (WCHAR *) alloca(dwBufReqd);
  1258. if (NULL == cszVolumeName)
  1259. {
  1260. ErrorTrace(0, "alloca for size %d failed", dwBufReqd);
  1261. m_dwRes = RSTRRES_FAIL;
  1262. goto Exit;
  1263. }
  1264. lstrcpy(cszVolumeName, m_strDst);
  1265. if (cszVolumeName[lstrlen(cszVolumeName) - 1] != L'\\')
  1266. {
  1267. wcscat(cszVolumeName, L"\\");
  1268. }
  1269. DebugTrace(0, "MountDelete: Src=%S, Volume Name=%S", cszSrc,cszVolumeName);
  1270. if ( FALSE == DoesDirExist( cszSrc ) )
  1271. {
  1272. // try to create the directory if it does not exist
  1273. if (FALSE ==CreateDirectory( cszSrc, // directory name
  1274. NULL)) // SD
  1275. {
  1276. m_dwErr = ::GetLastError();
  1277. m_dwRes = RSTRRES_FAIL;
  1278. s_cszErr = ::GetSysErrStr( m_dwErr );
  1279. ErrorTrace(0, "CreateDirectory failed %S", s_cszErr);
  1280. goto Exit;
  1281. }
  1282. }
  1283. // Workaround for filter bug where the filter
  1284. // gives the volume name in the format \??\Volume{098089}\
  1285. // whereas the correct format is \\?\Volume{098089}\
  1286. cszVolumeName[1] = L'\\';
  1287. if ( !::SetVolumeMountPoint(cszSrc, cszVolumeName))
  1288. {
  1289. m_dwErr = ::GetLastError();
  1290. m_dwRes = RSTRRES_IGNORE;
  1291. s_cszErr = ::GetSysErrStr( m_dwErr );
  1292. ErrorTrace(0, "::DeleteVolumeMountPoint failed - '%ls'", s_cszErr);
  1293. goto Exit;
  1294. }
  1295. m_dwRes = RSTRRES_OK;
  1296. Exit:
  1297. TraceFunctLeave();
  1298. }
  1299. /////////////////////////////////////////////////////////////////////////////
  1300. //
  1301. // CreateRestoreMapEntry
  1302. //
  1303. /////////////////////////////////////////////////////////////////////////////
  1304. /*
  1305. // NOTE - 8/1/00 - skkhang
  1306. //
  1307. // Commented out to incorporate excluding restore map logic.
  1308. // But DO NOT delete this until we are comfortable 100% about removing
  1309. // restore map.
  1310. //
  1311. CRestoreMapEntry*
  1312. CreateRestoreMapEntry( RestoreMapEntry* pRME, LPCWSTR cszDrv, LPCWSTR cszDSPath )
  1313. {
  1314. TraceFunctEnter("CreateRestoreMapEntry");
  1315. LPCWSTR cszSrc;
  1316. PVOID pOpt;
  1317. WCHAR szSrc[MAX_PATH];
  1318. WCHAR szOpt[MAX_PATH];
  1319. CRestoreMapEntry *pEnt = NULL;
  1320. //cszSrc = (LPCWSTR)pRME->m_bData;
  1321. ::lstrcpy( szSrc, cszDrv );
  1322. ::PathAppend( szSrc, (LPCWSTR)pRME->m_bData );
  1323. pOpt = ::GetOptional( pRME );
  1324. switch ( pRME->m_dwOperation )
  1325. {
  1326. case OPR_DIR_CREATE :
  1327. pEnt = new CRMEDirCreate( szSrc );
  1328. break;
  1329. case OPR_DIR_DELETE :
  1330. pEnt = new CRMEDirDelete( szSrc );
  1331. break;
  1332. case OPR_DIR_RENAME :
  1333. ::lstrcpy( szOpt, cszDrv );
  1334. ::PathAppend( szOpt, (LPCWSTR)pOpt );
  1335. pEnt = new CRMEDirRename( szSrc, szOpt );
  1336. break;
  1337. case OPR_FILE_ADD :
  1338. ::lstrcpy( szOpt, cszDSPath );
  1339. ::PathAppend( szOpt, (LPCWSTR)pOpt );
  1340. pEnt = new CRMEFileCreate( szSrc, szOpt );
  1341. break;
  1342. case OPR_FILE_DELETE :
  1343. pEnt = new CRMEFileDelete( szSrc );
  1344. break;
  1345. case OPR_FILE_MODIFY :
  1346. ::lstrcpy( szOpt, cszDSPath );
  1347. ::PathAppend( szOpt, (LPCWSTR)pOpt );
  1348. pEnt = new CRMEFileModify( szSrc, szOpt );
  1349. break;
  1350. case OPR_FILE_RENAME :
  1351. ::lstrcpy( szOpt, cszDrv );
  1352. ::PathAppend( szOpt, (LPCWSTR)pOpt );
  1353. pEnt = new CRMEFileRename( szSrc, szOpt );
  1354. break;
  1355. case OPR_SETACL :
  1356. pEnt = new CRMESetAcl( szSrc, (LPBYTE)pOpt, pRME->m_cbAcl, pRME->m_fAclInline, cszDSPath );
  1357. break;
  1358. case OPR_SETATTRIB :
  1359. pEnt = new CRMESetAttrib( szSrc, pRME->m_dwAttribute );
  1360. break;
  1361. default :
  1362. ErrorTrace(0, "Invalid operation type - %d", pRME->m_dwOperation);
  1363. goto Exit;
  1364. }
  1365. if ( pEnt == NULL )
  1366. {
  1367. FatalTrace(0, "Insufficient memory...");
  1368. goto Exit;
  1369. }
  1370. Exit:
  1371. TraceFunctLeave();
  1372. return( pEnt );
  1373. }
  1374. */
  1375. //
  1376. // util function to append strings larger than MAX_PATH
  1377. //
  1378. void
  1379. MyPathAppend(
  1380. LPWSTR pszSrc,
  1381. LPWSTR pszString)
  1382. {
  1383. if (pszSrc && pszString)
  1384. {
  1385. pszSrc = pszSrc + lstrlen(pszSrc) - 1;
  1386. if (*pszSrc != L'\\') // append '\' if not already present in first string
  1387. {
  1388. pszSrc++;
  1389. *pszSrc = L'\\';
  1390. }
  1391. pszSrc++;
  1392. if (*pszString == L'\\') // skip '\' if already present in second string
  1393. {
  1394. pszString++;
  1395. }
  1396. memcpy(pszSrc, pszString, (lstrlen(pszString) + 1) * sizeof(WCHAR));
  1397. }
  1398. return;
  1399. }
  1400. /////////////////////////////////////////////////////////////////////////////
  1401. //
  1402. // CreateRestoreMapEntryForUndo
  1403. //
  1404. /////////////////////////////////////////////////////////////////////////////
  1405. BOOL
  1406. CreateRestoreMapEntryFromChgLog( CChangeLogEntry* pCLE,
  1407. LPCWSTR cszDrv,
  1408. LPCWSTR cszDSPath,
  1409. CRMEArray &aryEnt )
  1410. {
  1411. TraceFunctEnter("CreateRestoreMapEntry");
  1412. BOOL fRet = FALSE;
  1413. INT64 llSeq;
  1414. WCHAR szSrc[SR_MAX_FILENAME_LENGTH + MAX_PATH];
  1415. WCHAR szOpt[SR_MAX_FILENAME_LENGTH + MAX_PATH];
  1416. DWORD dwOpr;
  1417. CRestoreMapEntry *pEnt = NULL;
  1418. BOOL fOptimized = FALSE;
  1419. llSeq = pCLE->GetSequenceNum();
  1420. if (FALSE == pCLE->CheckPathLengths())
  1421. {
  1422. trace(0, "Filepath lengths too long");
  1423. goto Exit;
  1424. }
  1425. ::lstrcpy( szSrc, cszDrv );
  1426. MyPathAppend( szSrc, pCLE->GetPath1() );
  1427. dwOpr = pCLE->GetType() & SrEventLogMask;
  1428. // Create and add regular operation
  1429. switch ( dwOpr )
  1430. {
  1431. case SrEventStreamChange :
  1432. case SrEventStreamOverwrite :
  1433. ::lstrcpy( szOpt, cszDSPath );
  1434. MyPathAppend( szOpt, pCLE->GetRPDir() );
  1435. MyPathAppend( szOpt, pCLE->GetTemp() );
  1436. pEnt = new CRMEFileModify( llSeq, szSrc, szOpt );
  1437. break;
  1438. case SrEventAclChange :
  1439. pEnt = new CRMESetAcl( llSeq, szSrc, pCLE->GetAcl(), pCLE->GetAclSize(), pCLE->GetAclInline(), cszDSPath );
  1440. break;
  1441. case SrEventAttribChange :
  1442. pEnt = new CRMESetAttrib( llSeq, szSrc, pCLE->GetAttributes() );
  1443. break;
  1444. case SrEventFileDelete :
  1445. if ( pCLE->GetTemp() != NULL && ::lstrlen( pCLE->GetTemp() ) > 0 )
  1446. {
  1447. ::lstrcpy( szOpt, cszDSPath );
  1448. MyPathAppend( szOpt, pCLE->GetRPDir() );
  1449. MyPathAppend( szOpt, pCLE->GetTemp() );
  1450. }
  1451. else
  1452. {
  1453. szOpt[0] = L'\0';
  1454. fOptimized = TRUE;
  1455. }
  1456. pEnt = new CRMEFileCreate( llSeq, szSrc, szOpt, pCLE->GetShortName() );
  1457. break;
  1458. case SrEventFileCreate :
  1459. pEnt = new CRMEFileDelete( llSeq, szSrc );
  1460. break;
  1461. case SrEventFileRename :
  1462. ::lstrcpy( szOpt, cszDrv );
  1463. MyPathAppend( szOpt, pCLE->GetPath2() );
  1464. pEnt = new CRMEFileRename( llSeq, szSrc, szOpt, pCLE->GetShortName() );
  1465. break;
  1466. case SrEventDirectoryCreate :
  1467. pEnt = new CRMEDirDelete( llSeq, szSrc);
  1468. break;
  1469. case SrEventDirectoryRename :
  1470. ::lstrcpy( szOpt, cszDrv );
  1471. MyPathAppend( szOpt, pCLE->GetPath2() );
  1472. pEnt = new CRMEDirRename( llSeq, szSrc, szOpt, pCLE->GetShortName());
  1473. break;
  1474. case SrEventDirectoryDelete :
  1475. pEnt = new CRMEDirCreate( llSeq, szSrc, pCLE->GetShortName() );
  1476. break;
  1477. case SrEventMountCreate :
  1478. pEnt = new CRMEMountDelete( llSeq, szSrc );
  1479. break;
  1480. case SrEventMountDelete :
  1481. ::lstrcpy( szOpt, pCLE->GetPath2() );
  1482. pEnt = new CRMEMountCreate( llSeq, szSrc,szOpt);
  1483. break;
  1484. default :
  1485. ErrorTrace(0, "Invalid operation type - %d", pCLE->GetType());
  1486. goto Exit;
  1487. }
  1488. if ( pEnt == NULL )
  1489. {
  1490. FatalTrace(0, "Insufficient memory...");
  1491. goto Exit;
  1492. }
  1493. if ( !aryEnt.AddItem( pEnt ) )
  1494. {
  1495. pEnt->Release();
  1496. goto Exit;
  1497. }
  1498. if (fOptimized == FALSE)
  1499. {
  1500. // Add Acl if exists
  1501. if ( ( dwOpr != SrEventAclChange ) && ( pCLE->GetAcl() != NULL ) )
  1502. {
  1503. pEnt = new CRMESetAcl( llSeq, szSrc, pCLE->GetAcl(), pCLE->GetAclSize(), pCLE->GetAclInline(), cszDSPath );
  1504. if ( pEnt == NULL )
  1505. {
  1506. FatalTrace(0, "Insufficient memory...");
  1507. goto Exit;
  1508. }
  1509. if ( !aryEnt.AddItem( pEnt ) )
  1510. {
  1511. pEnt->Release();
  1512. goto Exit;
  1513. }
  1514. }
  1515. // Add attribute if exists
  1516. if ( ( dwOpr != SrEventAttribChange ) && ( pCLE->GetAttributes() != 0xFFFFFFFF ) )
  1517. {
  1518. pEnt = new CRMESetAttrib( llSeq, szSrc, pCLE->GetAttributes() );
  1519. if ( pEnt == NULL )
  1520. {
  1521. FatalTrace(0, "Insufficient memory...");
  1522. goto Exit;
  1523. }
  1524. if ( !aryEnt.AddItem( pEnt ) )
  1525. {
  1526. pEnt->Release();
  1527. goto Exit;
  1528. }
  1529. }
  1530. }
  1531. fRet = TRUE;
  1532. Exit:
  1533. TraceFunctLeave();
  1534. return( fRet );
  1535. }
  1536. /*
  1537. Note about handling locked files:
  1538. Here is mail from SK about this:
  1539. Sorry about long mail. It's quite complicated, so I needed to write
  1540. things down. If you want to discuss further, please ping me today
  1541. 4pm-5pm or tomorrow.
  1542. The initial code of ProcessDependency had a couple of problems, and
  1543. one fix made on 2001/05/18 by Brijesh for bug #398320 tried to solve
  1544. one of them but caused this delete & add bug as a side effect.
  1545. First of all, three type of ops can cause dependency if locked -
  1546. Delete, Rename, and Modify.
  1547. And there are two types of dependency:
  1548. 1. Location. Failed delete or rename ops will leave a file/dir at a
  1549. location and can prevent later ops cannot create an object in
  1550. there. Create ops and destination of Rename ops (m_strSrc).
  1551. 2. Object. Failed rename or modify ops can cause later ops cannot find
  1552. a proper file to work on. Delete ops, source of Rename ops (m_strDst),
  1553. Modify ops, SetAttrib and SetAcl.
  1554. Now the full list of scenarios the ProcessDependency must take care of are:
  1555. 1. Delete ops. Compare m_strSrc with Location of the others.
  1556. 2. Rename ops. Compare m_strDst with Location of the others.
  1557. 3. Rename ops. Compare m_strSrc with Object of the others.
  1558. 4. Modify ops. Compare m_strSrc with Object of the others.
  1559. ProcessDependency was broken because it had only two cases and was
  1560. comparing wrong pathes, so only #1 case was being handled
  1561. properly. Brijesh's fix corrected #2 and #3 case, but broke #1 case --
  1562. the new bug.
  1563. In order to fix this properly,
  1564. 1. Remove ProcessDependency.
  1565. 2. Replace each call to ProcessDependency by below codes:
  1566. DELETE (DirDelete and FileDelete)
  1567. if ( pROMgr->FindDependentMapEntry( m_strSrc, FALSE, &pEnt ) )
  1568. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  1569. RENAME (DirRename and FileRename)
  1570. if ( pROMgr->FindDependentMapEntry( m_strDst, FALSE, &pEnt ) )
  1571. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  1572. if ( pROMgr->FindDependentMapEntry( m_strSrc, TRUE, &pEnt ) )
  1573. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  1574. MODIFY (FileModify)
  1575. if ( pROMgr->FindDependentMapEntry( m_strSrc, TRUE, &pEnt ) )
  1576. pEnt->SetResults( RSTRRES_LOCKED, 0 );
  1577. 3. (optional) To be a little more clear, "fCheckSrc" flag of
  1578. FindDependentMapEntry could be renamed to "fCheckObj". I tried to
  1579. explain this in the comment of FindDependentMapEntry function, but as
  1580. I read it now, it seems not clear and easy enough...
  1581. And correct, dependency is not being checked cascaded.
  1582. Thanks,
  1583. skkhang
  1584. Note from AshishS - I made a few of the modifications mentioned
  1585. above. The code already is doing the correct thing for renames so I
  1586. did not change it for SP1.
  1587. In particular,
  1588. 1. The code for handling locked cases for Modify is incorrect if the
  1589. Modify operation was flagged as a dependent operation of another
  1590. operation that was found locked.
  1591. 2. There is no code that handles a creation operation being
  1592. locked. However, a create operation should not really be locked since
  1593. the file should not exist.
  1594. 3. SetAcl and SetAttrib cases should not be checked while checking for
  1595. dependency since since they cannot be done after the reboot
  1596. anyways. Restore should not fail because of these operations failing.
  1597. The following cases were checked along with the results:
  1598. Delete a.dll
  1599. Create a.dll
  1600. Create a.dll
  1601. Del a.dll - this cannot be locked since a.dll should not exist
  1602. Create a.dll
  1603. Create restore point
  1604. Modify a.dll - this succeeds but in the dependency check for modify,
  1605. the next setacl change is picked. However, the delete also handles
  1606. the locked case independently
  1607. Modify a.dll
  1608. Ren a.dll c.dll
  1609. Lock c.dll - This has two problems when the HandleLocked for Modify is
  1610. called, the temp file does not exist. This causes Handlelock to not
  1611. work as expected. However, before this, the SetACL fails since the
  1612. file a.dll does not exist.
  1613. */
  1614. // end of file