Source code of Windows XP (NT5)
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.

1287 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: simpstm.cxx
  7. //
  8. // Contents: CStdStream implementation
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 04-Aug-94 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "simphead.cxx"
  18. #pragma hdrstop
  19. #include <ole.hxx>
  20. #include <logfile.hxx>
  21. #include <expparam.hxx>
  22. #if DBG == 1 && defined(SECURE_SIMPLE_MODE)
  23. void CSimpStream::CheckSeekPointer(void)
  24. {
  25. LONG lHighChk;
  26. ULONG ulLowChk;
  27. lHighChk = 0;
  28. ulLowChk = SetFilePointer(_hFile, 0, &lHighChk, FILE_CURRENT);
  29. if (ulLowChk == 0xFFFFFFFF)
  30. {
  31. //An error occurred while checking.
  32. simpDebugOut((DEB_ERROR, "SetFilePointer call failed with %lu\n",
  33. GetLastError()));
  34. }
  35. else if ((ulLowChk != _ulSeekPos) || (lHighChk != 0))
  36. {
  37. simpDebugOut((DEB_ERROR, "Seek pointer mismatch."
  38. " Cached = %lu, Real = %lu, High = %lu\n",
  39. _ulSeekPos, ulLowChk, lHighChk));
  40. simpAssert((ulLowChk == _ulSeekPos) && (lHighChk == 0));
  41. }
  42. }
  43. #define CheckSeek() CheckSeekPointer()
  44. #else
  45. #define CheckSeek()
  46. #endif // DBG == 1 && defined(SECURE_SIMPLE_MODE)
  47. //+---------------------------------------------------------------------------
  48. //
  49. // Member: CSimpStream::Init, public
  50. //
  51. // Synopsis: Initialize stream object
  52. //
  53. // Arguments: [pstgParent] -- Pointer to parent
  54. // [hFile] -- File handle for writes
  55. // [ulSeekStart] -- Beginning seek pointer
  56. //
  57. // Returns: Appropriate status code
  58. //
  59. // Modifies:
  60. //
  61. // History: 04-Aug-94 PhilipLa Created
  62. //
  63. // Notes:
  64. //
  65. //----------------------------------------------------------------------------
  66. SCODE CSimpStream::Init(
  67. CSimpStorage *pstgParent,
  68. HANDLE hFile,
  69. ULONG ulSeekStart)
  70. {
  71. simpDebugOut((DEB_ITRACE, "In CSimpStream::Init:%p()\n", this));
  72. _ulSeekStart = ulSeekStart;
  73. _hFile = hFile;
  74. _pstgParent = pstgParent;
  75. _cReferences = 1;
  76. #ifdef SECURE_SIMPLE_MODE
  77. _ulHighWater = ulSeekStart;
  78. #endif
  79. _ulSeekPos = ulSeekStart;
  80. if (SetFilePointer(_hFile, ulSeekStart, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  81. {
  82. return STG_SCODE(GetLastError());
  83. }
  84. CheckSeek();
  85. if (!SetEndOfFile(_hFile))
  86. {
  87. return STG_SCODE(GetLastError());
  88. }
  89. simpDebugOut((DEB_ITRACE, "Out CSimpStream::Init\n"));
  90. return S_OK;
  91. }
  92. //+--------------------------------------------------------------
  93. //
  94. // Member: CSimpStream::Read, public
  95. //
  96. // Synopsis: Read from a stream
  97. //
  98. // Arguments: [pb] - Buffer
  99. // [cb] - Count of bytes to read
  100. // [pcbRead] - Return number of bytes read
  101. //
  102. // Returns: Appropriate status code
  103. //
  104. // Modifies: [pcbRead]
  105. //
  106. // History: 04-Aug-94 PhilipLa Created
  107. //
  108. //---------------------------------------------------------------
  109. STDMETHODIMP CSimpStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
  110. {
  111. ULONG cbRead;
  112. ULONG *pcb;
  113. SCODE sc;
  114. olLog(("%p::In CSimpStream::Read(%p, %lu, %p)\n",
  115. this, pb, cb, pcbRead));
  116. SIMP_VALIDATE(Read(pb, cb, pcbRead));
  117. pcb = (pcbRead != NULL) ? pcbRead : &cbRead;
  118. #ifdef SECURE_SIMPLE_MODE
  119. if (_ulSeekPos + cb > _ulHighWater)
  120. {
  121. ULONG cbTotalSize;
  122. cbTotalSize = GetFileSize(_hFile, NULL);
  123. if (_ulSeekPos + cb > cbTotalSize)
  124. {
  125. //Truncate.
  126. cb = (_ulSeekPos > cbTotalSize) ? 0 : cbTotalSize - _ulSeekPos;
  127. }
  128. //Part of this read would come from uninitialized space, so
  129. // we need to return zeroes instead.
  130. if (_ulSeekPos > _ulHighWater)
  131. {
  132. if (SetFilePointer(_hFile,
  133. _ulSeekPos + cb,
  134. NULL,
  135. FILE_BEGIN) == 0xFFFFFFFF)
  136. {
  137. //We can't get the seek pointer where it will need to
  138. // end up, so return zero bytes and be done with it.
  139. *pcb = 0;
  140. return S_OK;
  141. }
  142. //Actually, the whole thing is coming from uninitialized
  143. // space. Why someone would do this is a mystery, but
  144. // let's return zeroes anyway.
  145. memset(pb, SECURECHAR, cb);
  146. *pcb = cb;
  147. _ulSeekPos += cb;
  148. }
  149. else
  150. {
  151. ULONG cbBytesToRead = _ulHighWater - _ulSeekPos;
  152. if (FAILED(sc = Read(pb, cbBytesToRead, pcb)))
  153. {
  154. CheckSeek();
  155. return sc;
  156. }
  157. cb -= *pcb;
  158. if ((*pcb != cbBytesToRead) ||
  159. (SetFilePointer(_hFile,
  160. _ulSeekPos + cb,
  161. NULL,
  162. FILE_BEGIN) == 0xFFFFFFFF))
  163. {
  164. //Either the Read call returned a weird number of bytes,
  165. // Or
  166. //We can't actually get the seek pointer where we need
  167. // it, so return fewer bytes than we normally would,
  168. // with a success code.
  169. CheckSeek();
  170. return S_OK;
  171. }
  172. //Zero the rest of the buffer.
  173. memset((BYTE *)pb + *pcb, SECURECHAR, cb);
  174. *pcb += cb;
  175. _ulSeekPos += cb;
  176. }
  177. CheckSeek();
  178. return S_OK;
  179. }
  180. #endif
  181. //Maps directly to ReadFile call
  182. BOOL f = ReadFile(_hFile,
  183. pb,
  184. cb,
  185. pcb,
  186. NULL);
  187. _ulSeekPos += *pcb;
  188. CheckSeek();
  189. if (!f)
  190. return STG_SCODE(GetLastError());
  191. olLog(("%p::Out CSimpStream::Read(). *pcbRead == %lu, ret = %lx\n",
  192. this, *pcb, S_OK));
  193. return S_OK;
  194. }
  195. //+--------------------------------------------------------------
  196. //
  197. // Member: CSimpStream::Write, public
  198. //
  199. // Synopsis: Write to a stream
  200. //
  201. // Arguments: [pb] - Buffer
  202. // [cb] - Count of bytes to write
  203. // [pcbWritten] - Return of bytes written
  204. //
  205. // Returns: Appropriate status code
  206. //
  207. // Modifies: [pcbWritten]
  208. //
  209. // History: 04-Aug-94 PhilipLa Created
  210. //
  211. //---------------------------------------------------------------
  212. STDMETHODIMP CSimpStream::Write(
  213. VOID const HUGEP *pb,
  214. ULONG cb,
  215. ULONG *pcbWritten)
  216. {
  217. ULONG cbWritten;
  218. ULONG *pcb;
  219. BOOL f = TRUE;
  220. SCODE sc = S_OK;
  221. olLog(("%p::In CSimpStream::Write(%p, %lu, %p)\n",
  222. this, pb, cb, pcbWritten));
  223. SIMP_VALIDATE(Write(pb, cb, pcbWritten));
  224. pcb = (pcbWritten != NULL) ? pcbWritten : &cbWritten;
  225. if (_ulSeekPos + cb >= OLOCKREGIONBEGIN)
  226. return STG_E_DOCFILETOOLARGE;
  227. #ifdef SECURE_SIMPLE_MODE
  228. if (_ulSeekPos > _ulHighWater)
  229. {
  230. //We're leaving a gap in the file, so we need to fill in that
  231. // gap. Sad but true.
  232. ULONG cbBytesToWrite = _ulSeekPos - _ulHighWater;
  233. ULONG cbWrittenSecure;
  234. if (SetFilePointer(_hFile,
  235. _ulHighWater,
  236. NULL,
  237. FILE_BEGIN) != 0xFFFFFFFF)
  238. {
  239. while (cbBytesToWrite > 0)
  240. {
  241. if (!(f = WriteFile(_hFile,
  242. s_bufSecure,
  243. min(MINISTREAMSIZE, cbBytesToWrite),
  244. &cbWrittenSecure,
  245. NULL)))
  246. {
  247. break;
  248. }
  249. cbBytesToWrite -= cbWrittenSecure;
  250. }
  251. if ((!f) && (SetFilePointer(_hFile,
  252. _ulSeekPos,
  253. NULL,
  254. FILE_BEGIN) == 0xFFFFFFFF))
  255. {
  256. return STG_SCODE(GetLastError());
  257. }
  258. }
  259. CheckSeek();
  260. }
  261. #endif
  262. //Maps directly to WriteFile call
  263. f = WriteFile(_hFile,
  264. pb,
  265. cb,
  266. pcb,
  267. NULL);
  268. _ulSeekPos += *pcb;
  269. #ifdef SECURE_SIMPLE_MODE
  270. if (_ulSeekPos > _ulHighWater)
  271. _ulHighWater = _ulSeekPos;
  272. #endif
  273. if (!f)
  274. {
  275. sc = STG_SCODE(GetLastError());
  276. }
  277. CheckSeek();
  278. olLog(("%p::Out CSimpStream::Write(). "
  279. "*pcbWritten == %lu, ret = %lx\n",
  280. this, *pcb, sc));
  281. return sc;
  282. }
  283. //+--------------------------------------------------------------
  284. //
  285. // Member: CSimpStream::Seek, public
  286. //
  287. // Synopsis: Seek to a point in a stream
  288. //
  289. // Arguments: [dlibMove] - Offset to move by
  290. // [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
  291. // [plibNewPosition] - Return of new offset
  292. //
  293. // Returns: Appropriate status code
  294. //
  295. // Modifies: [plibNewPosition]
  296. //
  297. // History: 04-Aug-94 PhilipLa Created
  298. //
  299. //
  300. //---------------------------------------------------------------
  301. STDMETHODIMP CSimpStream::Seek(LARGE_INTEGER dlibMove,
  302. DWORD dwOrigin,
  303. ULARGE_INTEGER *plibNewPosition)
  304. {
  305. SCODE sc = S_OK;
  306. LONG lMove;
  307. ULONG ulPos;
  308. simpAssert((dwOrigin == STREAM_SEEK_SET) || (dwOrigin == STREAM_SEEK_CUR) ||
  309. (dwOrigin == STREAM_SEEK_END));
  310. olLog(("%p::In CSimpStream::Seek(%ld, %lu, %p)\n",
  311. this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
  312. SIMP_VALIDATE(Seek(dlibMove, dwOrigin, plibNewPosition));
  313. // Truncate dlibMove to 32 bits
  314. if (dwOrigin == STREAM_SEEK_SET)
  315. {
  316. // Make sure we don't seek too far
  317. if (LIGetHigh(dlibMove) != 0)
  318. LISet32(dlibMove, 0xffffffff);
  319. }
  320. else
  321. {
  322. // High dword must be zero for positive values or -1 for
  323. // negative values
  324. // Additionally, for negative values, the low dword can't
  325. // exceed -0x80000000 because the 32nd bit is the sign
  326. // bit
  327. if (LIGetHigh(dlibMove) > 0 ||
  328. (LIGetHigh(dlibMove) == 0 &&
  329. LIGetLow(dlibMove) >= 0x80000000))
  330. LISet32(dlibMove, 0x7fffffff);
  331. else if (LIGetHigh(dlibMove) < -1 ||
  332. (LIGetHigh(dlibMove) == -1 &&
  333. LIGetLow(dlibMove) <= 0x7fffffff))
  334. LISet32(dlibMove, 0x80000000);
  335. }
  336. lMove = (LONG)LIGetLow(dlibMove);
  337. switch(dwOrigin)
  338. {
  339. case STREAM_SEEK_SET:
  340. ulPos = _ulSeekStart + lMove;
  341. break;
  342. case STREAM_SEEK_END:
  343. ULONG cbSize;
  344. cbSize = GetFileSize(_hFile, NULL);
  345. if (lMove < 0)
  346. {
  347. if ((ULONG)(-lMove) > (cbSize - _ulSeekStart))
  348. return STG_E_INVALIDFUNCTION;
  349. }
  350. ulPos = cbSize+lMove;
  351. break;
  352. case STREAM_SEEK_CUR:
  353. ulPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
  354. if (lMove < 0)
  355. {
  356. if ((ULONG)(-lMove) > (ulPos - _ulSeekStart))
  357. return STG_E_INVALIDFUNCTION;
  358. }
  359. ulPos += lMove;
  360. break;
  361. }
  362. ulPos = SetFilePointer(_hFile,
  363. ulPos,
  364. NULL,
  365. FILE_BEGIN);
  366. if (plibNewPosition != NULL)
  367. {
  368. ULISet32(*plibNewPosition, ulPos - _ulSeekStart);
  369. }
  370. _ulSeekPos = ulPos;
  371. CheckSeek();
  372. olLog(("%p::Out CSimpStream::Seek(). ulPos == %lu, ret == %lx\n",
  373. this, ulPos, sc));
  374. return sc;
  375. }
  376. //+--------------------------------------------------------------
  377. //
  378. // Member: CSimpStream::SetSize, public
  379. //
  380. // Synopsis: Sets the size of a stream
  381. //
  382. // Arguments: [ulNewSize] - New size
  383. //
  384. // Returns: Appropriate status code
  385. //
  386. // History: 04-Aug-94 PhilipLa Created
  387. //
  388. //---------------------------------------------------------------
  389. STDMETHODIMP CSimpStream::SetSize(ULARGE_INTEGER ulNewSize)
  390. {
  391. ULONG ulCurrentPos;
  392. SCODE sc;
  393. olLog(("%p::In CSimpStream::SetSize(%lu)\n",
  394. this, ULIGetLow(ulNewSize)));
  395. SIMP_VALIDATE(SetSize(ulNewSize));
  396. ulCurrentPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
  397. if (ulCurrentPos == 0xFFFFFFFF)
  398. {
  399. return STG_SCODE(GetLastError());
  400. }
  401. if (ULIGetHigh(ulNewSize) != 0 ||
  402. ulCurrentPos + ULIGetLow(ulNewSize) >= OLOCKREGIONBEGIN)
  403. return STG_E_DOCFILETOOLARGE;
  404. if (SetFilePointer(_hFile,
  405. ULIGetLow(ulNewSize) + _ulSeekStart,
  406. NULL,
  407. FILE_BEGIN) == 0xFFFFFFFF)
  408. {
  409. CheckSeek();
  410. return STG_SCODE(GetLastError());
  411. }
  412. if (!SetEndOfFile(_hFile))
  413. {
  414. SetFilePointer(_hFile, ulCurrentPos, NULL, FILE_BEGIN);
  415. CheckSeek();
  416. return STG_SCODE(GetLastError());
  417. }
  418. #ifdef SECURE_SIMPLE_MODE
  419. // if we are shrinking the stream below the highwater mark, reset it
  420. if (ULIGetLow(ulNewSize) + _ulSeekStart < _ulHighWater)
  421. {
  422. _ulHighWater = ULIGetLow(ulNewSize) + _ulSeekStart;
  423. }
  424. #endif
  425. if (SetFilePointer(_hFile, ulCurrentPos, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  426. {
  427. _ulSeekPos = ULIGetLow(ulNewSize) + _ulSeekStart;
  428. CheckSeek();
  429. return STG_SCODE(GetLastError());
  430. }
  431. CheckSeek();
  432. olLog(("%p::Out CSimpStream::SetSize(). ret == %lx\n", this, S_OK));
  433. return S_OK;
  434. }
  435. //+--------------------------------------------------------------
  436. //
  437. // Member: CSimpStream::CopyTo, public
  438. //
  439. // Synopsis: Copies information from one stream to another
  440. //
  441. // Arguments: [pstm] - Destination
  442. // [cb] - Number of bytes to copy
  443. // [pcbRead] - Return number of bytes read
  444. // [pcbWritten] - Return number of bytes written
  445. //
  446. // Returns: Appropriate status code
  447. //
  448. // Modifies: [pcbRead]
  449. // [pcbWritten]
  450. //
  451. // History: 04-Aug-94 PhilipLa Created
  452. //
  453. //---------------------------------------------------------------
  454. STDMETHODIMP CSimpStream::CopyTo(IStream *pstm,
  455. ULARGE_INTEGER cb,
  456. ULARGE_INTEGER *pcbRead,
  457. ULARGE_INTEGER *pcbWritten)
  458. {
  459. simpDebugOut((DEB_TRACE, "In CSimpStream::CopyTo("
  460. "%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
  461. pcbRead, pcbWritten));
  462. simpDebugOut((DEB_TRACE, "Out CSimpStream::CopyTo\n"));
  463. return STG_E_INVALIDFUNCTION;
  464. }
  465. //+--------------------------------------------------------------
  466. //
  467. // Member: CSimpStream::Release, public
  468. //
  469. // Synopsis: Releases a stream
  470. //
  471. // Returns: Appropriate status code
  472. //
  473. // History: 04-Aug-94 PhilipLa Created
  474. //
  475. //---------------------------------------------------------------
  476. STDMETHODIMP_(ULONG) CSimpStream::Release(void)
  477. {
  478. LONG lRet;
  479. olLog(("%p::In CSimpStream::Release()\n", this));
  480. simpDebugOut((DEB_TRACE, "In CSimpStream::Release()\n"));
  481. simpAssert(_cReferences > 0);
  482. lRet = AtomicDec(&_cReferences);
  483. if (lRet == 0)
  484. {
  485. #ifdef SECURE_SIMPLE_MODE
  486. _pstgParent->ReleaseCurrentStream(_ulHighWater);
  487. #else
  488. _pstgParent->ReleaseCurrentStream();
  489. #endif
  490. delete this;
  491. }
  492. else if (lRet < 0)
  493. lRet = 0;
  494. simpDebugOut((DEB_TRACE, "Out CSimpStream::Release\n"));
  495. olLog(("%p::Out CSimpStream::Release(). ret == %lu\n", this, lRet));
  496. FreeLogFile();
  497. return lRet;
  498. }
  499. //+--------------------------------------------------------------
  500. //
  501. // Member: CSimpStream::Stat, public
  502. //
  503. // Synopsis: Fills in a buffer of information about this object
  504. //
  505. // Arguments: [pstatstg] - Buffer
  506. //
  507. // Returns: Appropriate status code
  508. //
  509. // Modifies: [pstatstg]
  510. //
  511. // History: 04-Aug-94 PhilipLa Created
  512. //
  513. //---------------------------------------------------------------
  514. STDMETHODIMP CSimpStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
  515. {
  516. SCODE sc = S_OK;
  517. simpDebugOut((DEB_TRACE, "In CSimpStream::Stat(%p, %lu)\n",
  518. pstatstg, grfStatFlag));
  519. SIMP_VALIDATE(Stat(pstatstg, grfStatFlag));
  520. memset (pstatstg, 0, sizeof(STATSTG));
  521. if (!(grfStatFlag & STATFLAG_NONAME))
  522. {
  523. return STG_E_INVALIDFLAG;
  524. //pstatstg->pwcsName = (WCHAR *) CoTaskMemAlloc (
  525. // _pdfl->GetName()->GetLength()+sizeof(WCHAR));
  526. //if (pstatstg->pwcsName)
  527. //{
  528. // memcpy (pstatstg->pwcsName, _pdfl->GetName()->GetBuffer(),
  529. // _pdfl->GetName()->GetLength());
  530. // pstatstg->pwcsName[_pdfl->GetName()->GetLength()/sizeof(WCHAR)]
  531. // = L'\0';
  532. //}
  533. //else sc = STG_E_INSUFFICIENTMEMORY;
  534. }
  535. pstatstg->cbSize.LowPart = _ulSeekPos - _ulSeekStart;
  536. pstatstg->cbSize.HighPart = 0;
  537. pstatstg->type = STGTY_STREAM;
  538. pstatstg->grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  539. simpDebugOut((DEB_TRACE, "Out CSimpStream::Stat\n"));
  540. return sc;
  541. }
  542. //+--------------------------------------------------------------
  543. //
  544. // Member: CSimpStream::Clone, public
  545. //
  546. // Synopsis: Clones a stream
  547. //
  548. // Returns: Appropriate status code
  549. //
  550. // History: 04-Aug-94 PhilipLa Created
  551. //
  552. //---------------------------------------------------------------
  553. STDMETHODIMP CSimpStream::Clone(IStream **ppstm)
  554. {
  555. simpDebugOut((DEB_TRACE, "In CSimpStream::Clone(%p)\n",
  556. ppstm));
  557. simpDebugOut((DEB_TRACE, "Out CSimpStream::Clone\n"));
  558. return STG_E_INVALIDFUNCTION;
  559. }
  560. //+--------------------------------------------------------------
  561. //
  562. // Member: CSimpStream::AddRef, public
  563. //
  564. // Synopsis: Increments the ref count
  565. //
  566. // Returns: Appropriate status code
  567. //
  568. // History: 04-Aug-94 PhilipLa Created
  569. //
  570. //---------------------------------------------------------------
  571. STDMETHODIMP_(ULONG) CSimpStream::AddRef(void)
  572. {
  573. ULONG ulRet;
  574. olLog(("%p::In CSimpStream::AddRef()\n", this));
  575. simpDebugOut((DEB_TRACE, "In CSimpStream::AddRef()\n"));
  576. AtomicInc(&_cReferences);
  577. ulRet = _cReferences;
  578. simpDebugOut((DEB_TRACE, "Out CSimpStream::AddRef\n"));
  579. olLog(("%p::Out CSimpStream::AddRef(). ret == %lu\n", this, ulRet));
  580. return ulRet;
  581. }
  582. //+--------------------------------------------------------------
  583. //
  584. // Member: CSimpStream::LockRegion, public
  585. //
  586. // Synopsis: Nonfunctional
  587. //
  588. // Returns: Appropriate status code
  589. //
  590. // History: 04-Aug-94 PhilipLa Created
  591. //
  592. //---------------------------------------------------------------
  593. STDMETHODIMP CSimpStream::LockRegion(ULARGE_INTEGER libOffset,
  594. ULARGE_INTEGER cb,
  595. DWORD dwLockType)
  596. {
  597. simpDebugOut((DEB_TRACE, "In CSimpStream::LockRegion("
  598. "%lu, %lu\n", ULIGetLow(cb), dwLockType));
  599. simpDebugOut((DEB_TRACE, "Out CSimpStream::LockRegion\n"));
  600. return ResultFromScode(STG_E_INVALIDFUNCTION);
  601. }
  602. //+--------------------------------------------------------------
  603. //
  604. // Member: CSimpStream::UnlockRegion, public
  605. //
  606. // Synopsis: Nonfunctional
  607. //
  608. // Returns: Appropriate status code
  609. //
  610. // History: 04-Aug-94 PhilipLa Created
  611. //
  612. //---------------------------------------------------------------
  613. STDMETHODIMP CSimpStream::UnlockRegion(ULARGE_INTEGER libOffset,
  614. ULARGE_INTEGER cb,
  615. DWORD dwLockType)
  616. {
  617. simpDebugOut((DEB_TRACE, "In CSimpStream::UnlockRegion(%lu, %lu)\n",
  618. ULIGetLow(cb), dwLockType));
  619. simpDebugOut((DEB_TRACE, "Out CSimpStream::UnlockRegion\n"));
  620. return ResultFromScode(STG_E_INVALIDFUNCTION);
  621. }
  622. //+--------------------------------------------------------------
  623. //
  624. // Member: CSimpStream::Commit, public
  625. //
  626. // Synopsis: No-op in current implementation
  627. //
  628. // Returns: Appropriate status code
  629. //
  630. // History: 04-Aug-94 PhilipLa Created
  631. //
  632. //---------------------------------------------------------------
  633. STDMETHODIMP CSimpStream::Commit(DWORD grfCommitFlags)
  634. {
  635. simpDebugOut((DEB_TRACE, "In CSimpStream::Commit(%lu)\n",
  636. grfCommitFlags));
  637. simpDebugOut((DEB_TRACE, "Out CSimpStream::Commit\n"));
  638. return STG_E_UNIMPLEMENTEDFUNCTION;
  639. }
  640. //+--------------------------------------------------------------
  641. //
  642. // Member: CSimpStream::Revert, public
  643. //
  644. // Synopsis: No-op in current implementation
  645. //
  646. // Returns: Appropriate status code
  647. //
  648. // History: 04-Aug-94 PhilipLa Created
  649. //
  650. //---------------------------------------------------------------
  651. STDMETHODIMP CSimpStream::Revert(void)
  652. {
  653. simpDebugOut((DEB_TRACE, "In CSimpStream::Revert()\n"));
  654. simpDebugOut((DEB_TRACE, "Out CSimpStream::Revert\n"));
  655. return STG_E_INVALIDFUNCTION;
  656. }
  657. //+--------------------------------------------------------------
  658. //
  659. // Member: CSimpStream::QueryInterface, public
  660. //
  661. // Synopsis: Returns an object for the requested interface
  662. //
  663. // Arguments: [iid] - Interface ID
  664. // [ppvObj] - Object return
  665. //
  666. // Returns: Appropriate status code
  667. //
  668. // Modifies: [ppvObj]
  669. //
  670. // History: 04-Aug-94 PhilipLa Created
  671. //
  672. //---------------------------------------------------------------
  673. STDMETHODIMP CSimpStream::QueryInterface(REFIID iid, void **ppvObj)
  674. {
  675. SCODE sc;
  676. olLog(("%p::In CSimpStream::QueryInterface(?, %p)\n",
  677. this, ppvObj));
  678. simpDebugOut((DEB_TRACE, "In CSimpStream::QueryInterface(?, %p)\n",
  679. ppvObj));
  680. SIMP_VALIDATE(QueryInterface(iid, ppvObj));
  681. sc = S_OK;
  682. if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
  683. {
  684. *ppvObj = (IStream *)this;
  685. CSimpStream::AddRef();
  686. }
  687. else if (IsEqualIID(iid, IID_IMarshal))
  688. {
  689. *ppvObj = (IMarshal *)this;
  690. CSimpStream::AddRef();
  691. }
  692. else
  693. sc = E_NOINTERFACE;
  694. simpDebugOut((DEB_TRACE, "Out CSimpStream::QueryInterface => %p\n",
  695. ppvObj));
  696. olLog(("%p::Out CSimpStream::QueryInterface(). "
  697. "*ppvObj == %p, ret == %lx\n", this, *ppvObj, sc));
  698. return ResultFromScode(sc);
  699. }
  700. //+--------------------------------------------------------------
  701. //
  702. // Member: CSimpStream::GetUnmarshalClass, public
  703. //
  704. // Synopsis: Returns the class ID
  705. //
  706. // Arguments: [riid] - IID of object
  707. // [pv] - Unreferenced
  708. // [dwDestContext] - Unreferenced
  709. // [pvDestContext] - Unreferenced
  710. // [mshlflags] - Unreferenced
  711. // [pcid] - CLSID return
  712. //
  713. // Returns: Invalid function.
  714. //
  715. // Modifies: [pcid]
  716. //
  717. // History: 04-Aug-94 PhilipLa Created
  718. //
  719. //---------------------------------------------------------------
  720. STDMETHODIMP CSimpStream::GetUnmarshalClass(REFIID riid,
  721. void *pv,
  722. DWORD dwDestContext,
  723. LPVOID pvDestContext,
  724. DWORD mshlflags,
  725. LPCLSID pcid)
  726. {
  727. return STG_E_INVALIDFUNCTION;
  728. }
  729. //+--------------------------------------------------------------
  730. //
  731. // Member: CSimpStream::GetMarshalSizeMax, public
  732. //
  733. // Synopsis: Returns the size needed for the marshal buffer
  734. //
  735. // Arguments: [riid] - IID of object being marshaled
  736. // [pv] - Unreferenced
  737. // [dwDestContext] - Unreferenced
  738. // [pvDestContext] - Unreferenced
  739. // [mshlflags] - Unreferenced
  740. // [pcbSize] - Size return
  741. //
  742. // Returns: Appropriate status code
  743. //
  744. // Modifies: [pcbSize]
  745. //
  746. // History: 04-Aug-94 PhilipLa Created
  747. //
  748. //---------------------------------------------------------------
  749. STDMETHODIMP CSimpStream::GetMarshalSizeMax(REFIID riid,
  750. void *pv,
  751. DWORD dwDestContext,
  752. LPVOID pvDestContext,
  753. DWORD mshlflags,
  754. LPDWORD pcbSize)
  755. {
  756. return STG_E_INVALIDFUNCTION;
  757. }
  758. //+--------------------------------------------------------------
  759. //
  760. // Member: CSimpStream::MarshalInterface, public
  761. //
  762. // Synopsis: Marshals a given object
  763. //
  764. // Arguments: [pstStm] - Stream to write marshal data into
  765. // [riid] - Interface to marshal
  766. // [pv] - Unreferenced
  767. // [dwDestContext] - Unreferenced
  768. // [pvDestContext] - Unreferenced
  769. // [mshlflags] - Unreferenced
  770. //
  771. // Returns: Appropriate status code
  772. //
  773. // History: 04-Aug-94 PhilipLa Created
  774. //
  775. //---------------------------------------------------------------
  776. STDMETHODIMP CSimpStream::MarshalInterface(IStream *pstStm,
  777. REFIID riid,
  778. void *pv,
  779. DWORD dwDestContext,
  780. LPVOID pvDestContext,
  781. DWORD mshlflags)
  782. {
  783. return STG_E_INVALIDFUNCTION;
  784. }
  785. //+--------------------------------------------------------------
  786. //
  787. // Member: CSimpStream::UnmarshalInterface, public
  788. //
  789. // Synopsis: Non-functional
  790. //
  791. // Arguments: [pstStm] -
  792. // [riid] -
  793. // [ppvObj] -
  794. //
  795. // Returns: Appropriate status code
  796. //
  797. // Modifies: [ppvObj]
  798. //
  799. // History: 04-Aug-94 PhilipLa Created
  800. //
  801. //---------------------------------------------------------------
  802. STDMETHODIMP CSimpStream::UnmarshalInterface(IStream *pstStm,
  803. REFIID riid,
  804. void **ppvObj)
  805. {
  806. return STG_E_INVALIDFUNCTION;
  807. }
  808. //+--------------------------------------------------------------
  809. //
  810. // Member: CSimpStream::ReleaseMarshalData, public
  811. //
  812. // Synopsis: Non-functional
  813. //
  814. // Arguments: [pstStm] -
  815. //
  816. // Returns: Appropriate status code
  817. //
  818. // History: 18-Sep-92 PhilipLa Created
  819. //
  820. //---------------------------------------------------------------
  821. STDMETHODIMP CSimpStream::ReleaseMarshalData(IStream *pstStm)
  822. {
  823. return STG_E_INVALIDFUNCTION;
  824. }
  825. //+--------------------------------------------------------------
  826. //
  827. // Member: CSimpStream::DisconnectObject, public
  828. //
  829. // Synopsis: Non-functional
  830. //
  831. // Arguments: [dwRevserved] -
  832. //
  833. // Returns: Appropriate status code
  834. //
  835. // History: 18-Sep-92 PhilipLa Created
  836. //
  837. //---------------------------------------------------------------
  838. STDMETHODIMP CSimpStream::DisconnectObject(DWORD dwReserved)
  839. {
  840. return STG_E_INVALIDFUNCTION;
  841. }
  842. //+---------------------------------------------------------------------------
  843. //
  844. // Member: CSimpStreamOpen::Init, public
  845. //
  846. // Synopsis: Initialize stream object for simple mode read
  847. //
  848. // Arguments: [pstgParent] -- Pointer to parent
  849. // [hFile] -- File handle for writes
  850. // [ulSeekStart] -- Beginning seek pointer
  851. // [grfMode] -- open mode of the stream
  852. // [pdfl] -- CDfNameList entry for this stream
  853. //
  854. // Returns: Appropriate status code
  855. //
  856. // History: 04-Jun-96 HenryLee Created
  857. //
  858. // Notes:
  859. //
  860. //----------------------------------------------------------------------------
  861. SCODE CSimpStreamOpen::Init(CSimpStorageOpen *pstgParent, HANDLE hFile,
  862. ULONG ulSeekStart, DWORD grfMode, CDfNameList *pdfl)
  863. {
  864. simpDebugOut((DEB_ITRACE, "In CSimpStreamOpen::Init:%p()\n", this));
  865. simpAssert (pdfl != NULL);
  866. _ulSeekStart = ulSeekStart;
  867. _pdfl = pdfl;
  868. _hFile = hFile;
  869. _pstgParent = pstgParent;
  870. _cReferences = 1;
  871. _grfMode = grfMode;
  872. if (SetFilePointer(_hFile, ulSeekStart, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  873. {
  874. return HRESULT_FROM_WIN32(GetLastError());
  875. }
  876. #ifdef SECURE_SIMPLE_MODE
  877. _ulHighWater = ulSeekStart + pdfl->GetSize();
  878. #endif
  879. _ulSeekPos = ulSeekStart;
  880. simpDebugOut((DEB_ITRACE, "Out CSimpStreamOpen::Init\n"));
  881. return S_OK;
  882. }
  883. //+--------------------------------------------------------------
  884. //
  885. // Member: CSimpStreamOpen::Read, public
  886. //
  887. // Synopsis: Read from a stream for simple mode open
  888. //
  889. // Arguments: [pb] - Buffer
  890. // [cb] - Count of bytes to read
  891. // [pcbRead] - Return of bytes written
  892. //
  893. // Returns: Appropriate status code
  894. //
  895. // Modifies: [pcbRead]
  896. //
  897. // History: 04-Aug-96 HenryLee Created
  898. //
  899. //---------------------------------------------------------------
  900. STDMETHODIMP CSimpStreamOpen::Read ( VOID *pb, ULONG cb, ULONG *pcbRead)
  901. {
  902. SCODE sc = S_OK;
  903. simpAssert (_pdfl != NULL);
  904. // cannot read past end of stream
  905. if (_ulSeekPos + cb > _ulSeekStart + _pdfl->GetSize())
  906. cb = _ulSeekStart + _pdfl->GetSize() - _ulSeekPos;
  907. sc = CSimpStream::Read (pb, cb, pcbRead);
  908. return sc;
  909. }
  910. //+--------------------------------------------------------------
  911. //
  912. // Member: CSimpStreamOpen::Write, public
  913. //
  914. // Synopsis: Write to a stream for simple mode open
  915. //
  916. // Arguments: [pb] - Buffer
  917. // [cb] - Count of bytes to write
  918. // [pcbWritten] - Return of bytes written
  919. //
  920. // Returns: Appropriate status code
  921. //
  922. // Modifies: [pcbWritten]
  923. //
  924. // History: 04-Jun-96 HenryLee Created
  925. //
  926. //---------------------------------------------------------------
  927. STDMETHODIMP CSimpStreamOpen::Write(VOID const *pb, ULONG cb, ULONG *pcbWritten)
  928. {
  929. SCODE sc = S_OK;
  930. simpAssert (_pdfl != NULL);
  931. if ((_grfMode & (STGM_READ|STGM_WRITE|STGM_READWRITE)) == STGM_READ)
  932. return STG_E_ACCESSDENIED;
  933. // cannot write past end of stream
  934. if (_ulSeekPos + cb > _ulSeekStart + _pdfl->GetSize())
  935. return STG_E_WRITEFAULT;
  936. sc = CSimpStream::Write (pb, cb, pcbWritten);
  937. return sc;
  938. }
  939. //+--------------------------------------------------------------
  940. //
  941. // Member: CSimpStreamOpen::SetSize, public
  942. //
  943. // Synopsis: Sets the size of a stream for simple mode read
  944. //
  945. // Arguments: [ulNewSize] - New size
  946. //
  947. // Returns: Appropriate status code
  948. //
  949. // History: 04-Jun-96 HenryLee Created
  950. //
  951. //---------------------------------------------------------------
  952. STDMETHODIMP CSimpStreamOpen::SetSize(ULARGE_INTEGER ulNewSize)
  953. {
  954. simpDebugOut((DEB_TRACE, "In CSimpStream2::SetSize()\n"));
  955. simpAssert (_pdfl != NULL);
  956. return STG_E_INVALIDFUNCTION;
  957. simpDebugOut((DEB_TRACE, "Out CSimpStreamOpen::SetSize\n"));
  958. }
  959. //+--------------------------------------------------------------
  960. //
  961. // Member: CSimpStreamOpen::Release, public
  962. //
  963. // Synopsis: Releases a stream
  964. //
  965. // Returns: Appropriate status code
  966. //
  967. // History: 04-Jun-96 HenryLee Created
  968. //
  969. //---------------------------------------------------------------
  970. STDMETHODIMP_(ULONG) CSimpStreamOpen::Release()
  971. {
  972. simpDebugOut((DEB_TRACE, "In CSimpStreamOpen::Release()\n"));
  973. simpAssert(_cReferences > 0);
  974. LONG lRet = AtomicDec(&_cReferences);
  975. if (lRet == 0)
  976. {
  977. ((CSimpStorageOpen *)_pstgParent)->ReleaseCurrentStream();
  978. delete this;
  979. }
  980. else if (lRet < 0)
  981. lRet = 0;
  982. simpDebugOut((DEB_TRACE, "Out CSimpStreamOpen::Release\n"));
  983. return lRet;
  984. }
  985. //+--------------------------------------------------------------
  986. //
  987. // Member: CSimpStreamOpen::Seek, public
  988. //
  989. // Synopsis: Seek to a point in a stream
  990. //
  991. // Arguments: [dlibMove] - Offset to move by
  992. // [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
  993. // [plibNewPosition] - Return of new offset
  994. //
  995. // Returns: Appropriate status code
  996. //
  997. // Modifies: [plibNewPosition]
  998. //
  999. // History: 04-Sep-96 HenryLee Created
  1000. //
  1001. //
  1002. //---------------------------------------------------------------
  1003. STDMETHODIMP CSimpStreamOpen::Seek(LARGE_INTEGER dlibMove,
  1004. DWORD dwOrigin,
  1005. ULARGE_INTEGER *plibNewPosition)
  1006. {
  1007. SCODE sc = S_OK;
  1008. LONG lMove;
  1009. ULONG ulPos;
  1010. simpDebugOut((DEB_TRACE, "%p::In CSimpStreamOpen::Seek(%ld, %lu, %p)\n",
  1011. this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
  1012. SIMP_VALIDATE(Seek(dlibMove, dwOrigin, plibNewPosition));
  1013. // Truncate dlibMove to 32 bits
  1014. if (dwOrigin == STREAM_SEEK_SET)
  1015. {
  1016. if (LIGetHigh(dlibMove) != 0) // Make sure we don't seek too far
  1017. LISet32(dlibMove, 0xffffffff);
  1018. }
  1019. else
  1020. {
  1021. // High dword must be zero for positive values or -1 for
  1022. // negative values
  1023. // Additionally, for negative values, the low dword can't
  1024. // exceed -0x80000000 because the 32nd bit is the sign
  1025. // bit
  1026. if (LIGetHigh(dlibMove) > 0 ||
  1027. (LIGetHigh(dlibMove) == 0 && LIGetLow(dlibMove) >= 0x80000000))
  1028. LISet32(dlibMove, 0x7fffffff);
  1029. else if (LIGetHigh(dlibMove) < -1 ||
  1030. (LIGetHigh(dlibMove) == -1 && LIGetLow(dlibMove) <= 0x7fffffff))
  1031. LISet32(dlibMove, 0x80000000);
  1032. }
  1033. lMove = (LONG)LIGetLow(dlibMove);
  1034. switch(dwOrigin)
  1035. {
  1036. case STREAM_SEEK_SET:
  1037. if (lMove < 0 || (ULONG) lMove > _pdfl->GetSize())
  1038. return STG_E_INVALIDFUNCTION;
  1039. ulPos = _ulSeekStart + lMove;
  1040. break;
  1041. case STREAM_SEEK_END:
  1042. if (lMove > 0 || (lMove < 0 && (ULONG)(-lMove) > _pdfl->GetSize()))
  1043. return STG_E_INVALIDFUNCTION;
  1044. ulPos = _ulSeekStart + _pdfl->GetSize() + lMove;
  1045. break;
  1046. case STREAM_SEEK_CUR:
  1047. ulPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
  1048. if ((ULONG) (ulPos + lMove) > _ulSeekStart + _pdfl->GetSize() ||
  1049. (LONG) (ulPos + lMove) < _ulSeekStart)
  1050. return STG_E_INVALIDFUNCTION;
  1051. ulPos += lMove;
  1052. break;
  1053. }
  1054. ulPos = SetFilePointer(_hFile,
  1055. ulPos,
  1056. NULL,
  1057. FILE_BEGIN);
  1058. if (plibNewPosition != NULL)
  1059. {
  1060. ULISet32(*plibNewPosition, ulPos - _ulSeekStart);
  1061. }
  1062. _ulSeekPos = ulPos;
  1063. simpDebugOut((DEB_TRACE, "%p::Out CSimpStreamOpen::Seek(). ulPos==%lu,"
  1064. " ret==%lx\n", this, ulPos, sc));
  1065. return sc;
  1066. }
  1067. //+--------------------------------------------------------------
  1068. //
  1069. // Member: CSimpStreamOpen::Stat, public
  1070. //
  1071. // Synopsis: Fills in a buffer of information about this object
  1072. //
  1073. // Arguments: [pstatstg] - Buffer
  1074. //
  1075. // Returns: Appropriate status code
  1076. //
  1077. // Modifies: [pstatstg]
  1078. //
  1079. // History: 04-Aug-94 PhilipLa Created
  1080. //
  1081. //---------------------------------------------------------------
  1082. STDMETHODIMP CSimpStreamOpen::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
  1083. {
  1084. SCODE sc = S_OK;
  1085. simpDebugOut((DEB_TRACE, "In CSimpStreamOpen::Stat(%p, %lu)\n",
  1086. pstatstg, grfStatFlag));
  1087. SIMP_VALIDATE(Stat(pstatstg, grfStatFlag));
  1088. simpAssert (_pdfl != NULL);
  1089. memset (pstatstg, 0, sizeof(STATSTG));
  1090. if (!(grfStatFlag & STATFLAG_NONAME))
  1091. {
  1092. pstatstg->pwcsName = (WCHAR *) CoTaskMemAlloc (
  1093. _pdfl->GetName()->GetLength()+sizeof(WCHAR));
  1094. if (pstatstg->pwcsName)
  1095. {
  1096. memcpy (pstatstg->pwcsName, _pdfl->GetName()->GetBuffer(),
  1097. _pdfl->GetName()->GetLength());
  1098. pstatstg->pwcsName[_pdfl->GetName()->GetLength()/sizeof(WCHAR)] =
  1099. L'\0';
  1100. }
  1101. else sc = STG_E_INSUFFICIENTMEMORY;
  1102. }
  1103. pstatstg->cbSize.LowPart = _pdfl->GetSize();
  1104. pstatstg->cbSize.HighPart = 0;
  1105. pstatstg->type = STGTY_STREAM;
  1106. pstatstg->grfMode = _grfMode;
  1107. simpDebugOut((DEB_TRACE, "Out CSimpStreamOpen::Stat\n"));
  1108. return sc;
  1109. }