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.

924 lines
23 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * NtfsStream.cpp
  8. *
  9. * Abstract:
  10. *
  11. * This file provides the Flat File IStream definition.
  12. *
  13. * Created:
  14. *
  15. * 4/26/1999 Mike Hillberg
  16. *
  17. \**************************************************************************/
  18. #include "precomp.hpp"
  19. #include "LargeInt.hpp"
  20. #include "time.h"
  21. #include "FileTime.hpp"
  22. #include "NtfsStream.hpp"
  23. IStream *
  24. CreateStreamOnFile(
  25. const OLECHAR * pwcsName,
  26. UINT access // GENERIC_READ and/or GENERIC_WRITE
  27. )
  28. {
  29. HANDLE hFile;
  30. FileStream * stream;
  31. UINT disposition;
  32. DWORD grfMode = STGM_SHARE_EXCLUSIVE;
  33. DWORD shareMode = 0;
  34. switch (access)
  35. {
  36. case GENERIC_READ:
  37. disposition = OPEN_EXISTING;
  38. shareMode = FILE_SHARE_READ;
  39. grfMode |= STGM_READ;
  40. break;
  41. case GENERIC_WRITE:
  42. disposition = CREATE_ALWAYS;
  43. grfMode |= STGM_WRITE;
  44. break;
  45. // Note that OPEN_ALWAYS does NOT clear existing file attributes (like size)
  46. case GENERIC_READ|GENERIC_WRITE:
  47. disposition = OPEN_ALWAYS;
  48. grfMode |= STGM_READWRITE;
  49. break;
  50. default:
  51. return NULL;
  52. }
  53. if (Globals::IsNt)
  54. {
  55. hFile = CreateFileW(pwcsName, access, shareMode, NULL,
  56. disposition, FILE_ATTRIBUTE_NORMAL, NULL);
  57. }
  58. else // Windows 9x - non-Unicode
  59. {
  60. AnsiStrFromUnicode nameStr(pwcsName);
  61. if (nameStr.IsValid())
  62. {
  63. hFile = CreateFileA(nameStr, access, shareMode, NULL,
  64. disposition, FILE_ATTRIBUTE_NORMAL, NULL);
  65. }
  66. else
  67. {
  68. hFile = INVALID_HANDLE_VALUE;
  69. }
  70. }
  71. if ((hFile != INVALID_HANDLE_VALUE) && (hFile != NULL))
  72. {
  73. stream = new FileStream();
  74. if (stream != NULL)
  75. {
  76. HRESULT hResult;
  77. hResult = stream->Init(hFile, grfMode, pwcsName);
  78. if (!FAILED(hResult))
  79. {
  80. return stream;
  81. }
  82. delete stream;
  83. }
  84. CloseHandle(hFile);
  85. }
  86. return NULL;
  87. }
  88. //+----------------------------------------------------------------------------
  89. //
  90. // Method: FileStream::AddRef (IUnknown)
  91. //
  92. //+----------------------------------------------------------------------------
  93. ULONG
  94. FileStream::AddRef()
  95. {
  96. LONG cRefs;
  97. cRefs = InterlockedIncrement( &_cRefs );
  98. return cRefs;
  99. }
  100. //+----------------------------------------------------------------------------
  101. //
  102. // Method: FileStream::Release (IUnknown)
  103. //
  104. //+----------------------------------------------------------------------------
  105. ULONG
  106. FileStream::Release()
  107. {
  108. ULONG ulRet = InterlockedDecrement( &_cRefs );
  109. if( 0 == ulRet )
  110. delete this;
  111. return( ulRet );
  112. }
  113. //+----------------------------------------------------------------------------
  114. //
  115. // Method: FileStream::AddRef (IUnknown)
  116. //
  117. //+----------------------------------------------------------------------------
  118. HRESULT
  119. FileStream::QueryInterface(
  120. REFIID riid,
  121. void** ppv )
  122. {
  123. HRESULT sc=S_OK;
  124. if( IsEqualIID( riid, IID_IUnknown )
  125. ||
  126. IsEqualIID( riid, IID_IStream )
  127. ||
  128. IsEqualIID( riid, IID_ISequentialStream ) )
  129. {
  130. *ppv = static_cast<IStream*>(this);
  131. AddRef();
  132. return( S_OK );
  133. }
  134. else
  135. {
  136. return( E_NOINTERFACE );
  137. }
  138. return sc;
  139. }
  140. //+----------------------------------------------------------------------------
  141. //
  142. // Method: FileStream::Seek (IStream)
  143. //
  144. //+----------------------------------------------------------------------------
  145. HRESULT
  146. FileStream::Seek(
  147. LARGE_INTEGER dlibMove,
  148. DWORD dwOrigin,
  149. ULARGE_INTEGER *puliNewPos)
  150. {
  151. HRESULT sc = S_OK;
  152. LARGE_INTEGER liFileSize;
  153. LARGE_INTEGER liNewPos;
  154. Lock( INFINITE );
  155. switch( dwOrigin )
  156. {
  157. case STREAM_SEEK_SET:
  158. liNewPos.QuadPart = dlibMove.QuadPart;
  159. break;
  160. case STREAM_SEEK_CUR:
  161. liNewPos.QuadPart = _liCurrentSeekPosition.QuadPart + dlibMove.QuadPart;
  162. break;
  163. case STREAM_SEEK_END:
  164. liFileSize.LowPart = GetFileSize( _hFile,
  165. (ULONG*)(&liFileSize.HighPart) );
  166. if( 0xFFFFFFFF == liFileSize.LowPart && NO_ERROR != GetLastError() )
  167. {
  168. nffChk( HRESULT_FROM_WIN32( GetLastError() ) );
  169. }
  170. liNewPos.QuadPart = liFileSize.QuadPart + dlibMove.QuadPart;
  171. break;
  172. default:
  173. break;
  174. }
  175. // Compatibility with Docfile. Seeking < 0 fails.
  176. if( liNewPos.QuadPart < 0 )
  177. nffErr( EH_Err, STG_E_INVALIDFUNCTION );
  178. _liCurrentSeekPosition = liNewPos;
  179. // If desired, give the caller the now-current seek position.
  180. if( NULL != puliNewPos )
  181. *puliNewPos = _liCurrentSeekPosition;
  182. EH_Err:
  183. Unlock();
  184. return( sc );
  185. }
  186. //+----------------------------------------------------------------------------
  187. //
  188. // Method: FileStream::SetSize (IStream)
  189. //
  190. //+----------------------------------------------------------------------------
  191. HRESULT
  192. FileStream::SetSize(
  193. ULARGE_INTEGER uliNewSize)
  194. {
  195. HRESULT sc = S_OK;
  196. CLargeInteger liEOF;
  197. if ( uliNewSize.HighPart != 0 )
  198. nffErr(EH_Err, STG_E_INVALIDFUNCTION);
  199. Lock( INFINITE );
  200. nffChk( CheckReverted() );
  201. // If this stream is mapped, set the size accordingly
  202. sc = SetFileSize( CULargeInteger(uliNewSize) );
  203. if( !FAILED(sc) )
  204. sc = S_OK;
  205. EH_Err:
  206. Unlock();
  207. return( sc);
  208. }
  209. //+----------------------------------------------------------------------------
  210. //
  211. // Method: FileStream::CopyTo (IStream)
  212. //
  213. //+----------------------------------------------------------------------------
  214. HRESULT
  215. FileStream::CopyTo(
  216. IStream *pstm,
  217. ULARGE_INTEGER cb,
  218. ULARGE_INTEGER *pcbRead,
  219. ULARGE_INTEGER *pcbWritten)
  220. {
  221. HRESULT sc = S_OK;
  222. PVOID pv = NULL;
  223. ULONG cbRead = 0, cbWritten = 0;
  224. CULargeInteger cbReadTotal = 0, cbWrittenTotal = 0;
  225. CLargeInteger liZero = 0;
  226. CULargeInteger uliOriginalSourcePosition, uliOriginalDestPosition;
  227. CULargeInteger cbSourceSize, cbDestSize;
  228. ULONG cbPerCopy = 0;
  229. STATSTG statstg;
  230. CULargeInteger cbRequested = cb;
  231. BOOL fCopyForward;
  232. Lock( INFINITE );
  233. nffChk( CheckReverted() );
  234. if( NULL == pstm)
  235. nffErr( EH_Err, STG_E_INVALIDPARAMETER );
  236. // Determine how much we'll copy at a time.
  237. // As of this writing, STREAMBUFFERSIZE is 8192 bytes
  238. if( cbRequested > STREAMBUFFERSIZE )
  239. cbPerCopy = STREAMBUFFERSIZE;
  240. else
  241. cbPerCopy = cbRequested.LowPart;
  242. // ------------------------------------------------------------------
  243. // Get the current stream sizes/positions, and adjust the destination
  244. // size if necessary
  245. // ------------------------------------------------------------------
  246. nffChk( this->Seek( liZero, STREAM_SEEK_CUR, &uliOriginalSourcePosition ) );
  247. nffChk( pstm->Seek( liZero, STREAM_SEEK_CUR, &uliOriginalDestPosition ) );
  248. nffChk( this->Stat( &statstg, STATFLAG_NONAME ) );
  249. cbSourceSize = statstg.cbSize;
  250. nffChk( pstm->Stat( &statstg, STATFLAG_NONAME ) );
  251. cbDestSize = statstg.cbSize;
  252. // Ensure the sizes are valid (we can't handle anything with the high bit
  253. // set, because Seek takes a signed offset).
  254. if( static_cast<CLargeInteger>(cbSourceSize) < 0
  255. ||
  256. static_cast<CLargeInteger>(cbDestSize) < 0 )
  257. {
  258. nffErr( EH_Err, STG_E_INVALIDHEADER );
  259. }
  260. // Don't copy more than the source stream has available
  261. if( cbRequested > cbSourceSize - uliOriginalSourcePosition )
  262. cbRequested = cbSourceSize - uliOriginalSourcePosition;
  263. // If necessary, grow the destination stream.
  264. if( cbSourceSize - uliOriginalSourcePosition > cbDestSize - uliOriginalDestPosition )
  265. {
  266. cbDestSize = cbSourceSize - uliOriginalSourcePosition + uliOriginalDestPosition;
  267. nffChk( pstm->SetSize( cbDestSize ) );
  268. }
  269. // ----------------------
  270. // Allocate a copy buffer
  271. // ----------------------
  272. nffMem( pv = CoTaskMemAlloc( cbPerCopy ) );
  273. // -----------------------------------------------------------------------------
  274. // Determine if we're copying forwards (high seek position to low) or backwards.
  275. // -----------------------------------------------------------------------------
  276. fCopyForward = TRUE;
  277. if( uliOriginalSourcePosition < uliOriginalDestPosition )
  278. {
  279. // E.g., say we're copying 15 bytes from offset 0 to offset 5,
  280. // and we're only able to copy 10 bytes at a time.
  281. // If we copy bytes 0-9 to offset 5, we'll end up overwriting
  282. // bytes 10-14, and be unable to complete the copy.
  283. // So instead, we'll copy bytes 5-14 to offset 10, and finish
  284. // up by copying bytes 0-4 to offset 5.
  285. fCopyForward = FALSE;
  286. // To do this kind of backwards copy, we need to start by seeking
  287. // towards the end of the stream.
  288. CULargeInteger uliNewSourcePosition, uliNewDestPosition;
  289. uliNewSourcePosition = cbSourceSize - cbPerCopy;
  290. nffChk( this->Seek( uliNewSourcePosition, STREAM_SEEK_SET, NULL ) );
  291. uliNewDestPosition = cbDestSize - cbPerCopy;
  292. nffChk( pstm->Seek( uliNewDestPosition, STREAM_SEEK_SET, NULL ) );
  293. }
  294. // --------------
  295. // Copy in chunks
  296. // --------------
  297. cbPerCopy = cbRequested > cbPerCopy ? cbPerCopy : cbRequested.LowPart;
  298. while( cbRequested > 0 )
  299. {
  300. // Read from the source
  301. nffChk( this->Read( pv, cbPerCopy, &cbRead ) );
  302. if( cbRead != cbPerCopy )
  303. nffErr(EH_Err, STG_E_READFAULT);
  304. cbReadTotal += cbRead;
  305. // Write to the dest
  306. nffChk( pstm->Write( pv, cbPerCopy, &cbWritten ) );
  307. if( cbWritten != cbPerCopy )
  308. nffErr( EH_Err, STG_E_WRITEFAULT );
  309. cbWrittenTotal += cbWritten;
  310. // Adjust the amount remaining to be copied
  311. cbRequested -= cbPerCopy;
  312. // Determine how much to copy in the next iteration (this will
  313. // always be cbPerCopy until the last iteration). If copying
  314. // backwards, we need to manually adjust the seek pointer.
  315. cbPerCopy = (cbRequested > cbPerCopy) ? cbPerCopy : cbRequested.LowPart;
  316. if( !fCopyForward && (cbRequested > 0))
  317. {
  318. nffChk( this->Seek( -static_cast<CLargeInteger>(cbPerCopy+STREAMBUFFERSIZE),
  319. STREAM_SEEK_CUR, NULL ) );
  320. nffChk( pstm->Seek( -static_cast<CLargeInteger>(cbPerCopy+STREAMBUFFERSIZE),
  321. STREAM_SEEK_CUR, NULL ) );
  322. }
  323. }
  324. // If we were backward-copying, adjust the seek pointers
  325. // as if we had forward-copied
  326. if( !fCopyForward )
  327. {
  328. uliOriginalSourcePosition += cbReadTotal;
  329. nffChk( this->Seek( uliOriginalSourcePosition, STREAM_SEEK_SET, NULL ) );
  330. uliOriginalDestPosition += cbWrittenTotal;
  331. nffChk( pstm->Seek( uliOriginalDestPosition, STREAM_SEEK_SET, NULL ) );
  332. }
  333. // ----
  334. // Exit
  335. // ----
  336. if( NULL != pcbRead )
  337. *pcbRead = cbReadTotal;
  338. if( NULL != pcbWritten )
  339. *pcbWritten = cbWrittenTotal;
  340. EH_Err:
  341. if( NULL != pv )
  342. CoTaskMemFree(pv);
  343. Unlock();
  344. return(sc);
  345. }
  346. //+----------------------------------------------------------------------------
  347. //
  348. // Method: FileStream::Commit (IStream)
  349. //
  350. //+----------------------------------------------------------------------------
  351. HRESULT
  352. FileStream::Commit( DWORD grfCommitFlags )
  353. {
  354. HRESULT sc = S_OK;
  355. Lock( INFINITE );
  356. nffChk( CheckReverted() );
  357. // NTRAID#NTBUG9-368729-2001-04-13-gilmanw "ISSUE: FileStream object - handle other stream commit flags"
  358. // Are there other commit flags that need to be handled?
  359. if( !(STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE & grfCommitFlags) )
  360. {
  361. if( !FlushFileBuffers( _hFile ))
  362. sc = HRESULT_FROM_WIN32( GetLastError() );
  363. }
  364. EH_Err:
  365. Unlock();
  366. return sc;
  367. }
  368. //+----------------------------------------------------------------------------
  369. //
  370. // Method: FileStream::Revert (IStream)
  371. //
  372. //+----------------------------------------------------------------------------
  373. HRESULT
  374. FileStream::Revert(void)
  375. {
  376. // We only support direct-mode.
  377. return CheckReverted();
  378. }
  379. //+----------------------------------------------------------------------------
  380. //
  381. // Method: FileStream::LockRegion (IStream)
  382. //
  383. //+----------------------------------------------------------------------------
  384. HRESULT
  385. FileStream::LockRegion(
  386. ULARGE_INTEGER libOffset,
  387. ULARGE_INTEGER cb,
  388. DWORD dwLockType)
  389. {
  390. HRESULT sc = S_OK;
  391. Lock( INFINITE );
  392. nffChk( CheckReverted() );
  393. // NTRAID#NTBUG9-368745-2001-04-13-gilmanw "ISSUE: FileStream::LockRegion - handle other lock flags"
  394. // Are all the lock types supported here?
  395. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  396. nffErr( EH_Err, STG_E_INVALIDFUNCTION );
  397. if( !LockFile( _hFile, libOffset.LowPart, libOffset.HighPart,
  398. cb.LowPart, cb.HighPart))
  399. {
  400. nffErr( EH_Err, HRESULT_FROM_WIN32( GetLastError() ));
  401. }
  402. EH_Err:
  403. Unlock();
  404. return( sc );
  405. }
  406. //+----------------------------------------------------------------------------
  407. //
  408. // Method: FileStream::Stat (IStream)
  409. //
  410. //+----------------------------------------------------------------------------
  411. HRESULT
  412. FileStream::Stat(
  413. STATSTG *pstatstg,
  414. DWORD grfStatFlag)
  415. {
  416. STATSTG statstg;
  417. HRESULT sc = S_OK;
  418. BY_HANDLE_FILE_INFORMATION ByHandleFileInformation;
  419. statstg.pwcsName = NULL;
  420. Lock( INFINITE );
  421. nffChk( CheckReverted() );
  422. ZeroMemory((void*)&statstg, sizeof(STATSTG));
  423. // Get the name, if desired
  424. if( (STATFLAG_NONAME & grfStatFlag) )
  425. statstg.pwcsName = NULL;
  426. else
  427. {
  428. nffMem( statstg.pwcsName = reinterpret_cast<WCHAR*>
  429. ( CoTaskMemAlloc( sizeof(WCHAR)*(UnicodeStringLength(_pwcsName) + 1) )));
  430. UnicodeStringCopy( statstg.pwcsName, _pwcsName );
  431. }
  432. // Get the type
  433. statstg.type = STGTY_STREAM;
  434. statstg.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  435. // Get the size & times.
  436. if( !GetFileInformationByHandle( _hFile, &ByHandleFileInformation ))
  437. nffErr( EH_Err, HRESULT_FROM_WIN32( GetLastError() ));
  438. statstg.cbSize.LowPart = ByHandleFileInformation.nFileSizeLow;
  439. statstg.cbSize.HighPart = ByHandleFileInformation.nFileSizeHigh;
  440. // We get a time back in ByHandleFileInformation, but it's the file's times,
  441. // not the streams times. So really the stream times are not supported, and
  442. // we'll just set them to zero.
  443. statstg.mtime = statstg.atime = statstg.ctime = CFILETIME(0);
  444. // Get the STGM modes
  445. statstg.grfMode = _grfMode & ~STGM_CREATE;
  446. *pstatstg = statstg;
  447. EH_Err:
  448. if( FAILED(sc) && NULL != statstg.pwcsName )
  449. CoTaskMemFree( statstg.pwcsName );
  450. Unlock();
  451. return( sc );
  452. }
  453. //+----------------------------------------------------------------------------
  454. //
  455. // Method: FileStream::Clone (IStream)
  456. //
  457. //+----------------------------------------------------------------------------
  458. HRESULT
  459. FileStream::Clone(
  460. IStream** ppstm)
  461. {
  462. // NTRAID#NTBUG9-368747-2001-04-13-gilmanw "ISSUE: FileStream::Clone returns E_NOTIMPL"
  463. return( E_NOTIMPL );
  464. }
  465. //+----------------------------------------------------------------------------
  466. //
  467. // Method: FileStream::Read (IStream)
  468. //
  469. //+----------------------------------------------------------------------------
  470. HRESULT
  471. FileStream::Read(
  472. void* pv,
  473. ULONG cb,
  474. ULONG* pcbRead)
  475. {
  476. LARGE_INTEGER lOffset;
  477. HRESULT sc = S_OK;
  478. ULONG cbRead = 0;
  479. lOffset.LowPart = _liCurrentSeekPosition.LowPart;
  480. lOffset.HighPart = _liCurrentSeekPosition.HighPart;
  481. if (lOffset.HighPart < 0)
  482. {
  483. return( TYPE_E_SIZETOOBIG );
  484. }
  485. Lock( INFINITE );
  486. nffChk( CheckReverted() );
  487. if(SetFilePointer(_hFile, lOffset.LowPart, &lOffset.HighPart,
  488. FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  489. {
  490. nffChk( HRESULT_FROM_WIN32(GetLastError()));
  491. }
  492. if(!ReadFile(_hFile, pv, cb, &cbRead, NULL))
  493. {
  494. nffChk( HRESULT_FROM_WIN32(GetLastError()));
  495. }
  496. _liCurrentSeekPosition += cbRead;
  497. if( NULL != pcbRead )
  498. *pcbRead = cbRead;
  499. EH_Err:
  500. Unlock();
  501. return( sc );
  502. }
  503. //+----------------------------------------------------------------------------
  504. //
  505. // Method: FileStream::Write (IStream)
  506. //
  507. //+----------------------------------------------------------------------------
  508. HRESULT
  509. FileStream::Write(
  510. const void* pv,
  511. ULONG cb,
  512. ULONG* pcbWritten)
  513. {
  514. LARGE_INTEGER lOffset;
  515. HRESULT sc = S_OK;
  516. ULONG cbWritten = 0;
  517. lOffset.LowPart = _liCurrentSeekPosition.LowPart;
  518. lOffset.HighPart = _liCurrentSeekPosition.HighPart;
  519. if (lOffset.HighPart < 0)
  520. {
  521. return( TYPE_E_SIZETOOBIG );
  522. }
  523. Lock( INFINITE );
  524. nffChk( CheckReverted() );
  525. if(SetFilePointer(_hFile, lOffset.LowPart, &lOffset.HighPart,
  526. FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  527. {
  528. nffChk( HRESULT_FROM_WIN32(GetLastError()));
  529. }
  530. if(!WriteFile(_hFile, pv, cb, &cbWritten, NULL))
  531. {
  532. nffChk(HRESULT_FROM_WIN32(GetLastError()));
  533. }
  534. _liCurrentSeekPosition += cbWritten;
  535. if( NULL != pcbWritten )
  536. *pcbWritten = cbWritten;
  537. EH_Err:
  538. Unlock();
  539. return( sc );
  540. }
  541. //+-------------------------------------------------------------------
  542. //
  543. // Member: FileStream Constructor
  544. //
  545. //--------------------------------------------------------------------
  546. FileStream::FileStream( )
  547. {
  548. _cRefs = 1;
  549. _grfMode = 0;
  550. _hFile = INVALID_HANDLE_VALUE;
  551. _liCurrentSeekPosition = 0;
  552. _pwcsName = NULL;
  553. _bCritSecInitialized = FALSE;
  554. __try
  555. {
  556. InitializeCriticalSection( &_critsec );
  557. _bCritSecInitialized = TRUE;
  558. }
  559. __except(EXCEPTION_EXECUTE_HANDLER)
  560. {
  561. // If we've thrown then _bCritSecInitialized will be FALSE and
  562. // Init() will automatically fail.
  563. }
  564. }
  565. //+-------------------------------------------------------------------
  566. //
  567. // Member: FileStream Destructor
  568. //
  569. //--------------------------------------------------------------------
  570. FileStream::~FileStream()
  571. {
  572. // Close the file
  573. if( INVALID_HANDLE_VALUE != _hFile )
  574. CloseHandle( _hFile );
  575. if( NULL != _pwcsName )
  576. CoTaskMemFree( _pwcsName );
  577. if (_bCritSecInitialized)
  578. {
  579. // We don't need to reset _bCrisSecInitialized to FALSE since the
  580. // object has been destroyed
  581. DeleteCriticalSection( &_critsec );
  582. }
  583. }
  584. //+-------------------------------------------------------------------
  585. //
  586. // Member: FileStream::Init
  587. //
  588. //--------------------------------------------------------------------
  589. HRESULT
  590. FileStream::Init(
  591. HANDLE hFile, // File handle of this Stream.
  592. DWORD grfMode, // Open Modes
  593. const OLECHAR * pwcsName) // Name of the Stream
  594. {
  595. // If we couldn't allocate the critical section then return an Error
  596. if (!_bCritSecInitialized)
  597. {
  598. return E_FAIL;
  599. }
  600. HRESULT sc=S_OK;
  601. HANDLE ev;
  602. // We now own this file handle, and are responsible for closing it.
  603. _hFile = hFile;
  604. // Save the STGM_ flags so we can return them in a Stat call.
  605. _grfMode = grfMode;
  606. // Save the stream name
  607. if( NULL != _pwcsName )
  608. {
  609. CoTaskMemFree( _pwcsName );
  610. _pwcsName = NULL;
  611. }
  612. if( NULL != pwcsName )
  613. {
  614. nffMem( _pwcsName = reinterpret_cast<WCHAR*>
  615. ( CoTaskMemAlloc( sizeof(WCHAR)*(UnicodeStringLength(pwcsName) + 1) )));
  616. UnicodeStringCopy( _pwcsName, pwcsName );
  617. }
  618. EH_Err:
  619. return sc;
  620. }
  621. //+----------------------------------------------------------------------------
  622. //
  623. // FileStream Non-Interface::ShutDown
  624. //
  625. // Flush data, Close File handle and mark the object as reverted.
  626. // This is called when the Storage is released and when the Oplock Breaks.
  627. //
  628. //+----------------------------------------------------------------------------
  629. HRESULT
  630. FileStream::ShutDown()
  631. {
  632. HRESULT sc=S_OK;
  633. if( INVALID_HANDLE_VALUE == _hFile )
  634. return S_OK;
  635. //
  636. // Close the file/stream handle and mark the IStream object as
  637. // Reverted by giving the file handle an invalid value.
  638. //
  639. CloseHandle(_hFile);
  640. _hFile = INVALID_HANDLE_VALUE;
  641. return S_OK;
  642. }
  643. //+----------------------------------------------------------------------------
  644. //
  645. // FileStream::SetFileSize (private, non-interface method)
  646. //
  647. // Set the size of the _hFile. This is used by the IStream & IMappedStream
  648. // SetSize methods
  649. //
  650. //+----------------------------------------------------------------------------
  651. HRESULT // private
  652. FileStream::SetFileSize( const CULargeInteger &uliNewSize )
  653. {
  654. HRESULT sc = S_OK;
  655. CLargeInteger liEOF;
  656. // We have to convert uliNewSize into a LARGE_INTEGER, so ensure that it can
  657. // be cast without loss of data.
  658. liEOF = static_cast<CLargeInteger>(uliNewSize);
  659. if( liEOF < 0 )
  660. nffErr( EH_Err, STG_E_INVALIDPARAMETER );
  661. // Move to what will be the new end-of-file position.
  662. liEOF.LowPart = SetFilePointer( _hFile, liEOF.LowPart,
  663. &liEOF.HighPart, FILE_BEGIN );
  664. if( 0xFFFFFFFF == liEOF.LowPart && NO_ERROR != GetLastError() )
  665. nffErr( EH_Err, HRESULT_FROM_WIN32( GetLastError() ));
  666. // Set this as the new eof
  667. if( !SetEndOfFile( _hFile ))
  668. nffErr( EH_Err, HRESULT_FROM_WIN32( GetLastError() ));
  669. EH_Err:
  670. return( sc );
  671. }
  672. HRESULT
  673. FileStream::UnlockRegion(
  674. ULARGE_INTEGER libOffset,
  675. ULARGE_INTEGER cb,
  676. DWORD dwLockType)
  677. {
  678. HRESULT sc = S_OK;
  679. Lock( INFINITE );
  680. nffChk( CheckReverted() );
  681. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  682. {
  683. nffErr( EH_Err, STG_E_INVALIDFUNCTION );
  684. }
  685. if( !UnlockFile(_hFile, libOffset.LowPart, libOffset.HighPart,
  686. cb.LowPart, cb.HighPart))
  687. {
  688. nffErr( EH_Err, HRESULT_FROM_WIN32(GetLastError()) );
  689. }
  690. EH_Err:
  691. Unlock();
  692. return( sc );
  693. }