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.

791 lines
22 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Stream.cpp
  5. Abstract:
  6. This file contains the implementation of the MPC::*Stream classes.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 07/14/99
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. /////////////////////////////////////////////////////////////////////////////
  13. STDMETHODIMP MPC::BaseStream::Read( /*[out]*/ void* pv ,
  14. /*[in] */ ULONG cb ,
  15. /*[out]*/ ULONG *pcbRead )
  16. {
  17. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Read");
  18. __MPC_FUNC_EXIT(E_NOTIMPL);
  19. }
  20. STDMETHODIMP MPC::BaseStream::Write( /*[in] */ const void* pv ,
  21. /*[in] */ ULONG cb ,
  22. /*[out]*/ ULONG *pcbWritten )
  23. {
  24. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Write");
  25. __MPC_FUNC_EXIT(E_NOTIMPL);
  26. }
  27. STDMETHODIMP MPC::BaseStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
  28. /*[in] */ DWORD dwOrigin ,
  29. /*[out]*/ ULARGE_INTEGER *plibNewPosition )
  30. {
  31. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Seek");
  32. __MPC_FUNC_EXIT(E_NOTIMPL);
  33. }
  34. STDMETHODIMP MPC::BaseStream::SetSize( /*[in]*/ ULARGE_INTEGER libNewSize )
  35. {
  36. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::SetSize");
  37. __MPC_FUNC_EXIT(E_NOTIMPL);
  38. }
  39. STDMETHODIMP MPC::BaseStream::CopyTo( /*[in] */ IStream* pstm ,
  40. /*[in] */ ULARGE_INTEGER cb ,
  41. /*[out]*/ ULARGE_INTEGER *pcbRead ,
  42. /*[out]*/ ULARGE_INTEGER *pcbWritten )
  43. {
  44. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::CopyTo");
  45. __MPC_FUNC_EXIT(E_NOTIMPL);
  46. }
  47. STDMETHODIMP MPC::BaseStream::Commit( /*[in]*/ DWORD grfCommitFlags )
  48. {
  49. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Commit");
  50. __MPC_FUNC_EXIT(E_NOTIMPL);
  51. }
  52. STDMETHODIMP MPC::BaseStream::Revert()
  53. {
  54. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Revert");
  55. __MPC_FUNC_EXIT(E_NOTIMPL);
  56. }
  57. STDMETHODIMP MPC::BaseStream::LockRegion( /*[in]*/ ULARGE_INTEGER libOffset ,
  58. /*[in]*/ ULARGE_INTEGER cb ,
  59. /*[in]*/ DWORD dwLockType )
  60. {
  61. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::LockRegion");
  62. __MPC_FUNC_EXIT(E_NOTIMPL);
  63. }
  64. STDMETHODIMP MPC::BaseStream::UnlockRegion( /*[in]*/ ULARGE_INTEGER libOffset ,
  65. /*[in]*/ ULARGE_INTEGER cb ,
  66. /*[in]*/ DWORD dwLockType )
  67. {
  68. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::UnlockRegion");
  69. __MPC_FUNC_EXIT(E_NOTIMPL);
  70. }
  71. STDMETHODIMP MPC::BaseStream::Stat( /*[out]*/ STATSTG *pstatstg ,
  72. /*[in] */ DWORD grfStatFlag )
  73. {
  74. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Stat");
  75. __MPC_FUNC_EXIT(E_NOTIMPL);
  76. }
  77. STDMETHODIMP MPC::BaseStream::Clone( /*[out]*/ IStream* *ppstm )
  78. {
  79. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Clone");
  80. __MPC_FUNC_EXIT(E_NOTIMPL);
  81. }
  82. HRESULT MPC::BaseStream::TransferData( /*[in] */ IStream* src ,
  83. /*[in] */ IStream* dst ,
  84. /*[in] */ ULONG ulCount ,
  85. /*[out]*/ ULONG *ulDone )
  86. {
  87. __MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::TransferData");
  88. HRESULT hr;
  89. BYTE rgBuf[512];
  90. ULONG ulTot = 0;
  91. ULONG ulRead;
  92. ULONG ulWritten;
  93. ULONG ul;
  94. __MPC_PARAMCHECK_BEGIN(hr)
  95. __MPC_PARAMCHECK_NOTNULL(src);
  96. __MPC_PARAMCHECK_NOTNULL(dst);
  97. __MPC_PARAMCHECK_END();
  98. while(1)
  99. {
  100. //
  101. // Compute the amount to read on this pass (-1 == everything).
  102. //
  103. if(ulCount == -1)
  104. {
  105. ul = sizeof( rgBuf );
  106. }
  107. else
  108. {
  109. ul = min( sizeof( rgBuf ), ulCount );
  110. }
  111. if(ul == 0) break;
  112. //
  113. // Read and write.
  114. //
  115. __MPC_EXIT_IF_METHOD_FAILS(hr, src->Read( rgBuf, ul, &ulRead ));
  116. if(hr == S_FALSE || ulRead == 0) break;
  117. __MPC_EXIT_IF_METHOD_FAILS(hr, dst->Write( rgBuf, ulRead, &ulWritten ));
  118. //
  119. // Update counters.
  120. //
  121. if(ulCount != -1)
  122. {
  123. ulCount -= ulRead;
  124. }
  125. ulTot += ulWritten;
  126. if(ulRead != ulWritten)
  127. {
  128. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_MEDIUMFULL);
  129. }
  130. }
  131. hr = S_OK;
  132. __MPC_FUNC_CLEANUP;
  133. if(ulDone) *ulDone = ulTot;
  134. __MPC_FUNC_EXIT(hr);
  135. }
  136. /////////////////////////////////////////////////////////////////////////////
  137. /////////////////////////////////////////////////////////////////////////////
  138. /////////////////////////////////////////////////////////////////////////////
  139. MPC::FileStream::FileStream()
  140. {
  141. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::FileStream");
  142. // MPC::wstring m_szFile;
  143. m_dwDesiredAccess = GENERIC_READ; // DWORD m_dwDesiredAccess;
  144. m_dwDisposition = OPEN_EXISTING; // DWORD m_dwDisposition;
  145. m_dwSharing = FILE_SHARE_READ | FILE_SHARE_WRITE; // DWORD m_dwSharing;
  146. m_hfFile = NULL; // HANDLE m_hfFile;
  147. m_fDeleteOnRelease = false; // bool m_fDeleteOnRelease;
  148. }
  149. MPC::FileStream::~FileStream()
  150. {
  151. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::~FileStream");
  152. Close();
  153. }
  154. HRESULT MPC::FileStream::Close()
  155. {
  156. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Close");
  157. HRESULT hr;
  158. if(m_hfFile)
  159. {
  160. ::CloseHandle( m_hfFile ); m_hfFile = NULL;
  161. if(m_fDeleteOnRelease)
  162. {
  163. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile( m_szFile ));
  164. }
  165. }
  166. hr = S_OK;
  167. __MPC_FUNC_CLEANUP;
  168. __MPC_FUNC_EXIT(hr);
  169. }
  170. HRESULT MPC::FileStream::Init( /*[in]*/ LPCWSTR szFile ,
  171. /*[in]*/ DWORD dwDesiredAccess ,
  172. /*[in]*/ DWORD dwDisposition ,
  173. /*[in]*/ DWORD dwSharing ,
  174. /*[in]*/ HANDLE hfFile )
  175. {
  176. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Init");
  177. HRESULT hr;
  178. __MPC_PARAMCHECK_BEGIN(hr)
  179. __MPC_PARAMCHECK_NOTNULL(szFile);
  180. __MPC_PARAMCHECK_END();
  181. Close();
  182. m_szFile = szFile;
  183. m_dwDesiredAccess = dwDesiredAccess;
  184. m_dwDisposition = dwDisposition;
  185. m_dwSharing = dwSharing;
  186. if(hfFile)
  187. {
  188. if(::DuplicateHandle( ::GetCurrentProcess(), hfFile,
  189. ::GetCurrentProcess(), &m_hfFile, m_dwDesiredAccess, FALSE, 0 ) == FALSE)
  190. {
  191. m_hfFile = NULL; // For cleanup.
  192. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError() );
  193. }
  194. }
  195. else
  196. {
  197. __MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, m_hfFile, ::CreateFileW( szFile, m_dwDesiredAccess, dwSharing, NULL, dwDisposition, FILE_ATTRIBUTE_NORMAL, NULL ));
  198. }
  199. hr = S_OK;
  200. __MPC_FUNC_CLEANUP;
  201. __MPC_FUNC_EXIT(hr);
  202. }
  203. HRESULT MPC::FileStream::InitForRead( /*[in]*/ LPCWSTR szFile ,
  204. /*[in]*/ HANDLE hfFile )
  205. {
  206. return Init( szFile, GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ | FILE_SHARE_WRITE, hfFile );
  207. }
  208. HRESULT MPC::FileStream::InitForReadWrite( /*[in]*/ LPCWSTR szFile ,
  209. /*[in]*/ HANDLE hfFile )
  210. {
  211. return Init( szFile, GENERIC_READ | GENERIC_WRITE, CREATE_ALWAYS, 0, hfFile );
  212. }
  213. HRESULT MPC::FileStream::InitForWrite( /*[in]*/ LPCWSTR szFile ,
  214. /*[in]*/ HANDLE hfFile )
  215. {
  216. return Init( szFile, GENERIC_WRITE, CREATE_ALWAYS, 0, hfFile );
  217. }
  218. HRESULT MPC::FileStream::DeleteOnRelease( /*[in]*/ bool fFlag )
  219. {
  220. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::DeleteOnRelease");
  221. m_fDeleteOnRelease = fFlag;
  222. __MPC_FUNC_EXIT(S_OK);
  223. }
  224. STDMETHODIMP MPC::FileStream::Read( /*[out]*/ void* pv ,
  225. /*[in] */ ULONG cb ,
  226. /*[out]*/ ULONG *pcbRead )
  227. {
  228. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Read");
  229. HRESULT hr;
  230. DWORD dwRead;
  231. if(pcbRead) *pcbRead = 0;
  232. if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  233. if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  234. if(::ReadFile( m_hfFile, pv, cb, &dwRead, NULL ) == FALSE)
  235. {
  236. DWORD dwRes = ::GetLastError();
  237. if(dwRes == ERROR_ACCESS_DENIED)
  238. {
  239. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
  240. }
  241. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  242. }
  243. else
  244. {
  245. if(dwRead == 0 && cb != 0)
  246. {
  247. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  248. }
  249. }
  250. if(pcbRead) *pcbRead = dwRead;
  251. hr = S_OK;
  252. __MPC_FUNC_CLEANUP;
  253. __MPC_FUNC_EXIT(hr);
  254. }
  255. STDMETHODIMP MPC::FileStream::Write( /*[in] */ const void* pv ,
  256. /*[in] */ ULONG cb ,
  257. /*[out]*/ ULONG *pcbWritten )
  258. {
  259. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Write");
  260. HRESULT hr;
  261. DWORD dwWritten;
  262. if(pcbWritten) *pcbWritten = 0;
  263. if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  264. if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  265. if((m_dwDesiredAccess & GENERIC_WRITE) == 0) // Read-only stream.
  266. {
  267. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_WRITEFAULT);
  268. }
  269. if(::WriteFile( m_hfFile, pv, cb, &dwWritten, NULL ) == FALSE)
  270. {
  271. DWORD dwRes = ::GetLastError();
  272. if(dwRes == ERROR_DISK_FULL)
  273. {
  274. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_MEDIUMFULL);
  275. }
  276. if(dwRes == ERROR_ACCESS_DENIED)
  277. {
  278. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
  279. }
  280. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_CANTSAVE);
  281. }
  282. if(pcbWritten) *pcbWritten = dwWritten;
  283. hr = S_OK;
  284. __MPC_FUNC_CLEANUP;
  285. __MPC_FUNC_EXIT(hr);
  286. }
  287. STDMETHODIMP MPC::FileStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
  288. /*[in] */ DWORD dwOrigin ,
  289. /*[out]*/ ULARGE_INTEGER *plibNewPosition )
  290. {
  291. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Seek");
  292. HRESULT hr;
  293. if(plibNewPosition)
  294. {
  295. plibNewPosition->HighPart = 0;
  296. plibNewPosition->LowPart = 0;
  297. }
  298. if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  299. switch(dwOrigin)
  300. {
  301. default :
  302. case STREAM_SEEK_CUR: dwOrigin = FILE_CURRENT; break;
  303. case STREAM_SEEK_SET: dwOrigin = FILE_BEGIN ; break;
  304. case STREAM_SEEK_END: dwOrigin = FILE_END ; break;
  305. }
  306. if(::SetFilePointer( m_hfFile, libMove.LowPart, plibNewPosition ? (LONG*)&plibNewPosition->LowPart : NULL, dwOrigin ) == INVALID_SET_FILE_POINTER)
  307. {
  308. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDFUNCTION );
  309. }
  310. hr = S_OK;
  311. __MPC_FUNC_CLEANUP;
  312. __MPC_FUNC_EXIT(hr);
  313. }
  314. STDMETHODIMP MPC::FileStream::Stat( /*[out]*/ STATSTG *pstatstg ,
  315. /*[in] */ DWORD grfStatFlag )
  316. {
  317. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Stat");
  318. HRESULT hr;
  319. BY_HANDLE_FILE_INFORMATION finfo;
  320. if(pstatstg == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  321. if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  322. if(::GetFileInformationByHandle( m_hfFile, &finfo ) == FALSE)
  323. {
  324. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
  325. }
  326. pstatstg->pwcsName = NULL;
  327. pstatstg->type = STGTY_STREAM;
  328. pstatstg->cbSize.HighPart = finfo.nFileSizeHigh;
  329. pstatstg->cbSize.LowPart = finfo.nFileSizeLow;
  330. pstatstg->mtime = finfo.ftCreationTime;
  331. pstatstg->ctime = finfo.ftLastAccessTime;
  332. pstatstg->atime = finfo.ftLastWriteTime;
  333. pstatstg->grfMode = 0;
  334. pstatstg->grfLocksSupported = 0;
  335. pstatstg->clsid = CLSID_NULL;
  336. pstatstg->grfStateBits = 0;
  337. pstatstg->reserved = 0;
  338. if(grfStatFlag != STATFLAG_NONAME)
  339. {
  340. pstatstg->pwcsName = (LPWSTR)::CoTaskMemAlloc( (m_szFile.length() + 1) * sizeof(WCHAR) );
  341. if(pstatstg->pwcsName == NULL)
  342. {
  343. __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INSUFFICIENTMEMORY);
  344. }
  345. StringCchCopyW( pstatstg->pwcsName, m_szFile.length() + 1, m_szFile.c_str() );
  346. }
  347. hr = S_OK;
  348. __MPC_FUNC_CLEANUP;
  349. __MPC_FUNC_EXIT(hr);
  350. }
  351. STDMETHODIMP MPC::FileStream::Clone( /*[out]*/ IStream* *ppstm )
  352. {
  353. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Clone");
  354. HRESULT hr;
  355. MPC::CComObjectNoLock<MPC::FileStream>* pStm = NULL;
  356. if(ppstm == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  357. //
  358. // Create a new stream object.
  359. //
  360. __MPC_EXIT_IF_METHOD_FAILS(hr, pStm->CreateInstance( &pStm ));
  361. //
  362. // Initialize it with the same settings.
  363. //
  364. __MPC_EXIT_IF_METHOD_FAILS(hr, pStm->Init( m_szFile.c_str(), m_dwDesiredAccess, m_dwDisposition, m_dwSharing, m_hfFile ));
  365. //
  366. // QI for its IStream interface.
  367. //
  368. __MPC_EXIT_IF_METHOD_FAILS(hr, pStm->QueryInterface( IID_IStream, (void**)ppstm )); pStm = NULL;
  369. hr = S_OK;
  370. __MPC_FUNC_CLEANUP;
  371. if(pStm) delete pStm;
  372. __MPC_FUNC_EXIT(hr);
  373. }
  374. ////////////////////////////////////////////////////////////////////////////////
  375. ////////////////////////////////////////////////////////////////////////////////
  376. ////////////////////////////////////////////////////////////////////////////////
  377. MPC::EncryptedStream::EncryptedStream()
  378. {
  379. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::EncryptedStream");
  380. // CComPtr<IStream> m_pStream;
  381. m_hCryptProv = NULL; // HCRYPTPROV m_hCryptProv;
  382. m_hKey = NULL; // HCRYPTKEY m_hKey;
  383. m_hHash = NULL; // HCRYPTHASH m_hHash;
  384. // BYTE m_rgDecrypted[512];
  385. m_dwDecryptedPos = 0; // DWORD m_dwDecryptedPos;
  386. m_dwDecryptedLen = 0; // DWORD m_dwDecryptedLen;
  387. }
  388. MPC::EncryptedStream::~EncryptedStream()
  389. {
  390. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::~EncryptedStream");
  391. Close();
  392. }
  393. HRESULT MPC::EncryptedStream::Close()
  394. {
  395. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Close");
  396. m_pStream.Release();
  397. if(m_hHash)
  398. {
  399. ::CryptDestroyHash( m_hHash ); m_hHash = NULL;
  400. }
  401. if(m_hKey)
  402. {
  403. ::CryptDestroyKey( m_hKey ); m_hKey = NULL;
  404. }
  405. if(m_hCryptProv)
  406. {
  407. ::CryptReleaseContext( m_hCryptProv, 0 ); m_hCryptProv = NULL;
  408. }
  409. m_dwDecryptedPos = 0;
  410. m_dwDecryptedLen = 0;
  411. __MPC_FUNC_EXIT(S_OK);
  412. }
  413. HRESULT MPC::EncryptedStream::Init( /*[in]*/ IStream* pStream ,
  414. /*[in]*/ LPCWSTR szPassword )
  415. {
  416. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Init");
  417. HRESULT hr;
  418. __MPC_PARAMCHECK_BEGIN(hr)
  419. __MPC_PARAMCHECK_NOTNULL(pStream);
  420. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szPassword);
  421. __MPC_PARAMCHECK_END();
  422. Close();
  423. m_pStream = pStream;
  424. if(!::CryptAcquireContext( &m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT ))
  425. {
  426. DWORD dwRes = ::GetLastError();
  427. if(dwRes != NTE_BAD_KEYSET)
  428. {
  429. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  430. }
  431. //
  432. // Key set doesn't exist, let's create one.
  433. //
  434. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptAcquireContext( &m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT ));
  435. }
  436. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptCreateHash( m_hCryptProv, CALG_MD5, 0, 0, &m_hHash ));
  437. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptHashData( m_hHash, (BYTE *)szPassword, sizeof(WCHAR) * wcslen( szPassword ), 0 ));
  438. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptDeriveKey( m_hCryptProv, CALG_RC4, m_hHash, CRYPT_EXPORTABLE, &m_hKey ));
  439. hr = S_OK;
  440. __MPC_FUNC_CLEANUP;
  441. if(FAILED(hr)) Close();
  442. __MPC_FUNC_EXIT(hr);
  443. }
  444. HRESULT MPC::EncryptedStream::Init( /*[in]*/ IStream* pStream ,
  445. /*[in]*/ HCRYPTKEY hKey )
  446. {
  447. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Init");
  448. HRESULT hr;
  449. __MPC_PARAMCHECK_BEGIN(hr)
  450. __MPC_PARAMCHECK_NOTNULL(pStream);
  451. __MPC_PARAMCHECK_NOTNULL(hKey);
  452. __MPC_PARAMCHECK_END();
  453. Close();
  454. m_pStream = pStream;
  455. m_hKey = hKey;
  456. hr = S_OK;
  457. __MPC_FUNC_CLEANUP;
  458. if(FAILED(hr)) Close();
  459. __MPC_FUNC_EXIT(hr);
  460. }
  461. ////////////////////////////////////////////////////////////////////////////////
  462. STDMETHODIMP MPC::EncryptedStream::Read( /*[out]*/ void* pv ,
  463. /*[in] */ ULONG cb ,
  464. /*[out]*/ ULONG *pcbRead )
  465. {
  466. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Read");
  467. HRESULT hr;
  468. DWORD dwRead = 0;
  469. if(pcbRead) *pcbRead = 0;
  470. if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  471. if(m_hKey == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  472. if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  473. while(cb > 0)
  474. {
  475. DWORD dwCount = min( cb, (m_dwDecryptedLen - m_dwDecryptedPos));
  476. ULONG ulRead;
  477. if(dwCount)
  478. {
  479. ::CopyMemory( pv, &m_rgDecrypted[m_dwDecryptedPos], dwCount );
  480. m_dwDecryptedPos += dwCount;
  481. dwRead += dwCount;
  482. cb -= dwCount;
  483. pv = &((BYTE*)pv)[dwCount];
  484. }
  485. else
  486. {
  487. dwCount = sizeof(m_rgDecrypted);
  488. __MPC_EXIT_IF_METHOD_FAILS(hr, m_pStream->Read( m_rgDecrypted, dwCount, &ulRead ));
  489. if(hr == S_FALSE || ulRead == 0) break;
  490. dwCount = ulRead;
  491. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptDecrypt( m_hKey, 0, FALSE, 0, m_rgDecrypted, &dwCount ));
  492. m_dwDecryptedPos = 0;
  493. m_dwDecryptedLen = dwCount;
  494. }
  495. }
  496. if(pcbRead) *pcbRead = dwRead;
  497. hr = S_OK;
  498. __MPC_FUNC_CLEANUP;
  499. __MPC_FUNC_EXIT(hr);
  500. }
  501. STDMETHODIMP MPC::EncryptedStream::Write( /*[in] */ const void* pv ,
  502. /*[in] */ ULONG cb ,
  503. /*[out]*/ ULONG *pcbWritten )
  504. {
  505. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Write");
  506. HRESULT hr;
  507. DWORD dwWritten = 0;
  508. if(pcbWritten) *pcbWritten = 0;
  509. if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  510. if(m_hKey == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  511. if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  512. while(cb > 0)
  513. {
  514. BYTE rgTmp[512];
  515. DWORD dwCount = min( cb, sizeof(rgTmp) / 2 ); // Let's divide by two, just in case...
  516. ULONG ulWritten;
  517. ::CopyMemory( rgTmp, pv, dwCount );
  518. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptEncrypt( m_hKey, 0, FALSE, 0, rgTmp, &dwCount, sizeof(rgTmp) ));
  519. __MPC_EXIT_IF_METHOD_FAILS(hr, m_pStream->Write( rgTmp, dwCount, &ulWritten ));
  520. dwWritten += dwCount;
  521. cb -= dwCount;
  522. pv = &((BYTE*)pv)[dwCount];
  523. }
  524. if(pcbWritten) *pcbWritten = dwWritten;
  525. hr = S_OK;
  526. __MPC_FUNC_CLEANUP;
  527. __MPC_FUNC_EXIT(hr);
  528. }
  529. STDMETHODIMP MPC::EncryptedStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
  530. /*[in] */ DWORD dwOrigin ,
  531. /*[out]*/ ULARGE_INTEGER *plibNewPosition )
  532. {
  533. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Seek");
  534. HRESULT hr;
  535. hr = E_NOTIMPL;
  536. __MPC_FUNC_EXIT(hr);
  537. }
  538. STDMETHODIMP MPC::EncryptedStream::Stat( /*[out]*/ STATSTG *pstatstg ,
  539. /*[in] */ DWORD grfStatFlag )
  540. {
  541. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Stat");
  542. HRESULT hr;
  543. if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
  544. hr = m_pStream->Stat( pstatstg, grfStatFlag );
  545. __MPC_FUNC_CLEANUP;
  546. __MPC_FUNC_EXIT(hr);
  547. }
  548. STDMETHODIMP MPC::EncryptedStream::Clone( /*[out]*/ IStream* *ppstm )
  549. {
  550. __MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Clone");
  551. HRESULT hr;
  552. hr = E_NOTIMPL;
  553. __MPC_FUNC_EXIT(hr);
  554. }