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.

3138 lines
79 KiB

  1. //
  2. // Copyright (c) 1991 Microsoft Corporation & Maynard Electornics
  3. //
  4. // Module Name:
  5. //
  6. // backup.c
  7. //
  8. // Abstract:
  9. //
  10. // This module implements Win32 Backup APIs
  11. //
  12. // Author:
  13. //
  14. // Steve DeVos (@Maynard) 2 March, 1992 15:38:24
  15. //
  16. // Revision History:
  17. #include <basedll.h>
  18. #pragma hdrstop
  19. #include <windows.h>
  20. #define CWCMAX_STREAMNAME 512
  21. #define CB_NAMELESSHEADER FIELD_OFFSET(WIN32_STREAM_ID, cStreamName)
  22. typedef struct
  23. {
  24. DWORD BufferSize;
  25. DWORD AllocSize;
  26. BYTE *Buffer;
  27. } BUFFER;
  28. //
  29. // BACKUPCONTEXT is the structure used to note the state of the backup.
  30. //
  31. typedef struct
  32. {
  33. //
  34. // Public header describing current stream. Since this structure precedes
  35. // a variable-length stream name, we must reserve space for that name
  36. // following the header.
  37. //
  38. WIN32_STREAM_ID head;
  39. union {
  40. WCHAR awcName[CWCMAX_STREAMNAME];
  41. } ex ;
  42. LARGE_INTEGER cbSparseOffset ;
  43. //
  44. // Offset in the current segment of the backup stream. This includes
  45. // the size of the above header (including variable length name).
  46. //
  47. LONGLONG liStreamOffset;
  48. //
  49. // BackupRead machine state
  50. //
  51. DWORD StreamIndex;
  52. //
  53. // Calculated size of the above header.
  54. //
  55. DWORD cbHeader;
  56. //
  57. // Handle to alternate data stream
  58. //
  59. HANDLE hAlternate;
  60. //
  61. // Buffers
  62. //
  63. BUFFER DataBuffer; // Data buffer
  64. DWORD dwSparseMapSize ; // size of the sparse file map
  65. DWORD dwSparseMapOffset ; // offset into the sparse map
  66. BOOLEAN fSparseBlockStart ; // TRUE if start of sparse block
  67. BOOLEAN fSparseHandAlt ; // TRUE if sparse stream is alt stream
  68. DWORD iNameBuffer; // Offset into stream name buffer
  69. BUFFER StreamNameBuffer; // Stream name buffer
  70. BOOLEAN NamesReady; // TRUE if stream name buffer has data in it
  71. BOOLEAN fStreamStart; // TRUE if start of new stream
  72. BOOLEAN fMultiStreamType; // TRUE if stream type has > 1 stream hdr
  73. BOOLEAN fAccessError; // TRUE if access to a stream was denied
  74. DWORD fAttribs; // object attributes...
  75. } BACKUPCONTEXT;
  76. //
  77. // BACKUPIOFRAME describes the current user BackupRead/Write request
  78. //
  79. typedef struct
  80. {
  81. BYTE *pIoBuffer;
  82. DWORD *pcbTransferred;
  83. DWORD cbRequest;
  84. BOOLEAN fProcessSecurity;
  85. } BACKUPIOFRAME;
  86. #define CBMIN_BUFFER 1024
  87. #define BufferOverflow(s) \
  88. ((s) == STATUS_BUFFER_OVERFLOW || (s) == STATUS_BUFFER_TOO_SMALL)
  89. int mwStreamList[] =
  90. {
  91. BACKUP_SECURITY_DATA,
  92. BACKUP_REPARSE_DATA,
  93. BACKUP_DATA,
  94. BACKUP_EA_DATA,
  95. BACKUP_ALTERNATE_DATA,
  96. BACKUP_OBJECT_ID,
  97. BACKUP_INVALID,
  98. };
  99. __inline VOID *
  100. BackupAlloc (DWORD cb)
  101. /*++
  102. Routine Description:
  103. This is an internal routine that wraps heap allocation with tags.
  104. Arguments:
  105. cb - size of block to allocate
  106. Return Value:
  107. pointer to allocated memory or NULL
  108. --*/
  109. {
  110. return RtlAllocateHeap( RtlProcessHeap( ), MAKE_TAG( BACKUP_TAG ), cb );
  111. }
  112. __inline VOID
  113. BackupFree (IN VOID *pv)
  114. /*++
  115. Routine Description:
  116. This is an internal routine that wraps heap freeing.
  117. Arguments:
  118. pv - memory to be freed
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. RtlFreeHeap( RtlProcessHeap( ), 0, pv );
  124. }
  125. BOOL
  126. GrowBuffer (IN OUT BUFFER *Buffer, IN DWORD cbNew)
  127. /*++
  128. Routine Description:
  129. Attempt to grow the buffer in the backup context.
  130. Arguments:
  131. Buffer - pointer to buffer
  132. cbNew - size of buffer to allocate
  133. Return Value:
  134. TRUE if buffer was successfully allocated.
  135. --*/
  136. {
  137. VOID *pv;
  138. if ( Buffer->AllocSize < cbNew ) {
  139. pv = BackupAlloc( cbNew );
  140. if (pv == NULL) {
  141. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  142. return FALSE;
  143. }
  144. RtlCopyMemory( pv, Buffer->Buffer, Buffer->BufferSize );
  145. BackupFree( Buffer->Buffer );
  146. Buffer->Buffer = pv;
  147. Buffer->AllocSize = cbNew ;
  148. }
  149. Buffer->BufferSize = cbNew;
  150. return TRUE;
  151. }
  152. __inline VOID
  153. FreeBuffer (IN OUT BUFFER *Buffer)
  154. /*++
  155. Routine Description:
  156. Free the buffer
  157. Arguments:
  158. Buffer - pointer to buffer
  159. Return Value:
  160. Nothing
  161. --*/
  162. {
  163. if (Buffer->Buffer != NULL) {
  164. BackupFree( Buffer->Buffer );
  165. Buffer->Buffer = NULL;
  166. }
  167. }
  168. VOID ResetAccessDate( HANDLE hand )
  169. {
  170. LONGLONG tmp_time = -1 ;
  171. FILETIME *time_ptr ;
  172. time_ptr = (FILETIME *)(&tmp_time);
  173. if (hand && (hand != INVALID_HANDLE_VALUE)) {
  174. SetFileTime( hand,
  175. time_ptr,
  176. time_ptr,
  177. time_ptr ) ;
  178. }
  179. }
  180. VOID
  181. FreeContext (IN OUT LPVOID *lpContext)
  182. /*++
  183. Routine Description:
  184. Free a backup context and release all resources assigned to it.
  185. Arguments:
  186. lpContext - pointer to pointer backup context
  187. Return Value:
  188. None.
  189. --*/
  190. {
  191. BACKUPCONTEXT *pbuc = *lpContext;
  192. if (pbuc != INVALID_HANDLE_VALUE) {
  193. FreeBuffer( &pbuc->DataBuffer );
  194. FreeBuffer( &pbuc->StreamNameBuffer );
  195. ResetAccessDate( pbuc->hAlternate ) ;
  196. if (pbuc->hAlternate != INVALID_HANDLE_VALUE) {
  197. CloseHandle( pbuc->hAlternate );
  198. }
  199. BackupFree(pbuc);
  200. *lpContext = INVALID_HANDLE_VALUE;
  201. }
  202. }
  203. BACKUPCONTEXT *
  204. AllocContext (IN DWORD cbBuffer)
  205. /*++
  206. Routine Description:
  207. Allocate a backup context with a buffer of a specified size
  208. Arguments:
  209. cbBuffer - desired length of the buffer
  210. Return Value:
  211. pointer to initialized backupcontext or NULL if out of memory.
  212. --*/
  213. {
  214. BACKUPCONTEXT *pbuc;
  215. pbuc = BackupAlloc( sizeof( *pbuc ));
  216. if (pbuc != NULL) {
  217. RtlZeroMemory( pbuc, sizeof( *pbuc ));
  218. pbuc->fStreamStart = TRUE;
  219. if (cbBuffer != 0 && !GrowBuffer( &pbuc->DataBuffer, cbBuffer )) {
  220. BackupFree( pbuc );
  221. pbuc = NULL;
  222. }
  223. }
  224. if (pbuc == NULL) {
  225. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  226. }
  227. return(pbuc);
  228. }
  229. LONGLONG
  230. ComputeRemainingSize (IN BACKUPCONTEXT *pbuc)
  231. /*++
  232. Routine Description:
  233. (Re)Compute the number of bytes required to store the current
  234. stream. This needs to take into account the header length as
  235. well.
  236. Arguments:
  237. pbuc - backup context
  238. Return Value:
  239. Amount of data still remaining to transfer. Includes header
  240. size.
  241. --*/
  242. {
  243. LARGE_INTEGER ret_size ;
  244. ret_size.QuadPart = pbuc->cbHeader + pbuc->head.Size.QuadPart
  245. - pbuc->liStreamOffset;
  246. //
  247. // since the internally we treat the sparse buffer offset
  248. // as part of the header and since the caller need to see it
  249. // as part of the data, this code make the internal correction.
  250. //
  251. if ( pbuc->head.dwStreamId == BACKUP_SPARSE_BLOCK ) {
  252. ret_size.QuadPart -= sizeof(LARGE_INTEGER) ;
  253. }
  254. return ret_size.QuadPart ;
  255. }
  256. DWORD
  257. ComputeRequestSize (BACKUPCONTEXT *pbuc, DWORD cbrequest)
  258. /*++
  259. Routine Description:
  260. Given a transfer size request, return the number of
  261. bytes remaining that can safely be returned to the
  262. caller
  263. Arguments:
  264. pbuc - context of call
  265. cbRequest - desired transfer size
  266. Return Value:
  267. amount of data available to return.
  268. --*/
  269. {
  270. LONGLONG licbRemain;
  271. licbRemain = ComputeRemainingSize( pbuc );
  272. return (DWORD) min( cbrequest, licbRemain );
  273. }
  274. VOID
  275. ReportTransfer(BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif, DWORD cbtransferred)
  276. /*++
  277. Routine Description:
  278. Note that a transfer has occurred and update contexts
  279. Arguments:
  280. pbuc - context of call
  281. pbif - BACKUPIOFRAME of call detailing call
  282. cbtransferred - amount successfully transferred
  283. Return Value:
  284. None.
  285. --*/
  286. {
  287. pbuc->liStreamOffset += cbtransferred;
  288. *pbif->pcbTransferred += cbtransferred;
  289. pbif->cbRequest -= cbtransferred;
  290. pbif->pIoBuffer += cbtransferred;
  291. }
  292. VOID
  293. BackupReadBuffer (BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  294. /*++
  295. Routine Description:
  296. Perform a read to user buffer from the buffer in the backup
  297. context.
  298. Arguments:
  299. pbuc - context of call
  300. pbif - frame describing desired user BackupRead request
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. DWORD cbrequest;
  306. BYTE *pb;
  307. //
  308. // Determine size of allowable transfer and pointer to source
  309. // data
  310. //
  311. cbrequest = ComputeRequestSize( pbuc, pbif->cbRequest );
  312. pb = &pbuc->DataBuffer.Buffer[ pbuc->liStreamOffset - pbuc->cbHeader ];
  313. //
  314. // Move the data to the user's buffer
  315. //
  316. RtlCopyMemory(pbif->pIoBuffer, pb, cbrequest);
  317. //
  318. // Update statistics
  319. //
  320. ReportTransfer(pbuc, pbif, cbrequest);
  321. }
  322. BOOL
  323. BackupReadStream (HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  324. /*++
  325. Routine Description:
  326. Perform a read to user buffer from the stream.
  327. Arguments:
  328. hFile - handle to file for transfer
  329. pbuc - context of call
  330. pbif - frame describing BackupRead request
  331. Return Value:
  332. True if transfer succeeded..
  333. --*/
  334. {
  335. DWORD cbrequest;
  336. DWORD cbtransferred;
  337. BOOL fSuccess;
  338. if (pbuc->fSparseBlockStart) {
  339. PFILE_ALLOCATED_RANGE_BUFFER range_buf ;
  340. LARGE_INTEGER licbFile ;
  341. range_buf = (PFILE_ALLOCATED_RANGE_BUFFER)(pbuc->DataBuffer.Buffer + pbuc->dwSparseMapOffset) ;
  342. pbuc->head.Size.QuadPart = range_buf->Length.QuadPart + sizeof(LARGE_INTEGER) ;
  343. pbuc->head.dwStreamId = BACKUP_SPARSE_BLOCK ;
  344. pbuc->head.dwStreamAttributes = STREAM_SPARSE_ATTRIBUTE;
  345. pbuc->head.dwStreamNameSize = 0;
  346. pbuc->cbHeader = CB_NAMELESSHEADER + sizeof( LARGE_INTEGER ) ;
  347. pbuc->cbSparseOffset = range_buf->FileOffset ;
  348. RtlCopyMemory( pbuc->head.cStreamName, &pbuc->cbSparseOffset, sizeof( LARGE_INTEGER ) ) ;
  349. pbuc->fSparseBlockStart = FALSE;
  350. licbFile.HighPart = 0;
  351. licbFile.HighPart = range_buf->FileOffset.HighPart;
  352. licbFile.LowPart = SetFilePointer( hFile,
  353. range_buf->FileOffset.LowPart,
  354. &licbFile.HighPart,
  355. FILE_BEGIN );
  356. if ( licbFile.QuadPart != range_buf->FileOffset.QuadPart ) {
  357. pbuc->fAccessError = TRUE;
  358. return FALSE ;
  359. } else {
  360. return TRUE ;
  361. }
  362. }
  363. if (pbuc->liStreamOffset < pbuc->cbHeader) {
  364. return TRUE ;
  365. }
  366. cbrequest = ComputeRequestSize( pbuc, pbif->cbRequest );
  367. fSuccess = ReadFile( hFile, pbif->pIoBuffer, cbrequest, &cbtransferred, NULL );
  368. if (cbtransferred != 0) {
  369. ReportTransfer( pbuc, pbif, cbtransferred );
  370. } else if (fSuccess && cbrequest != 0) {
  371. SetLastError( ERROR_IO_DEVICE );
  372. fSuccess = FALSE;
  373. }
  374. return(fSuccess);
  375. }
  376. BOOL
  377. BackupGetSparseMap (HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  378. /*++
  379. Routine Description:
  380. Reads the sparse data map.
  381. Arguments:
  382. hFile - handle to file for transfer
  383. pbuc - context of call
  384. pbif - frame describing BackupRead request
  385. Return Value:
  386. True if transfer succeeded..
  387. --*/
  388. {
  389. FILE_ALLOCATED_RANGE_BUFFER req_buf ;
  390. PFILE_ALLOCATED_RANGE_BUFFER last_ret_buf ;
  391. DWORD out_buf_size ;
  392. DWORD data_size = 4096 ;
  393. IO_STATUS_BLOCK iosb ;
  394. LARGE_INTEGER file_size ;
  395. NTSTATUS Status ;
  396. BOOLEAN empty_file = FALSE ;
  397. req_buf.FileOffset.QuadPart = 0 ;
  398. pbuc->dwSparseMapSize = 0 ;
  399. pbuc->dwSparseMapOffset = 0 ;
  400. pbuc->fSparseBlockStart = FALSE ;
  401. req_buf.Length.LowPart = GetFileSize( hFile,
  402. &req_buf.Length.HighPart );
  403. file_size = req_buf.Length ;
  404. do {
  405. if ( GrowBuffer( &pbuc->DataBuffer,
  406. data_size ) ) {
  407. iosb.Information = 0 ;
  408. Status = NtFsControlFile( hFile,
  409. NULL, // overlapped event handle
  410. NULL, // Apc routine
  411. NULL, // overlapped structure
  412. &iosb,
  413. FSCTL_QUERY_ALLOCATED_RANGES,
  414. &req_buf,
  415. sizeof( req_buf ),
  416. pbuc->DataBuffer.Buffer + pbuc->dwSparseMapSize,
  417. pbuc->DataBuffer.AllocSize - pbuc->dwSparseMapSize ) ;
  418. out_buf_size = 0 ;
  419. if ((Status == STATUS_BUFFER_OVERFLOW) || NT_SUCCESS( Status ) ) {
  420. out_buf_size = (DWORD)iosb.Information ;
  421. if ( out_buf_size == 0 ) {
  422. empty_file = TRUE ;
  423. }
  424. }
  425. if ( out_buf_size != 0 ) {
  426. pbuc->dwSparseMapSize += out_buf_size ;
  427. last_ret_buf =
  428. (PFILE_ALLOCATED_RANGE_BUFFER)(pbuc->DataBuffer.Buffer +
  429. pbuc->dwSparseMapSize -
  430. sizeof(FILE_ALLOCATED_RANGE_BUFFER)) ;
  431. req_buf.FileOffset = last_ret_buf->FileOffset ;
  432. req_buf.FileOffset.QuadPart += last_ret_buf->Length.QuadPart ;
  433. //
  434. // if we can't fit any more in the buffer lets increase
  435. // the size and get more data otherwise assume were done.
  436. //
  437. if ( pbuc->dwSparseMapSize + sizeof(FILE_ALLOCATED_RANGE_BUFFER) >
  438. pbuc->DataBuffer.AllocSize ) {
  439. data_size += 4096 ;
  440. } else {
  441. break ;
  442. }
  443. } else {
  444. // reallocate for one more buffer entry
  445. if ( out_buf_size + sizeof(FILE_ALLOCATED_RANGE_BUFFER) > data_size ) {
  446. data_size += 4096 ;
  447. continue ;
  448. }
  449. break ;
  450. }
  451. } else {
  452. pbuc->dwSparseMapSize = 0 ;
  453. break ;
  454. }
  455. } while ( TRUE ) ;
  456. //
  457. // if there are RANGE_BUFFERS and it isn't simply the whole file, then
  458. // go into sparse read mode.
  459. //
  460. // hold on to your hat...
  461. // If there are no allocated ranges and the file is NOT 0 length
  462. // then we want to manufacture a record for the file length.
  463. //
  464. if ( (empty_file && ( file_size.QuadPart != 0 )) || (pbuc->dwSparseMapSize >= sizeof( FILE_ALLOCATED_RANGE_BUFFER) ) ) {
  465. last_ret_buf = (PFILE_ALLOCATED_RANGE_BUFFER)(pbuc->DataBuffer.Buffer ) ;
  466. if ( empty_file ||
  467. ( last_ret_buf->FileOffset.QuadPart != 0 ) ||
  468. ( last_ret_buf->Length.QuadPart != file_size.QuadPart ) ) {
  469. // first lets add a record for the EOF marker
  470. pbuc->dwSparseMapSize += sizeof(FILE_ALLOCATED_RANGE_BUFFER) ;
  471. last_ret_buf =
  472. (PFILE_ALLOCATED_RANGE_BUFFER)(pbuc->DataBuffer.Buffer +
  473. pbuc->dwSparseMapSize -
  474. sizeof(FILE_ALLOCATED_RANGE_BUFFER)) ;
  475. last_ret_buf->FileOffset.QuadPart = file_size.QuadPart ;
  476. last_ret_buf->Length.QuadPart = 0 ;
  477. pbuc->fSparseBlockStart = TRUE ;
  478. return TRUE ;
  479. }
  480. }
  481. pbuc->dwSparseMapSize = 0 ;
  482. return FALSE ;
  483. }
  484. BOOL
  485. BackupReadData (HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  486. /*++
  487. Routine Description:
  488. Read default data for a user BackupRead request.
  489. Arguments:
  490. hFile - handle to file for transfer
  491. pbuc - context of call
  492. pbif - frame describing BackupRead request
  493. Return Value:
  494. True if transfer succeeded..
  495. --*/
  496. {
  497. LARGE_INTEGER licbFile ;
  498. //
  499. // If the context is not initialized for this transfer,
  500. // set up based on file size.
  501. //
  502. if (pbuc->fStreamStart) {
  503. if (pbuc->fAttribs & FILE_ATTRIBUTE_ENCRYPTED) {
  504. return TRUE;
  505. }
  506. if (pbuc->fAttribs & FILE_ATTRIBUTE_DIRECTORY) {
  507. return TRUE;
  508. }
  509. licbFile.LowPart = GetFileSize( hFile, &licbFile.HighPart );
  510. if (licbFile.QuadPart == 0) {
  511. return TRUE;
  512. }
  513. if (licbFile.LowPart == 0xffffffff && GetLastError() != NO_ERROR) {
  514. return FALSE;
  515. }
  516. pbuc->head.dwStreamId = BACKUP_DATA;
  517. pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
  518. pbuc->head.dwStreamNameSize = 0;
  519. pbuc->cbHeader = CB_NAMELESSHEADER;
  520. pbuc->fStreamStart = FALSE;
  521. if ( BackupGetSparseMap( hFile, pbuc, pbif ) ) {
  522. pbuc->head.Size.QuadPart = 0 ;
  523. pbuc->head.dwStreamAttributes = STREAM_SPARSE_ATTRIBUTE;
  524. } else {
  525. pbuc->head.Size = licbFile;
  526. licbFile.HighPart = 0;
  527. SetFilePointer( hFile, 0, &licbFile.HighPart, FILE_BEGIN );
  528. }
  529. return TRUE;
  530. }
  531. //
  532. // If there's more data for us to read, then go and
  533. // get it from the stream
  534. //
  535. return BackupReadStream( hFile, pbuc, pbif );
  536. }
  537. BOOL
  538. BackupReadAlternateData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  539. /*++
  540. Routine Description:
  541. Perform a read to user buffer from alternate data streams.
  542. Arguments:
  543. hFile - handle to base file for transfer
  544. pbuc - context of call
  545. pbif - frame describing BackupRead request
  546. Return Value:
  547. True if transfer succeeded..
  548. --*/
  549. {
  550. //
  551. // If we haven't started transferring alternate data streams then
  552. // buffer all the stream information from the file system
  553. //
  554. if (pbuc->fStreamStart) {
  555. NTSTATUS Status;
  556. FILE_STREAM_INFORMATION *pfsi;
  557. IO_STATUS_BLOCK iosb;
  558. if (pbuc->fAttribs & FILE_ATTRIBUTE_ENCRYPTED) {
  559. if ( !(pbuc->fAttribs & FILE_ATTRIBUTE_DIRECTORY) ) {
  560. return TRUE;
  561. }
  562. }
  563. //
  564. // Loop, growing the names buffer, until it is large enough to
  565. // contain all the alternate data
  566. //
  567. if (!pbuc->NamesReady) {
  568. if (!GrowBuffer( &pbuc->StreamNameBuffer, 1024 ) ) {
  569. return FALSE;
  570. }
  571. while (TRUE) {
  572. //
  573. // Resize the buffer. If we cannot grow it, then fail.
  574. //
  575. Status = NtQueryInformationFile(
  576. hFile,
  577. &iosb,
  578. pbuc->StreamNameBuffer.Buffer,
  579. pbuc->StreamNameBuffer.BufferSize,
  580. FileStreamInformation);
  581. //
  582. // If we succeeded in reading some data, set the buffer
  583. // up and finish initializing
  584. //
  585. if (NT_SUCCESS(Status) && iosb.Information != 0) {
  586. pbuc->iNameBuffer = 0;
  587. pbuc->NamesReady = TRUE;
  588. break;
  589. }
  590. //
  591. // If the error was not due to overflow, then skip
  592. // all alternate streams
  593. //
  594. if (!BufferOverflow(Status)) {
  595. return TRUE;
  596. }
  597. //
  598. // simply inlarge the buffer and try again.
  599. //
  600. if (!GrowBuffer( &pbuc->StreamNameBuffer,
  601. pbuc->StreamNameBuffer.BufferSize * 2)) {
  602. return FALSE;
  603. }
  604. }
  605. }
  606. pbuc->hAlternate = INVALID_HANDLE_VALUE;
  607. pbuc->fStreamStart = FALSE;
  608. pfsi = (FILE_STREAM_INFORMATION *) &pbuc->StreamNameBuffer.Buffer[pbuc->iNameBuffer];
  609. //
  610. // Skip first stream if it is the default data stream. This
  611. // code is NTFS-specific and relies on behaviour not documented anywhere.
  612. //
  613. if (pfsi->StreamNameLength >= 2 * sizeof(WCHAR) &&
  614. pfsi->StreamName[1] == ':') {
  615. if (pfsi->NextEntryOffset == 0) {
  616. return TRUE; // No more, do next stream type
  617. }
  618. pbuc->iNameBuffer += pfsi->NextEntryOffset;
  619. }
  620. pbuc->head.Size.LowPart = 1;
  621. //
  622. // If we don't have an open stream
  623. //
  624. } else if (pbuc->hAlternate == INVALID_HANDLE_VALUE) {
  625. NTSTATUS Status;
  626. PFILE_STREAM_INFORMATION pfsi;
  627. UNICODE_STRING strName;
  628. OBJECT_ATTRIBUTES oa;
  629. IO_STATUS_BLOCK iosb;
  630. DWORD reparse_flg = 0 ;
  631. pbuc->head.Size.QuadPart = 0;
  632. //
  633. // Form the relative name of the stream and try to
  634. // open it relative to the base file
  635. //
  636. pfsi = (FILE_STREAM_INFORMATION *) &pbuc->StreamNameBuffer.Buffer[pbuc->iNameBuffer];
  637. strName.Length = (USHORT) pfsi->StreamNameLength;
  638. strName.MaximumLength = strName.Length;
  639. strName.Buffer = pfsi->StreamName;
  640. if (pbuc->fAttribs & FILE_ATTRIBUTE_REPARSE_POINT ) {
  641. reparse_flg = FILE_OPEN_REPARSE_POINT ;
  642. }
  643. InitializeObjectAttributes(
  644. &oa,
  645. &strName,
  646. OBJ_CASE_INSENSITIVE,
  647. hFile,
  648. NULL);
  649. Status = NtOpenFile(
  650. &pbuc->hAlternate,
  651. FILE_READ_DATA | SYNCHRONIZE,
  652. &oa,
  653. &iosb,
  654. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  655. FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | reparse_flg);
  656. //
  657. // If we did not succeed, skip this entry and set up for another stream
  658. //
  659. if (!NT_SUCCESS( Status )) {
  660. pbuc->iNameBuffer += pfsi->NextEntryOffset;
  661. if (pfsi->NextEntryOffset != 0) {
  662. pbuc->head.Size.LowPart = 1;
  663. pbuc->fMultiStreamType = TRUE; // more to come
  664. }
  665. SetLastError( ERROR_SHARING_VIOLATION );
  666. return FALSE;
  667. }
  668. // if we can't lock all records, return an error
  669. if (!LockFile( pbuc->hAlternate, 0, 0, 0xffffffff, 0xffffffff )) {
  670. SetLastError( ERROR_SHARING_VIOLATION );
  671. return FALSE;
  672. }
  673. //
  674. // Perform common header initialization
  675. //
  676. pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
  677. pbuc->head.dwStreamNameSize = pfsi->StreamNameLength;
  678. pbuc->cbHeader = CB_NAMELESSHEADER + pfsi->StreamNameLength;
  679. RtlCopyMemory(
  680. pbuc->head.cStreamName,
  681. pfsi->StreamName,
  682. pfsi->StreamNameLength);
  683. //
  684. // Advance to the next stream in the stream information block
  685. //
  686. if (pfsi->NextEntryOffset != 0) {
  687. pbuc->iNameBuffer += pfsi->NextEntryOffset;
  688. pbuc->fMultiStreamType = TRUE;
  689. }
  690. //
  691. // If we are a data stream, set up for data stream copy
  692. //
  693. if (BasepIsDataAttribute( pfsi->StreamNameLength, pfsi->StreamName )) {
  694. pbuc->head.dwStreamId = BACKUP_ALTERNATE_DATA;
  695. if ( BackupGetSparseMap( pbuc->hAlternate, pbuc, pbif ) ) {
  696. pbuc->head.Size.QuadPart = 0 ;
  697. pbuc->head.dwStreamAttributes = STREAM_SPARSE_ATTRIBUTE;
  698. } else {
  699. pbuc->head.Size.LowPart = GetFileSize(
  700. pbuc->hAlternate,
  701. &pbuc->head.Size.HighPart );
  702. }
  703. }
  704. //
  705. // If we need to return the name
  706. //
  707. } else if ( pbuc->liStreamOffset < pbuc->cbHeader) {
  708. return TRUE ;
  709. //
  710. // If there is more data in this stream to transfer
  711. //
  712. } else if ( (pbuc->head.dwStreamId == BACKUP_ALTERNATE_DATA) ||
  713. (pbuc->head.dwStreamId == BACKUP_SPARSE_BLOCK) ) {
  714. return BackupReadStream( pbuc->hAlternate, pbuc, pbif );
  715. }
  716. return TRUE;
  717. }
  718. BOOL
  719. BackupReadEaData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  720. /*++
  721. Routine Description:
  722. Perform a read to user buffer from EA data.
  723. Arguments:
  724. hFile - handle to file with EAs
  725. pbuc - context of call
  726. pbif - frame describing BackupRead request
  727. Return Value:
  728. True if transfer succeeded..
  729. --*/
  730. {
  731. //
  732. // If we are just starting out on the EA data
  733. //
  734. if (pbuc->fStreamStart) {
  735. IO_STATUS_BLOCK iosb;
  736. //
  737. // Loop trying to read all EA data into the buffer and
  738. // resize the buffer if necessary
  739. //
  740. while (TRUE) {
  741. NTSTATUS Status;
  742. FILE_EA_INFORMATION fei;
  743. Status = NtQueryEaFile(
  744. hFile,
  745. &iosb,
  746. pbuc->DataBuffer.Buffer,
  747. pbuc->DataBuffer.BufferSize,
  748. FALSE,
  749. NULL,
  750. 0,
  751. 0,
  752. (BOOLEAN) TRUE );
  753. //
  754. // If we successfully read all the data, go complete
  755. // the initialization
  756. //
  757. if (NT_SUCCESS( Status ) && iosb.Information != 0) {
  758. pbuc->NamesReady = TRUE;
  759. break;
  760. }
  761. //
  762. // If we received a status OTHER than buffer overflow then
  763. // skip EA's altogether
  764. //
  765. if (!BufferOverflow(Status)) {
  766. return TRUE;
  767. }
  768. //
  769. // Get a stab at the total EA size
  770. //
  771. Status = NtQueryInformationFile(
  772. hFile,
  773. &iosb,
  774. &fei,
  775. sizeof(fei),
  776. FileEaInformation);
  777. //
  778. // This call should never have failed (since we were able to
  779. // QueryEaFile) above. However, if it does, skip EAs altogether
  780. //
  781. if (!NT_SUCCESS(Status)) {
  782. return TRUE;
  783. }
  784. //
  785. // Resize the buffer to something that seems reasonable. No guarantees
  786. // about whether this will work or not... If we couldn't grow the buffer
  787. // fail this call.
  788. //
  789. if (!GrowBuffer( &pbuc->DataBuffer, (fei.EaSize * 5) / 4)) {
  790. pbuc->fAccessError = TRUE;
  791. return FALSE;
  792. }
  793. }
  794. //
  795. // Set up the header for the EA stream
  796. //
  797. pbuc->head.dwStreamId = BACKUP_EA_DATA;
  798. pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
  799. pbuc->head.dwStreamNameSize = 0;
  800. pbuc->cbHeader = CB_NAMELESSHEADER;
  801. pbuc->head.Size.QuadPart = iosb.Information;
  802. pbuc->fStreamStart = FALSE;
  803. //
  804. // If we have more data in the buffer to read then go
  805. // copy it out.
  806. //
  807. } else if (pbuc->liStreamOffset >= pbuc->cbHeader) {
  808. BackupReadBuffer( pbuc, pbif );
  809. }
  810. return TRUE;
  811. }
  812. BOOL
  813. BackupReadObjectId(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  814. /*++
  815. Routine Description:
  816. Perform a read to user buffer from NtObject ID data.
  817. Arguments:
  818. hFile - handle to file with EAs
  819. pbuc - context of call
  820. pbif - frame describing BackupRead request
  821. Return Value:
  822. True if transfer succeeded..
  823. --*/
  824. {
  825. //
  826. // If we are just starting out on the Object ID data
  827. //
  828. if (pbuc->fStreamStart) {
  829. IO_STATUS_BLOCK iosb;
  830. NTSTATUS Status ;
  831. if (!GrowBuffer( &pbuc->DataBuffer, 1024 ) ) {
  832. pbuc->fAccessError = TRUE;
  833. return FALSE;
  834. }
  835. Status = NtFsControlFile( hFile,
  836. NULL, // overlapped event handle
  837. NULL, // Apc routine
  838. NULL, // overlapped structure
  839. &iosb,
  840. FSCTL_GET_OBJECT_ID,
  841. NULL,
  842. 0,
  843. pbuc->DataBuffer.Buffer,
  844. pbuc->DataBuffer.BufferSize ) ;
  845. if ( !NT_SUCCESS(Status) ) {
  846. return TRUE ;
  847. }
  848. //
  849. // Set up the header for the Object ID stream
  850. //
  851. pbuc->NamesReady = TRUE;
  852. pbuc->head.dwStreamId = BACKUP_OBJECT_ID ;
  853. pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
  854. pbuc->head.dwStreamNameSize = 0;
  855. pbuc->cbHeader = CB_NAMELESSHEADER;
  856. pbuc->head.Size.QuadPart = iosb.Information;
  857. pbuc->fStreamStart = FALSE;
  858. //
  859. // If we have more data in the buffer to read then go
  860. // copy it out.
  861. //
  862. } else if (pbuc->liStreamOffset >= pbuc->cbHeader) {
  863. BackupReadBuffer( pbuc, pbif );
  864. }
  865. return TRUE;
  866. }
  867. BOOL
  868. BackupReadReparseData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  869. /*++
  870. Routine Description:
  871. Perform a read to user buffer from Reparse tag data.
  872. Arguments:
  873. hFile - handle to file with EAs
  874. pbuc - context of call
  875. pbif - frame describing BackupRead request
  876. Return Value:
  877. True if transfer succeeded..
  878. --*/
  879. {
  880. IO_STATUS_BLOCK iosb;
  881. PREPARSE_DATA_BUFFER rp_buf_ptr ;
  882. NTSTATUS Status ;
  883. struct RP_SUMMARY {
  884. USHORT tag ;
  885. USHORT rp_size ;
  886. } *rp_summary_ptr =(struct RP_SUMMARY*) &(iosb.Information) ;
  887. //
  888. // If the object is not a reparse then simply return
  889. //
  890. if ( !(pbuc->fAttribs & FILE_ATTRIBUTE_REPARSE_POINT) ) {
  891. return TRUE ;
  892. }
  893. //
  894. // If we are just starting out on the ReParse data
  895. //
  896. if (pbuc->fStreamStart) {
  897. //
  898. // Loop trying to read all EA data into the buffer and
  899. // resize the buffer if necessary
  900. //
  901. // for some reason a TOO_SMALL error is not setting the information
  902. // member of the iosb....
  903. rp_summary_ptr->rp_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE ;
  904. Status = NtFsControlFile( hFile,
  905. NULL, // overlapped event handle
  906. NULL, // Apc routine
  907. NULL, // overlapped structure
  908. &iosb,
  909. FSCTL_GET_REPARSE_POINT,
  910. NULL,
  911. 0,
  912. pbuc->DataBuffer.Buffer,
  913. pbuc->DataBuffer.BufferSize ) ;
  914. if ( BufferOverflow( Status ) ) {
  915. if ( rp_summary_ptr->rp_size == 0 ) {
  916. rp_summary_ptr->rp_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE ;
  917. }
  918. if (!GrowBuffer( &pbuc->DataBuffer,
  919. rp_summary_ptr->rp_size ) ) {
  920. pbuc->fAccessError = TRUE;
  921. return FALSE;
  922. }
  923. Status = NtFsControlFile( hFile,
  924. NULL, // overlapped event handle
  925. NULL, // Apc routine
  926. NULL, // overlapped structure
  927. &iosb,
  928. FSCTL_GET_REPARSE_POINT,
  929. NULL,
  930. 0,
  931. pbuc->DataBuffer.Buffer,
  932. pbuc->DataBuffer.BufferSize ) ;
  933. }
  934. //
  935. // If we successfully read all the data, go complete
  936. // the initialization
  937. //
  938. if ( !NT_SUCCESS( Status ) ) {
  939. return TRUE ;
  940. }
  941. //
  942. // Set up the header for the ReParse stream
  943. //
  944. rp_buf_ptr = (PREPARSE_DATA_BUFFER)(pbuc->DataBuffer.Buffer) ;
  945. pbuc->NamesReady = TRUE;
  946. pbuc->head.dwStreamId = BACKUP_REPARSE_DATA;
  947. pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE;
  948. pbuc->head.dwStreamNameSize = 0;
  949. pbuc->cbHeader = CB_NAMELESSHEADER;
  950. if ( IsReparseTagMicrosoft( rp_buf_ptr->ReparseTag ) ) {
  951. pbuc->head.Size.QuadPart = rp_buf_ptr->ReparseDataLength +
  952. FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) ;
  953. } else {
  954. pbuc->head.Size.QuadPart = rp_buf_ptr->ReparseDataLength +
  955. FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) ;
  956. }
  957. if( (unsigned)pbuc->head.Size.QuadPart > iosb.Information ) {
  958. //
  959. // sanity check the reparse point buffer size so we don't AV
  960. //
  961. pbuc->head.Size.QuadPart = iosb.Information;
  962. }
  963. pbuc->fStreamStart = FALSE;
  964. //
  965. // If we have more data in the buffer to read then go
  966. // copy it out.
  967. //
  968. } else if (pbuc->liStreamOffset >= pbuc->cbHeader) {
  969. BackupReadBuffer( pbuc, pbif );
  970. }
  971. return TRUE;
  972. }
  973. BOOL
  974. BackupReadSecurityData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  975. {
  976. //
  977. // If we are to skip security then do so.
  978. //
  979. if (!pbif->fProcessSecurity) {
  980. return TRUE;
  981. }
  982. //
  983. // If we are just starting out on the security data
  984. //
  985. if (pbuc->fStreamStart) {
  986. //
  987. // Loop trying to read all security data into the buffer and
  988. // resize the buffer if necessary
  989. //
  990. while (TRUE) {
  991. NTSTATUS Status;
  992. DWORD cbSecurityInfo;
  993. RtlZeroMemory( pbuc->DataBuffer.Buffer, pbuc->DataBuffer.BufferSize );
  994. Status = NtQuerySecurityObject(
  995. hFile,
  996. OWNER_SECURITY_INFORMATION |
  997. GROUP_SECURITY_INFORMATION |
  998. DACL_SECURITY_INFORMATION |
  999. SACL_SECURITY_INFORMATION,
  1000. pbuc->DataBuffer.Buffer,
  1001. pbuc->DataBuffer.BufferSize,
  1002. &cbSecurityInfo );
  1003. //
  1004. // If we failed but it wasn't due to buffer overflow
  1005. //
  1006. if (!NT_SUCCESS( Status ) && !BufferOverflow( Status )) {
  1007. //
  1008. // Try reading everything but SACL
  1009. //
  1010. Status = NtQuerySecurityObject(
  1011. hFile,
  1012. OWNER_SECURITY_INFORMATION |
  1013. GROUP_SECURITY_INFORMATION |
  1014. DACL_SECURITY_INFORMATION,
  1015. pbuc->DataBuffer.Buffer,
  1016. pbuc->DataBuffer.BufferSize,
  1017. &cbSecurityInfo );
  1018. }
  1019. //
  1020. // If we got it all, then go continue initialization
  1021. //
  1022. if (NT_SUCCESS( Status )) {
  1023. pbuc->NamesReady = TRUE;
  1024. break;
  1025. }
  1026. //
  1027. // If not due to overflowing buffer, skip security altogether
  1028. //
  1029. if (!BufferOverflow( Status )) {
  1030. return TRUE;
  1031. }
  1032. //
  1033. // Resize the buffer to the expected size. If we fail, fail
  1034. // the entire call
  1035. //
  1036. if (!GrowBuffer( &pbuc->DataBuffer, cbSecurityInfo )) {
  1037. return FALSE;
  1038. }
  1039. }
  1040. //
  1041. // Initialize the stream header
  1042. //
  1043. pbuc->head.dwStreamId = BACKUP_SECURITY_DATA;
  1044. pbuc->head.dwStreamAttributes = STREAM_CONTAINS_SECURITY;
  1045. pbuc->head.dwStreamNameSize = 0;
  1046. pbuc->cbHeader = CB_NAMELESSHEADER;
  1047. pbuc->head.Size.QuadPart = RtlLengthSecurityDescriptor(pbuc->DataBuffer.Buffer);
  1048. pbuc->fStreamStart = FALSE;
  1049. //
  1050. // If there is more data in the buffer to transfer, go
  1051. // do it
  1052. //
  1053. } else if (pbuc->liStreamOffset >= pbuc->cbHeader) {
  1054. BackupReadBuffer( pbuc, pbif );
  1055. }
  1056. return TRUE;
  1057. }
  1058. VOID
  1059. BackupTestRestartStream(BACKUPCONTEXT *pbuc)
  1060. {
  1061. LONGLONG licbRemain;
  1062. licbRemain = ComputeRemainingSize( pbuc );
  1063. if (licbRemain == 0) {
  1064. if ( pbuc->dwSparseMapOffset != pbuc->dwSparseMapSize ) { // only true at backup
  1065. if ( !pbuc->fSparseBlockStart ) {
  1066. pbuc->dwSparseMapOffset += sizeof ( FILE_ALLOCATED_RANGE_BUFFER ) ;
  1067. }
  1068. }
  1069. if ( pbuc->dwSparseMapOffset != pbuc->dwSparseMapSize ) { // only true at backup
  1070. pbuc->fSparseBlockStart = TRUE ;
  1071. pbuc->cbHeader = 0 ;
  1072. pbuc->liStreamOffset = 0;
  1073. } else {
  1074. if ( !pbuc->fSparseHandAlt && (pbuc->hAlternate != NULL)) {
  1075. CloseHandle(pbuc->hAlternate); // releases any locks
  1076. pbuc->hAlternate = NULL;
  1077. }
  1078. pbuc->cbHeader = 0;
  1079. pbuc->fStreamStart = TRUE;
  1080. pbuc->fSparseBlockStart = TRUE;
  1081. pbuc->liStreamOffset = 0; // for BackupWrite
  1082. if (!pbuc->fMultiStreamType) { // for BackupRead
  1083. pbuc->StreamIndex++;
  1084. pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex] ;
  1085. pbuc->NamesReady = FALSE;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. // Routine Description:
  1091. //
  1092. // Data can be Backed up from an object using BackupRead.
  1093. //
  1094. // This API is used to read data from an object. After the
  1095. // read completes, the file pointer is adjusted by the number of bytes
  1096. // actually read. A return value of TRUE coupled with a bytes read of
  1097. // 0 indicates that end of file has been reached.
  1098. //
  1099. // Arguments:
  1100. //
  1101. // hFile - Supplies an open handle to a file that is to be read. The
  1102. // file handle must have been created with GENERIC_READ access.
  1103. //
  1104. // lpBuffer - Supplies the address of a buffer to receive the data read
  1105. // from the file.
  1106. //
  1107. // nNumberOfBytesToRead - Supplies the number of bytes to read from the
  1108. // file.
  1109. //
  1110. // lpNumberOfBytesRead - Returns the number of bytes read by this call.
  1111. // This parameter is always set to 0 before doing any IO or error
  1112. // checking.
  1113. //
  1114. // bAbort - If TRUE, then all resources associated with the context will
  1115. // be released.
  1116. //
  1117. // bProcessSecurity - If TRUE, then the NTFS ACL data will be read.
  1118. // If FALSE, then the ACL stream will be skipped.
  1119. //
  1120. // lpContext - Points to a buffer pointer setup and maintained by
  1121. // BackupRead.
  1122. //
  1123. //
  1124. // Return Value:
  1125. //
  1126. // TRUE - The operation was successul.
  1127. //
  1128. // FALSE - The operation failed. Extended error status is available
  1129. // using GetLastError.
  1130. //
  1131. //
  1132. // NOTE:
  1133. // The NT File Replication Service (NTFRS) performs an MD5 checksum on the
  1134. // stream of data returned by BackupRead(). If the sequence of file information
  1135. // returned changes then two machines, one downlevel and one uplevel will
  1136. // compute different MD5 checksums for the same file data. Under certain
  1137. // conditions this will cause needless file replication. Bear this in mind
  1138. // if a change in the returned data sequence is contemplated. The sources for
  1139. // NTFRS are in \nt\private\net\svcimgs\ntrepl.
  1140. //
  1141. BOOL WINAPI
  1142. BackupRead(
  1143. HANDLE hFile,
  1144. LPBYTE lpBuffer,
  1145. DWORD nNumberOfBytesToRead,
  1146. LPDWORD lpNumberOfBytesRead,
  1147. BOOL bAbort,
  1148. BOOL bProcessSecurity,
  1149. LPVOID *lpContext)
  1150. {
  1151. BACKUPCONTEXT *pbuc;
  1152. BACKUPIOFRAME bif;
  1153. BOOL fSuccess = FALSE;
  1154. IO_STATUS_BLOCK iosb ;
  1155. pbuc = *lpContext;
  1156. bif.pIoBuffer = lpBuffer;
  1157. bif.cbRequest = nNumberOfBytesToRead;
  1158. bif.pcbTransferred = lpNumberOfBytesRead;
  1159. bif.fProcessSecurity = (BOOLEAN)bProcessSecurity;
  1160. if (bAbort) {
  1161. if (pbuc != NULL) {
  1162. ResetAccessDate( hFile ) ;
  1163. FreeContext(lpContext);
  1164. }
  1165. return TRUE;
  1166. }
  1167. *bif.pcbTransferred = 0;
  1168. if (pbuc == INVALID_HANDLE_VALUE || bif.cbRequest == 0) {
  1169. return TRUE;
  1170. }
  1171. if (pbuc != NULL && mwStreamList[pbuc->StreamIndex] == BACKUP_INVALID) {
  1172. ResetAccessDate( hFile ) ;
  1173. FreeContext(lpContext);
  1174. return TRUE;
  1175. }
  1176. // Allocate our Context Control Block on first call.
  1177. if (pbuc == NULL) {
  1178. pbuc = AllocContext(CBMIN_BUFFER); // Alloc initial buffer
  1179. // ok, we allocated the context, Lets initialize it.
  1180. if (pbuc != NULL) {
  1181. NTSTATUS Status ;
  1182. FILE_BASIC_INFORMATION fbi;
  1183. Status = NtQueryInformationFile(
  1184. hFile,
  1185. &iosb,
  1186. &fbi,
  1187. sizeof(fbi),
  1188. FileBasicInformation );
  1189. if ( NT_SUCCESS( Status ) ) {
  1190. pbuc->fAttribs = fbi.FileAttributes ;
  1191. } else {
  1192. BaseSetLastNTError( Status );
  1193. return FALSE ;
  1194. }
  1195. }
  1196. }
  1197. if (pbuc != NULL) {
  1198. *lpContext = pbuc;
  1199. do {
  1200. if (pbuc->fStreamStart) {
  1201. pbuc->head.Size.QuadPart = 0;
  1202. pbuc->liStreamOffset = 0;
  1203. pbuc->dwSparseMapOffset = 0;
  1204. pbuc->dwSparseMapSize = 0;
  1205. pbuc->fMultiStreamType = FALSE;
  1206. }
  1207. fSuccess = TRUE;
  1208. switch (mwStreamList[pbuc->StreamIndex]) {
  1209. case BACKUP_DATA:
  1210. fSuccess = BackupReadData(hFile, pbuc, &bif);
  1211. break;
  1212. case BACKUP_ALTERNATE_DATA:
  1213. fSuccess = BackupReadAlternateData(hFile, pbuc, &bif);
  1214. break;
  1215. case BACKUP_EA_DATA:
  1216. fSuccess = BackupReadEaData(hFile, pbuc, &bif);
  1217. break;
  1218. case BACKUP_OBJECT_ID:
  1219. fSuccess = BackupReadObjectId(hFile, pbuc, &bif);
  1220. break;
  1221. case BACKUP_REPARSE_DATA:
  1222. fSuccess = BackupReadReparseData(hFile, pbuc, &bif);
  1223. break;
  1224. case BACKUP_SECURITY_DATA:
  1225. fSuccess = BackupReadSecurityData(hFile, pbuc, &bif);
  1226. break;
  1227. default:
  1228. pbuc->StreamIndex++;
  1229. pbuc->fStreamStart = TRUE;
  1230. break;
  1231. }
  1232. // if we're in the phase of reading the header, copy the header
  1233. if (pbuc->liStreamOffset < pbuc->cbHeader) {
  1234. DWORD cbrequest;
  1235. // Send the current stream header;
  1236. cbrequest =
  1237. (ULONG)min( pbuc->cbHeader - pbuc->liStreamOffset,
  1238. bif.cbRequest);
  1239. RtlCopyMemory(
  1240. bif.pIoBuffer,
  1241. (BYTE *) &pbuc->head + pbuc->liStreamOffset,
  1242. cbrequest);
  1243. ReportTransfer(pbuc, &bif, cbrequest);
  1244. }
  1245. //
  1246. // if we are at the end of a stream then
  1247. // start at the beginning of the next stream
  1248. //
  1249. if (pbuc->liStreamOffset >= pbuc->cbHeader) {
  1250. BackupTestRestartStream(pbuc);
  1251. }
  1252. } while (fSuccess &&
  1253. mwStreamList[pbuc->StreamIndex] != BACKUP_INVALID &&
  1254. bif.cbRequest != 0);
  1255. }
  1256. if (fSuccess && *bif.pcbTransferred == 0) {
  1257. ResetAccessDate( hFile ) ;
  1258. FreeContext(lpContext);
  1259. }
  1260. return(fSuccess);
  1261. }
  1262. // Routine Description:
  1263. //
  1264. // Data can be skiped during BackupRead or BackupWrite by using
  1265. // BackupSeek.
  1266. //
  1267. // This API is used to seek forward from the current position the
  1268. // specified number of bytes. This function does not seek over a
  1269. // stream header. The number of bytes actually seeked is returned.
  1270. // If a caller wants to seek to the start of the next stream it can
  1271. // pass 0xffffffff, 0xffffffff as the amount to seek. The number of
  1272. // bytes actually skiped over is returned.
  1273. //
  1274. // Arguments:
  1275. //
  1276. // hFile - Supplies an open handle to a file that is to be read. The
  1277. // file handle must have been created with GENERIC_READ or
  1278. // GENERIC_WRITE access.
  1279. //
  1280. // dwLowBytesToSeek - Specifies the low 32 bits of the number of bytes
  1281. // requested to seek.
  1282. //
  1283. // dwHighBytesToSeek - Specifies the high 32 bits of the number of bytes
  1284. // requested to seek.
  1285. //
  1286. // lpdwLowBytesSeeked - Points to the buffer where the low 32 bits of the
  1287. // actual number of bytes to seek is to be placed.
  1288. //
  1289. // lpdwHighBytesSeeked - Points to the buffer where the high 32 bits of the
  1290. // actual number of bytes to seek is to be placed.
  1291. //
  1292. // bAbort - If true, then all resources associated with the context will
  1293. // be released.
  1294. //
  1295. // lpContext - Points to a buffer pointer setup and maintained by
  1296. // BackupRead.
  1297. //
  1298. //
  1299. // Return Value:
  1300. //
  1301. // TRUE - The operation successfuly seeked the requested number of bytes.
  1302. //
  1303. // FALSE - The requested number of bytes could not be seeked. The number
  1304. // of bytes actually seeked is returned.
  1305. BOOL WINAPI
  1306. BackupSeek(
  1307. HANDLE hFile,
  1308. DWORD dwLowBytesToSeek,
  1309. DWORD dwHighBytesToSeek,
  1310. LPDWORD lpdwLowBytesSeeked,
  1311. LPDWORD lpdwHighBytesSeeked,
  1312. LPVOID *lpContext)
  1313. {
  1314. BACKUPCONTEXT *pbuc;
  1315. LONGLONG licbRemain;
  1316. LARGE_INTEGER licbRequest;
  1317. BOOL fSuccess;
  1318. LARGE_INTEGER sparse_bytes ;
  1319. pbuc = *lpContext;
  1320. sparse_bytes.QuadPart = 0 ;
  1321. *lpdwHighBytesSeeked = 0;
  1322. *lpdwLowBytesSeeked = 0;
  1323. if (pbuc == INVALID_HANDLE_VALUE || pbuc == NULL || pbuc->fStreamStart) {
  1324. return FALSE;
  1325. }
  1326. if (pbuc->liStreamOffset < pbuc->cbHeader) {
  1327. return FALSE;
  1328. }
  1329. //
  1330. // If we made it here, we are in the middle of a stream
  1331. //
  1332. licbRemain = ComputeRemainingSize( pbuc );
  1333. licbRequest.LowPart = dwLowBytesToSeek;
  1334. licbRequest.HighPart = dwHighBytesToSeek & 0x7fffffff;
  1335. if (licbRequest.QuadPart > licbRemain) {
  1336. licbRequest.QuadPart = licbRemain;
  1337. }
  1338. fSuccess = TRUE;
  1339. switch (pbuc->head.dwStreamId) {
  1340. case BACKUP_EA_DATA:
  1341. case BACKUP_SECURITY_DATA:
  1342. case BACKUP_OBJECT_ID :
  1343. case BACKUP_REPARSE_DATA :
  1344. // assume less than 2gig of data
  1345. break;
  1346. case BACKUP_SPARSE_BLOCK :
  1347. if ( pbuc->liStreamOffset < sizeof(LARGE_INTEGER) ) {
  1348. sparse_bytes.QuadPart = ( sizeof(LARGE_INTEGER) - pbuc->liStreamOffset ) ;
  1349. if ( sparse_bytes.QuadPart < licbRequest.QuadPart ) {
  1350. licbRequest.QuadPart -= sparse_bytes.QuadPart ;
  1351. } else {
  1352. licbRequest.QuadPart = 0 ;
  1353. }
  1354. }
  1355. case BACKUP_DATA:
  1356. case BACKUP_ALTERNATE_DATA:
  1357. {
  1358. LARGE_INTEGER liCurPos;
  1359. LARGE_INTEGER liNewPos;
  1360. HANDLE hf;
  1361. // set up the correct handle to seek with
  1362. if (pbuc->head.dwStreamId == BACKUP_DATA) {
  1363. hf = hFile;
  1364. }
  1365. else {
  1366. hf = pbuc->hAlternate;
  1367. }
  1368. // first, let's get the current position
  1369. liCurPos.HighPart = 0;
  1370. liCurPos.LowPart = SetFilePointer(
  1371. hf,
  1372. 0,
  1373. &liCurPos.HighPart,
  1374. FILE_CURRENT);
  1375. // Now seek the requested number of bytes
  1376. liNewPos.HighPart = licbRequest.HighPart;
  1377. liNewPos.LowPart = SetFilePointer(
  1378. hf,
  1379. licbRequest.LowPart,
  1380. &liNewPos.HighPart,
  1381. FILE_CURRENT);
  1382. // Assume that we seek the requested amount because if we do not,
  1383. // subsequent reads will fail and the caller will never be able
  1384. // to read to the next stream.
  1385. break;
  1386. }
  1387. default:
  1388. break;
  1389. }
  1390. if (dwHighBytesToSeek != (DWORD) licbRequest.HighPart ||
  1391. dwLowBytesToSeek != licbRequest.LowPart) {
  1392. fSuccess = FALSE;
  1393. }
  1394. licbRequest.QuadPart += sparse_bytes.QuadPart ;
  1395. pbuc->liStreamOffset += licbRequest.QuadPart ;
  1396. *lpdwLowBytesSeeked = licbRequest.LowPart;
  1397. *lpdwHighBytesSeeked = licbRequest.HighPart;
  1398. BackupTestRestartStream(pbuc);
  1399. if (!fSuccess) {
  1400. SetLastError(ERROR_SEEK);
  1401. }
  1402. return(fSuccess);
  1403. }
  1404. BOOL
  1405. BackupWriteHeader(BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif, DWORD cbHeader)
  1406. /*++
  1407. Routine Description:
  1408. This is an internal routine that fills our internal backup header
  1409. from the user's data.
  1410. Arguments:
  1411. pbuc - CONTEXT of call
  1412. pbif - IOCONTEXT of call
  1413. cbHeader - size of header to fill
  1414. Return Value:
  1415. None.
  1416. --*/
  1417. {
  1418. //
  1419. // Determine how much data we can transfer into our header.
  1420. //
  1421. DWORD cbrequest =
  1422. (DWORD) min( pbif->cbRequest, cbHeader - pbuc->liStreamOffset );
  1423. //
  1424. // Copy from user buffer into header
  1425. //
  1426. if ( pbuc->liStreamOffset+cbrequest > CWCMAX_STREAMNAME + CB_NAMELESSHEADER ) {
  1427. return FALSE ;
  1428. }
  1429. RtlCopyMemory(
  1430. (CHAR *) &pbuc->head + pbuc->liStreamOffset,
  1431. pbif->pIoBuffer,
  1432. cbrequest);
  1433. //
  1434. // Update transfer statistics
  1435. //
  1436. ReportTransfer(pbuc, pbif, cbrequest);
  1437. //
  1438. // If we've filled up the header, mark the header as complete
  1439. // even though we might need more if names are present
  1440. //
  1441. if (pbuc->liStreamOffset == cbHeader) {
  1442. pbuc->cbHeader = cbHeader;
  1443. }
  1444. return TRUE ;
  1445. }
  1446. typedef enum {
  1447. BRB_FAIL,
  1448. BRB_DONE,
  1449. BRB_MORE,
  1450. } BUFFERSTATUS;
  1451. BUFFERSTATUS
  1452. BackupWriteBuffer(BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1453. /*++
  1454. Routine Description:
  1455. This is an internal routine that fills our internal buffer
  1456. from the user's data.
  1457. Arguments:
  1458. pbuc - CONTEXT of call
  1459. pbif - IOCONTEXT of call
  1460. Return Value:
  1461. BRB_FAIL if an error occurred (out of memory)
  1462. BRB_DONE if buffer is full or was successfully filled
  1463. BRB_MORE if buffer is partially full
  1464. --*/
  1465. {
  1466. DWORD cbrequest;
  1467. //
  1468. // If we're starting out on the buffer, we make sure
  1469. // we have a buffer to contain all of the data since
  1470. // the Nt calls we'll use must have all the data
  1471. // present
  1472. //
  1473. if (pbuc->fStreamStart) {
  1474. pbuc->fStreamStart = FALSE;
  1475. if (pbuc->DataBuffer.BufferSize < pbuc->head.Size.QuadPart &&
  1476. !GrowBuffer( &pbuc->DataBuffer, pbuc->head.Size.LowPart )) {
  1477. return(BRB_FAIL);
  1478. }
  1479. }
  1480. //
  1481. // Determine how much data from the user buffer is
  1482. // needed to fill our buffer
  1483. //
  1484. cbrequest = ComputeRequestSize( pbuc, pbif->cbRequest );
  1485. //
  1486. // Fill in the next portion of the buffer
  1487. //
  1488. RtlCopyMemory(
  1489. pbuc->DataBuffer.Buffer + pbuc->liStreamOffset - pbuc->cbHeader,
  1490. pbif->pIoBuffer,
  1491. cbrequest);
  1492. //
  1493. // Update transfer statistics
  1494. //
  1495. ReportTransfer(pbuc, pbif, cbrequest);
  1496. //
  1497. // If we've entirely filled the buffer, let our caller know
  1498. //
  1499. return ComputeRemainingSize( pbuc ) == 0 ? BRB_DONE : BRB_MORE;
  1500. }
  1501. BOOL
  1502. BackupWriteSparse(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1503. /*++
  1504. Routine Description:
  1505. This is an internal routine that writes sparse block of stream data from
  1506. the user's buffer into the output handle. The BACKUPCONTEXT contains
  1507. the total length of data to be output.
  1508. Arguments:
  1509. hFile - output file handle
  1510. pbuc - CONTEXT of call
  1511. pbif - IOCONTEXT of call
  1512. Return Value:
  1513. TRUE if data was successfully written, FALSE otherwise.
  1514. --*/
  1515. {
  1516. LARGE_INTEGER licbFile ;
  1517. DWORD cbrequest;
  1518. DWORD cbtransferred;
  1519. BOOL fSuccess;
  1520. if ( pbuc->fSparseBlockStart ) {
  1521. RtlCopyMemory( &pbuc->cbSparseOffset, pbuc->head.cStreamName, sizeof( LARGE_INTEGER ) ) ;
  1522. licbFile = pbuc->cbSparseOffset;
  1523. licbFile.LowPart = SetFilePointer( pbuc->fSparseHandAlt?pbuc->hAlternate:hFile,
  1524. licbFile.LowPart,
  1525. &licbFile.HighPart,
  1526. FILE_BEGIN );
  1527. if ( licbFile.QuadPart != pbuc->cbSparseOffset.QuadPart ) {
  1528. return FALSE ;
  1529. }
  1530. if ( pbuc->head.Size.QuadPart == sizeof( LARGE_INTEGER ) ) {
  1531. SetEndOfFile(pbuc->fSparseHandAlt?pbuc->hAlternate:hFile) ;
  1532. }
  1533. pbuc->fSparseBlockStart = FALSE ;
  1534. }
  1535. //
  1536. // Determine how much data from the user buffer is
  1537. // needed to be written into the stream and perform
  1538. // the transfer.
  1539. //
  1540. cbrequest = ComputeRequestSize(pbuc, pbif->cbRequest);
  1541. fSuccess = WriteFile(
  1542. pbuc->fSparseHandAlt?pbuc->hAlternate:hFile,
  1543. pbif->pIoBuffer,
  1544. cbrequest,
  1545. &cbtransferred,
  1546. NULL);
  1547. //
  1548. // Update transfer statistics
  1549. //
  1550. ReportTransfer(pbuc, pbif, cbtransferred);
  1551. return(fSuccess);
  1552. return TRUE ;
  1553. }
  1554. BOOL
  1555. BackupWriteStream(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1556. /*++
  1557. Routine Description:
  1558. This is an internal routine that writes stream data from the user's
  1559. buffer into the output handle. The BACKUPCONTEXT contains the total
  1560. length of data to be output.
  1561. Arguments:
  1562. hFile - output file handle
  1563. pbuc - CONTEXT of call
  1564. pbif - IOCONTEXT of call
  1565. Return Value:
  1566. TRUE if data was successfully written, FALSE otherwise.
  1567. --*/
  1568. {
  1569. DWORD cbrequest;
  1570. DWORD cbtransferred;
  1571. BOOL fSuccess;
  1572. IO_STATUS_BLOCK iosb;
  1573. if ( pbuc->fStreamStart ) {
  1574. if ( pbuc->head.dwStreamAttributes & STREAM_SPARSE_ATTRIBUTE ) {
  1575. // if it was sparse when be backed it up make is sparse again.
  1576. NtFsControlFile( hFile,
  1577. NULL, // overlapped event handle
  1578. NULL, // Apc routine
  1579. NULL, // overlapped structure
  1580. &iosb,
  1581. FSCTL_SET_SPARSE ,
  1582. NULL,
  1583. 0,
  1584. NULL,
  1585. 0 ) ;
  1586. } else {
  1587. LARGE_INTEGER end_of_file ;
  1588. end_of_file.QuadPart = pbuc->head.Size.QuadPart ;
  1589. SetFilePointer( hFile,
  1590. end_of_file.LowPart,
  1591. &end_of_file.HighPart,
  1592. FILE_BEGIN );
  1593. SetEndOfFile(hFile) ;
  1594. end_of_file.QuadPart = 0 ;
  1595. SetFilePointer( hFile,
  1596. end_of_file.LowPart,
  1597. &end_of_file.HighPart,
  1598. FILE_BEGIN );
  1599. }
  1600. pbuc->fStreamStart = FALSE;
  1601. }
  1602. //
  1603. // Determine how much data from the user buffer is
  1604. // needed to be written into the stream and perform
  1605. // the transfer.
  1606. //
  1607. cbrequest = ComputeRequestSize(pbuc, pbif->cbRequest);
  1608. fSuccess = WriteFile(
  1609. hFile,
  1610. pbif->pIoBuffer,
  1611. cbrequest,
  1612. &cbtransferred,
  1613. NULL);
  1614. //
  1615. // Update transfer statistics
  1616. //
  1617. ReportTransfer(pbuc, pbif, cbtransferred);
  1618. return(fSuccess);
  1619. }
  1620. BOOL
  1621. BackupWriteAlternateData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1622. /*++
  1623. Routine Description:
  1624. This is an internal routine that overwrites an alternate data stream with
  1625. data from the user's buffer.
  1626. Arguments:
  1627. hFile - handle to the file itself. This is not the handle to the stream
  1628. being overwritten.
  1629. pbuc - CONTEXT of call. This contains the name of the stream.
  1630. pbif - IOCONTEXT of call
  1631. Return Value:
  1632. TRUE if data was successfully written, FALSE otherwise.
  1633. --*/
  1634. {
  1635. //
  1636. // If we are just starting out on this stream then attempt to
  1637. // overwrite the new stream.
  1638. //
  1639. if (pbuc->fStreamStart) {
  1640. NTSTATUS Status;
  1641. UNICODE_STRING strName;
  1642. OBJECT_ATTRIBUTES oa;
  1643. IO_STATUS_BLOCK iosb;
  1644. DWORD reparse_flg = 0 ;
  1645. strName.Length = (USHORT) pbuc->head.dwStreamNameSize;
  1646. strName.MaximumLength = strName.Length;
  1647. strName.Buffer = pbuc->head.cStreamName;
  1648. if (pbuc->hAlternate != INVALID_HANDLE_VALUE) {
  1649. CloseHandle(pbuc->hAlternate);
  1650. pbuc->hAlternate = INVALID_HANDLE_VALUE;
  1651. pbuc->fSparseHandAlt = FALSE ;
  1652. }
  1653. if (pbuc->fAttribs & FILE_ATTRIBUTE_REPARSE_POINT ) {
  1654. reparse_flg = FILE_OPEN_REPARSE_POINT ;
  1655. }
  1656. InitializeObjectAttributes(
  1657. &oa,
  1658. &strName,
  1659. OBJ_CASE_INSENSITIVE,
  1660. hFile,
  1661. NULL);
  1662. Status = NtCreateFile(
  1663. &pbuc->hAlternate,
  1664. FILE_WRITE_DATA | SYNCHRONIZE,
  1665. &oa,
  1666. &iosb,
  1667. NULL,
  1668. FILE_ATTRIBUTE_NORMAL,
  1669. FILE_SHARE_READ | FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  1670. FILE_OVERWRITE_IF,
  1671. FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | reparse_flg,
  1672. NULL,
  1673. 0L);
  1674. //
  1675. // If we failed, map the error, record the failure, and return failure.
  1676. //
  1677. if (!NT_SUCCESS( Status )) {
  1678. BaseSetLastNTError( Status );
  1679. pbuc->fAccessError = TRUE;
  1680. return FALSE;
  1681. }
  1682. if ( pbuc->head.dwStreamAttributes & STREAM_SPARSE_ATTRIBUTE ) {
  1683. pbuc->fSparseHandAlt = TRUE ;
  1684. // if it was sparse when be backed it up make is sparse again.
  1685. NtFsControlFile( pbuc->hAlternate,
  1686. NULL, // overlapped event handle
  1687. NULL, // Apc routine
  1688. NULL, // overlapped structure
  1689. &iosb,
  1690. FSCTL_SET_SPARSE ,
  1691. NULL,
  1692. 0,
  1693. NULL,
  1694. 0 ) ;
  1695. }
  1696. // don't reset stream start because WriteStream will do it.
  1697. }
  1698. //
  1699. // If we have no handle for the transfer, record this failure
  1700. // and return failure.
  1701. //
  1702. if (pbuc->hAlternate == INVALID_HANDLE_VALUE) {
  1703. pbuc->fAccessError = TRUE;
  1704. return FALSE;
  1705. }
  1706. //
  1707. // Let the normal stream copy perform the transfer
  1708. //
  1709. return BackupWriteStream( pbuc->hAlternate, pbuc, pbif );
  1710. }
  1711. BOOL
  1712. BackupWriteEaData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1713. /*++
  1714. Routine Description:
  1715. This is an internal routine that writes EA data on the file from
  1716. the user's buffer
  1717. Arguments:
  1718. hFile - handle to output file
  1719. pbuc - CONTEXT of call
  1720. pbif - IOCONTEXT of call
  1721. Return Value:
  1722. TRUE if EA data was successfully written, FALSE otherwise.
  1723. --*/
  1724. {
  1725. NTSTATUS Status;
  1726. IO_STATUS_BLOCK iosb;
  1727. //
  1728. // Attempt to fill up the buffer from the input.
  1729. //
  1730. switch (BackupWriteBuffer( pbuc, pbif )) {
  1731. default:
  1732. case BRB_FAIL:
  1733. return FALSE;
  1734. case BRB_MORE:
  1735. return TRUE;
  1736. case BRB_DONE:
  1737. break;
  1738. }
  1739. //
  1740. // The buffer is now completely filled with our EA data. Set the
  1741. // EA data on the file.
  1742. //
  1743. Status = NtSetEaFile(
  1744. hFile,
  1745. &iosb,
  1746. pbuc->DataBuffer.Buffer,
  1747. pbuc->head.Size.LowPart );
  1748. //
  1749. // If we failed, map the error and return failure
  1750. //
  1751. if (!NT_SUCCESS( Status )) {
  1752. BaseSetLastNTError( Status );
  1753. return FALSE;
  1754. }
  1755. return TRUE;
  1756. }
  1757. BOOL
  1758. BackupWriteReparseData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1759. /*++
  1760. Routine Description:
  1761. This is an internal routine that writes Reparse data on the file from
  1762. the user's buffer
  1763. Arguments:
  1764. hFile - handle to output file
  1765. pbuc - CONTEXT of call
  1766. pbif - IOCONTEXT of call
  1767. Return Value:
  1768. TRUE if EA data was successfully written, FALSE otherwise.
  1769. --*/
  1770. {
  1771. NTSTATUS Status;
  1772. IO_STATUS_BLOCK iosb;
  1773. DWORD *rp_tag_ptr ;
  1774. //
  1775. // Attempt to fill up the buffer from the input.
  1776. //
  1777. switch (BackupWriteBuffer( pbuc, pbif )) {
  1778. default:
  1779. case BRB_FAIL:
  1780. return FALSE;
  1781. case BRB_MORE:
  1782. return TRUE;
  1783. case BRB_DONE:
  1784. break;
  1785. }
  1786. //
  1787. // The buffer is now completely filled with our Reparse data. Set the
  1788. // Reparse data on the file.
  1789. //
  1790. rp_tag_ptr = (DWORD *)(pbuc->DataBuffer.Buffer) ;
  1791. pbuc->fAttribs |= FILE_ATTRIBUTE_REPARSE_POINT ;
  1792. Status = NtFsControlFile( hFile,
  1793. NULL, // overlapped event handle
  1794. NULL, // Apc routine
  1795. NULL, // overlapped structure
  1796. &iosb,
  1797. FSCTL_SET_REPARSE_POINT,
  1798. pbuc->DataBuffer.Buffer,
  1799. pbuc->head.Size.LowPart,
  1800. NULL,
  1801. 0 ) ;
  1802. //
  1803. // If we failed, map the error and return failure
  1804. //
  1805. if (!NT_SUCCESS( Status )) {
  1806. BaseSetLastNTError( Status );
  1807. return FALSE;
  1808. }
  1809. return TRUE;
  1810. }
  1811. BOOL
  1812. BackupWriteObjectId(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1813. /*++
  1814. Routine Description:
  1815. This is an internal routine that writes the Object IDa on the file from
  1816. the user's buffer. Birth ids are made reborn. i.e. the volume id component
  1817. of the birth id is changed to the current volume's id, and the object id
  1818. component of the birth id is changed to the current object id.
  1819. Arguments:
  1820. hFile - handle to output file
  1821. pbuc - CONTEXT of call
  1822. pbif - IOCONTEXT of call
  1823. Return Value:
  1824. TRUE if Object ID was successfully written, FALSE otherwise.
  1825. --*/
  1826. {
  1827. IO_STATUS_BLOCK iosb;
  1828. NTSTATUS Status ;
  1829. FILE_FS_OBJECTID_INFORMATION fsobOID;
  1830. GUID guidZero;
  1831. //
  1832. // Attempt to fill up the buffer from the input.
  1833. //
  1834. switch (BackupWriteBuffer( pbuc, pbif )) {
  1835. default:
  1836. case BRB_FAIL:
  1837. return FALSE;
  1838. case BRB_MORE:
  1839. return TRUE;
  1840. case BRB_DONE:
  1841. break;
  1842. }
  1843. //
  1844. // Zero out the birth ID (the extended 48 bytes)
  1845. //
  1846. memset(&pbuc->DataBuffer.Buffer[sizeof(GUID)], 0, 3*sizeof(GUID));
  1847. //
  1848. // Set the ID on the file.
  1849. //
  1850. Status = NtFsControlFile( hFile,
  1851. NULL, // overlapped event handle
  1852. NULL, // Apc routine
  1853. NULL, // overlapped structure
  1854. &iosb,
  1855. FSCTL_SET_OBJECT_ID,
  1856. pbuc->DataBuffer.Buffer,
  1857. pbuc->head.Size.LowPart,
  1858. NULL,
  1859. 0);
  1860. //
  1861. // Ignore errors
  1862. //
  1863. if (!NT_SUCCESS( Status )) {
  1864. BaseSetLastNTError( Status );
  1865. }
  1866. return( TRUE );
  1867. }
  1868. BOOL
  1869. BackupWriteSecurityData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1870. /*++
  1871. Routine Description:
  1872. This is an internal routine that sets security information on the
  1873. file from data in the user's buffer.
  1874. Arguments:
  1875. hFile - handle to output file
  1876. pbuc - CONTEXT of call
  1877. pbif - IOCONTEXT of call
  1878. Return Value:
  1879. TRUE if security was successfully written, FALSE otherwise.
  1880. --*/
  1881. {
  1882. NTSTATUS Status;
  1883. SECURITY_INFORMATION si;
  1884. //
  1885. // Attempt to fill up the buffer from the input.
  1886. //
  1887. switch (BackupWriteBuffer(pbuc, pbif)) {
  1888. default:
  1889. case BRB_FAIL:
  1890. return FALSE;
  1891. case BRB_MORE:
  1892. return TRUE;
  1893. case BRB_DONE:
  1894. break;
  1895. }
  1896. //
  1897. // The buffer is now completely filled with our security data. If we
  1898. // are to ignore it, then return success
  1899. //
  1900. if (!pbif->fProcessSecurity) {
  1901. return TRUE;
  1902. }
  1903. //
  1904. // Find out what security information is present so we know what to
  1905. // set.
  1906. si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION;
  1907. if (((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control & SE_DACL_PRESENT) {
  1908. si |= DACL_SECURITY_INFORMATION;
  1909. }
  1910. if (((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control & SE_SACL_PRESENT) {
  1911. si |= SACL_SECURITY_INFORMATION;
  1912. }
  1913. //
  1914. // If the security descriptor has AUTO_INHERITED set, set the appropriate REQ bits.
  1915. //
  1916. if (((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control & SE_DACL_AUTO_INHERITED) {
  1917. ((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  1918. }
  1919. if (((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control & SE_SACL_AUTO_INHERITED) {
  1920. ((PISECURITY_DESCRIPTOR) pbuc->DataBuffer.Buffer)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  1921. }
  1922. Status = NtSetSecurityObject( hFile, si, pbuc->DataBuffer.Buffer );
  1923. if (!NT_SUCCESS( Status )) {
  1924. NTSTATUS Status2;
  1925. //
  1926. // If that didn't work, the caller is probably not running as Backup
  1927. // Operator, so we can't set the owner and group. Keep the current
  1928. // status code, and attempt to set the DACL and SACL while ignoring
  1929. // failures.
  1930. //
  1931. if (si & SACL_SECURITY_INFORMATION) {
  1932. NtSetSecurityObject(
  1933. hFile,
  1934. SACL_SECURITY_INFORMATION,
  1935. pbuc->DataBuffer.Buffer );
  1936. }
  1937. if (si & DACL_SECURITY_INFORMATION) {
  1938. Status = NtSetSecurityObject(
  1939. hFile,
  1940. DACL_SECURITY_INFORMATION,
  1941. pbuc->DataBuffer.Buffer);
  1942. }
  1943. Status2 = NtSetSecurityObject(
  1944. hFile,
  1945. OWNER_SECURITY_INFORMATION |
  1946. GROUP_SECURITY_INFORMATION,
  1947. pbuc->DataBuffer.Buffer);
  1948. if (NT_SUCCESS(Status)) {
  1949. Status = Status2;
  1950. }
  1951. }
  1952. if (!NT_SUCCESS(Status)) {
  1953. BaseSetLastNTError(Status);
  1954. return FALSE;
  1955. }
  1956. return TRUE;
  1957. }
  1958. BOOL
  1959. BackupWriteLinkData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif)
  1960. /*++
  1961. Routine Description:
  1962. This is an internal routine that establishes links based on the
  1963. user's data.
  1964. Arguments:
  1965. hFile - handle of file being restored
  1966. pbuc - CONTEXT of call
  1967. pbif - IOCONTEXT of call
  1968. Return Value:
  1969. TRUE if link was successfully established, FALSE otherwise.
  1970. --*/
  1971. {
  1972. FILE_LINK_INFORMATION *pfli;
  1973. WCHAR *pwc;
  1974. WCHAR *pwcSlash;
  1975. INT cbName;
  1976. INT cSlash;
  1977. WCHAR wcSave;
  1978. BOOL fSuccess;
  1979. //
  1980. // Attempt to fill up the buffer from the input.
  1981. //
  1982. switch (BackupWriteBuffer(pbuc, pbif)) {
  1983. default:
  1984. case BRB_FAIL:
  1985. return FALSE;
  1986. case BRB_MORE:
  1987. return TRUE;
  1988. case BRB_DONE:
  1989. break;
  1990. }
  1991. //
  1992. // The buffer is now completely filled with our link data.
  1993. // Find the last component of the name.
  1994. //
  1995. cSlash = 0;
  1996. pwcSlash = NULL;
  1997. pwc = (WCHAR *) pbuc->DataBuffer.Buffer;
  1998. cbName = sizeof(WCHAR);
  1999. while (*pwc != L'\0') {
  2000. if (*pwc == L'\\') {
  2001. pwcSlash = pwc;
  2002. cSlash++;
  2003. cbName = 0;
  2004. }
  2005. pwc++;
  2006. cbName += sizeof(WCHAR);
  2007. }
  2008. pfli = BackupAlloc( sizeof(*pfli) + cbName );
  2009. if (pfli == NULL) {
  2010. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  2011. return FALSE;
  2012. }
  2013. RtlCopyMemory( pfli->FileName, pwcSlash + 1, cbName );
  2014. pfli->FileNameLength = cbName - sizeof(WCHAR);
  2015. if (cSlash > 1) {
  2016. wcSave = L'\\';
  2017. }
  2018. else {
  2019. wcSave = *pwcSlash++;
  2020. }
  2021. *pwcSlash = L'\0';
  2022. //
  2023. // Open the parent of the link target
  2024. //
  2025. pfli->RootDirectory = CreateFileW(
  2026. (WCHAR *) pbuc->DataBuffer.Buffer,
  2027. GENERIC_WRITE | GENERIC_READ,
  2028. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  2029. NULL,
  2030. OPEN_EXISTING,
  2031. FILE_ATTRIBUTE_NORMAL| FILE_FLAG_BACKUP_SEMANTICS,
  2032. NULL );
  2033. *pwcSlash = wcSave;
  2034. pfli->ReplaceIfExists = TRUE;
  2035. fSuccess = TRUE;
  2036. if (pfli->RootDirectory == INVALID_HANDLE_VALUE) {
  2037. SetLastError( ERROR_FILE_NOT_FOUND );
  2038. fSuccess = FALSE;
  2039. }
  2040. else {
  2041. NTSTATUS Status;
  2042. IO_STATUS_BLOCK iosb;
  2043. Status = NtSetInformationFile(
  2044. hFile,
  2045. &iosb,
  2046. pfli,
  2047. sizeof(*pfli) + cbName,
  2048. FileLinkInformation );
  2049. CloseHandle( pfli->RootDirectory );
  2050. pfli->RootDirectory = INVALID_HANDLE_VALUE;
  2051. if (!NT_SUCCESS( Status )) {
  2052. BaseSetLastNTError( Status );
  2053. fSuccess = FALSE;
  2054. } else {
  2055. if (iosb.Information == FILE_OVERWRITTEN) {
  2056. SetLastError( ERROR_ALREADY_EXISTS );
  2057. } else {
  2058. SetLastError( 0 );
  2059. }
  2060. }
  2061. }
  2062. BackupFree( pfli );
  2063. return fSuccess;
  2064. }
  2065. // Routine Description:
  2066. //
  2067. // Data can be written to a file using BackupWrite.
  2068. //
  2069. // This API is used to Restore data to an object. After the
  2070. // write completes, the file pointer is adjusted by the number of bytes
  2071. // actually written.
  2072. //
  2073. // Unlike DOS, a NumberOfBytesToWrite value of zero does not truncate
  2074. // or extend the file. If this function is required, SetEndOfFile
  2075. // should be used.
  2076. //
  2077. // Arguments:
  2078. //
  2079. // hFile - Supplies an open handle to a file that is to be written. The
  2080. // file handle must have been created with GENERIC_WRITE access to
  2081. // the file.
  2082. //
  2083. // lpBuffer - Supplies the address of the data that is to be written to
  2084. // the file.
  2085. //
  2086. // nNumberOfBytesToWrite - Supplies the number of bytes to write to the
  2087. // file. Unlike DOS, a value of zero is interpreted a null write.
  2088. //
  2089. // lpNumberOfBytesWritten - Returns the number of bytes written by this
  2090. // call. Before doing any work or error processing, the API sets this
  2091. // to zero.
  2092. //
  2093. // bAbort - If true, then all resources associated with the context will
  2094. // be released.
  2095. //
  2096. // bProcessSecurity - If TRUE, then the NTFS ACL data will be written.
  2097. // If FALSE, then the ACL stream will be ignored.
  2098. //
  2099. // lpContext - Points to a buffer pointer setup and maintained by
  2100. // BackupRead.
  2101. //
  2102. //
  2103. // Return Value:
  2104. //
  2105. // TRUE - The operation was a success.
  2106. //
  2107. // FALSE - The operation failed. Extended error status is
  2108. // available using GetLastError.
  2109. BOOL WINAPI
  2110. BackupWrite(
  2111. HANDLE hFile,
  2112. LPBYTE lpBuffer,
  2113. DWORD nNumberOfBytesToWrite,
  2114. LPDWORD lpNumberOfBytesWritten,
  2115. BOOL bAbort,
  2116. BOOL bProcessSecurity,
  2117. LPVOID *lpContext)
  2118. {
  2119. BACKUPCONTEXT *pbuc;
  2120. BACKUPIOFRAME bif;
  2121. BOOL fSuccess = FALSE;
  2122. pbuc = *lpContext;
  2123. bif.pIoBuffer = lpBuffer;
  2124. bif.cbRequest = nNumberOfBytesToWrite;
  2125. bif.pcbTransferred = lpNumberOfBytesWritten;
  2126. bif.fProcessSecurity = (BOOLEAN)bProcessSecurity;
  2127. //
  2128. // Allocate our Context Control Block on first call.
  2129. //
  2130. if (bAbort) {
  2131. if (pbuc != NULL) {
  2132. FreeContext(lpContext);
  2133. }
  2134. return TRUE;
  2135. }
  2136. *bif.pcbTransferred = 0;
  2137. if (pbuc == INVALID_HANDLE_VALUE) {
  2138. return TRUE;
  2139. }
  2140. // Allocate our Context Control Block on first call.
  2141. if (pbuc == NULL) {
  2142. pbuc = AllocContext(0); // No initial buffer
  2143. //
  2144. // If we have no space then return failure
  2145. //
  2146. if (pbuc == NULL) {
  2147. return FALSE;
  2148. }
  2149. }
  2150. *lpContext = pbuc;
  2151. do {
  2152. DWORD cbrequest;
  2153. LONGLONG licbRemain;
  2154. //
  2155. // If we do not have a complete header, go
  2156. // fill it in.
  2157. //
  2158. if (pbuc->cbHeader == 0) {
  2159. pbuc->fMultiStreamType = TRUE ; //restore does not auto inc stream index.
  2160. pbuc->fStreamStart = TRUE ;
  2161. BackupWriteHeader(pbuc, &bif, CB_NAMELESSHEADER) ;
  2162. }
  2163. //
  2164. // If no more data, then exit
  2165. //
  2166. if (bif.cbRequest == 0) {
  2167. return TRUE;
  2168. }
  2169. //
  2170. // If a stream name was expected, go read it in
  2171. //
  2172. if (pbuc->cbHeader == CB_NAMELESSHEADER &&
  2173. pbuc->head.dwStreamNameSize != 0) {
  2174. if ( !BackupWriteHeader(
  2175. pbuc,
  2176. &bif,
  2177. pbuc->cbHeader + pbuc->head.dwStreamNameSize) )
  2178. {
  2179. SetLastError( ERROR_INVALID_DATA );
  2180. return FALSE ;
  2181. }
  2182. //
  2183. // If no more data then exit
  2184. //
  2185. if (bif.cbRequest == 0) {
  2186. return TRUE;
  2187. }
  2188. }
  2189. if ( ( pbuc->cbHeader == CB_NAMELESSHEADER ) &&
  2190. ( pbuc->head.dwStreamId == BACKUP_SPARSE_BLOCK ) ) {
  2191. BackupWriteHeader(
  2192. pbuc,
  2193. &bif,
  2194. pbuc->cbHeader + sizeof(LARGE_INTEGER) );
  2195. //
  2196. // If no more data then exit
  2197. //
  2198. if (bif.cbRequest == 0) {
  2199. if ( pbuc->cbHeader == CB_NAMELESSHEADER ) {
  2200. return TRUE;
  2201. }
  2202. }
  2203. }
  2204. //
  2205. // Determine amount of data remaining in user buffer
  2206. // that can be transferred as part of this section
  2207. // of the backup stream
  2208. //
  2209. cbrequest = ComputeRequestSize(pbuc, bif.cbRequest);
  2210. //
  2211. // Determine total amount of data left in this section
  2212. // of backup stream.
  2213. //
  2214. licbRemain = ComputeRemainingSize( pbuc );
  2215. //
  2216. // If we had an error in the transfer and we're done
  2217. // doing the transfer then pretend that we successfully
  2218. // completed the section.
  2219. //
  2220. if (pbuc->fAccessError && licbRemain == 0) {
  2221. ReportTransfer(pbuc, &bif, cbrequest);
  2222. continue;
  2223. }
  2224. //
  2225. // Begin or continue the transfer of data. We assume that there
  2226. // are no errors
  2227. //
  2228. pbuc->fAccessError = FALSE;
  2229. switch (pbuc->head.dwStreamId) {
  2230. case BACKUP_SPARSE_BLOCK :
  2231. fSuccess = BackupWriteSparse( hFile, pbuc, &bif ) ;
  2232. break ;
  2233. case BACKUP_DATA:
  2234. fSuccess = BackupWriteStream( hFile, pbuc, &bif );
  2235. break;
  2236. case BACKUP_ALTERNATE_DATA:
  2237. fSuccess = BackupWriteAlternateData( hFile, pbuc, &bif );
  2238. break;
  2239. case BACKUP_EA_DATA:
  2240. fSuccess = BackupWriteEaData( hFile, pbuc, &bif );
  2241. break;
  2242. case BACKUP_OBJECT_ID:
  2243. fSuccess = BackupWriteObjectId( hFile, pbuc, &bif );
  2244. break;
  2245. case BACKUP_REPARSE_DATA:
  2246. fSuccess = BackupWriteReparseData( hFile, pbuc, &bif );
  2247. break;
  2248. case BACKUP_SECURITY_DATA:
  2249. fSuccess = BackupWriteSecurityData( hFile, pbuc, &bif );
  2250. break;
  2251. case BACKUP_LINK:
  2252. fSuccess = BackupWriteLinkData( hFile, pbuc, &bif );
  2253. break;
  2254. default:
  2255. SetLastError(ERROR_INVALID_DATA);
  2256. fSuccess = FALSE;
  2257. break;
  2258. }
  2259. BackupTestRestartStream(pbuc);
  2260. } while (fSuccess && bif.cbRequest != 0);
  2261. if (fSuccess && *bif.pcbTransferred == 0) {
  2262. FreeContext(lpContext);
  2263. }
  2264. return(fSuccess);
  2265. }