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.

2215 lines
57 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. STRM.CPP
  5. Abstract:
  6. CMemStream implementation.
  7. This is a generic data stream for object/interface marshaling.
  8. History:
  9. a-raymcc 10-Apr-96 Created.
  10. a-raymcc 06-Jun-96 CArena support.
  11. a-raymcc 11-Sep-96 Support NULL pointers
  12. --*/
  13. #include "precomp.h"
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <strm.h>
  17. //***************************************************************************
  18. //
  19. // CMemStream::CMemStream
  20. //
  21. // Standard constructor.
  22. //
  23. // PARAMETERS:
  24. // nFlags
  25. // auto_delete or no_delete. If auto_delete, the internal buffer
  26. // is automatically deallocated at destruct-time. If no_delete,
  27. // it is assumed that another object has acquired the m_pBuffer
  28. // pointer and will deallocate it with m_pArena->Free().
  29. // pArena
  30. // The arena to use for allocation/deallocation. If NULL, the
  31. // CWin32DefaultArena is used.
  32. // nInitialSize
  33. // The initial size of the stream in bytes.
  34. // nGrowBy
  35. // How much to grow the internal buffer by when the caller has written
  36. // past the end-of-stream.
  37. //
  38. //***************************************************************************
  39. // ok
  40. CMemStream::CMemStream(
  41. int nFlags,
  42. CArena *pArena,
  43. int nInitialSize,
  44. int nGrowBy
  45. )
  46. {
  47. _ASSERT((nInitialSize >= 16), __TEXT("CMemStream: Initial size must be >= 16"));
  48. m_lRef = 0;
  49. m_nStatus = no_error;
  50. if (pArena == 0)
  51. m_pArena = _new CWin32DefaultArena;
  52. else
  53. m_pArena = pArena;
  54. m_pArena->AddRef();
  55. m_pBuffer = (BYTE *) m_pArena->Alloc((DWORD) nInitialSize +
  56. sizeof(STREAM_HEADER));
  57. if (!m_pBuffer)
  58. m_nStatus = out_of_memory;
  59. m_dwGrowBy = (DWORD) nGrowBy;
  60. m_dwSize = nInitialSize;
  61. m_dwCurrentPos = 0;
  62. m_nFlags = nFlags;
  63. m_nStackPtr = -1;
  64. m_dwEndOfStream = 0;
  65. // Write the validation header for this new stream.
  66. // ================================================
  67. STREAM_HEADER hdr;
  68. WriteBytes(&hdr, sizeof(STREAM_HEADER));
  69. }
  70. //***************************************************************************
  71. //
  72. // CMemStream::CMemStream
  73. //
  74. // Binding constructor.
  75. //
  76. //***************************************************************************
  77. // ok
  78. CMemStream::CMemStream(
  79. LPVOID pBindingAddress,
  80. CArena *pArena,
  81. int nFlags,
  82. int nGrowBy
  83. )
  84. {
  85. m_nStatus = no_error;
  86. m_pBuffer = (LPBYTE) pBindingAddress;
  87. m_pArena = pArena;
  88. m_pArena->AddRef();
  89. m_nFlags = nFlags;
  90. m_lRef = 0;
  91. // The stream header must be present in the block which
  92. // is being bound to.
  93. // ====================================================
  94. STREAM_HEADER& hdr = *(STREAM_HEADER *) m_pBuffer;
  95. if (!hdr.Verify()) {
  96. m_nStatus = failed;
  97. return;
  98. }
  99. // Initialize the remaining member variables.
  100. // ==========================================
  101. m_dwSize = hdr.dwLength;
  102. m_dwGrowBy = nGrowBy;
  103. m_dwCurrentPos = sizeof(hdr);
  104. m_dwEndOfStream = hdr.dwLength;
  105. m_nFlags = nFlags;
  106. m_nStackPtr = -1;
  107. }
  108. //***************************************************************************
  109. //
  110. // CMemStream::CMemStream
  111. //
  112. // Copy constructor.
  113. //
  114. //***************************************************************************
  115. // ok
  116. CMemStream::CMemStream(CMemStream &Src)
  117. {
  118. m_nStatus = 0;
  119. m_pBuffer = 0;
  120. m_dwGrowBy = 0;
  121. m_dwSize = 0;
  122. m_dwCurrentPos = 0;
  123. m_nFlags = 0;
  124. m_nStackPtr = -1;
  125. m_dwEndOfStream = 0;
  126. m_lRef = 0;
  127. // The assignment operator does not copy the arena
  128. // so as to allow transfers of stream objects between
  129. // arenas. So, we have to set up the arena here.
  130. // ==================================================
  131. m_pArena = Src.m_pArena;
  132. m_pArena->AddRef();
  133. *this = Src;
  134. }
  135. //***************************************************************************
  136. //
  137. // CMemStream::operator =
  138. //
  139. // Note that the arena is not copied as part of the assignment. This
  140. // is to allow transfer of objects between arenas.
  141. //
  142. //***************************************************************************
  143. // ok
  144. CMemStream& CMemStream::operator =(CMemStream &Src)
  145. {
  146. m_nStatus = Src.m_nStatus;
  147. m_dwSize = Src.m_dwSize;
  148. if (m_pBuffer)
  149. m_pArena->Free(m_pBuffer);
  150. m_pBuffer = (BYTE *) m_pArena->Alloc(m_dwSize);
  151. if (!m_pBuffer)
  152. m_nStatus = out_of_memory;
  153. else
  154. memcpy(m_pBuffer, Src.m_pBuffer, m_dwSize);
  155. m_dwGrowBy = Src.m_dwGrowBy;
  156. m_dwCurrentPos = Src.m_dwCurrentPos;
  157. m_nFlags = Src.m_nFlags;
  158. m_nStackPtr = Src.m_nStackPtr;
  159. m_dwEndOfStream = Src.m_dwEndOfStream;
  160. return *this;
  161. }
  162. //***************************************************************************
  163. //
  164. // CMemStream::Deserialize
  165. //
  166. // This function deserializes a stream from a Win32 file handle.
  167. // This function only works for files (including memory mapped files, etc.)
  168. /// and pipes. It will not work for mailslots since they must be read
  169. // in one operation.
  170. //
  171. // PARAMETERS:
  172. // hFile
  173. // The Win32 file handle.
  174. //
  175. // RETURN VALUES:
  176. // failed, out_of_memory, no_error
  177. //
  178. //***************************************************************************
  179. // ok
  180. int CMemStream::Deserialize(HANDLE hFile)
  181. {
  182. Reset();
  183. // Read the header. Note that we read this separately
  184. // first before the stream proper. This is because we
  185. // don't know how much memory to allocate until we have
  186. // read the header.
  187. // ====================================================
  188. STREAM_HEADER &hdr = *(STREAM_HEADER *) m_pBuffer;
  189. BOOL bRes;
  190. DWORD dwRead;
  191. bRes = ReadFile(hFile, &hdr, sizeof(hdr), &dwRead, 0);
  192. if (!bRes || dwRead != sizeof(hdr))
  193. {
  194. DWORD t_LastError = GetLastError () ;
  195. return failed;
  196. }
  197. if (!hdr.Verify())
  198. return failed;
  199. DWORD t_ReadLength = hdr.dwLength;
  200. // Read the rest.
  201. // ===============
  202. if (Resize(hdr.dwLength))
  203. return out_of_memory;
  204. BYTE *t_ReadPosition = m_pBuffer + sizeof ( hdr ) ;
  205. DWORD t_Remainder = m_dwSize - dwRead ;
  206. while ( t_Remainder )
  207. {
  208. bRes = ReadFile(hFile, t_ReadPosition , t_Remainder, &dwRead, 0);
  209. if (!bRes )
  210. return failed;
  211. t_Remainder = t_Remainder - dwRead ;
  212. t_ReadPosition = t_ReadPosition + dwRead ;
  213. }
  214. m_dwEndOfStream = t_ReadLength;
  215. return no_error;
  216. }
  217. //***************************************************************************
  218. //
  219. // CMemStream::Deserialize
  220. //
  221. // This function deserializes a stream from an ANSI C file object.
  222. //
  223. // PARAMETERS:
  224. // fStream
  225. // The ANSI C file object.
  226. //
  227. // RETURN VALUES:
  228. // failed, out_of_memory, no_error
  229. //
  230. //***************************************************************************
  231. // ok
  232. int CMemStream::Deserialize(FILE *fStream)
  233. {
  234. Reset();
  235. STREAM_HEADER &hdr = *(STREAM_HEADER *) m_pBuffer;
  236. if (1 != fread(&hdr, sizeof(STREAM_HEADER), 1, fStream))
  237. return failed;
  238. if (!hdr.Verify())
  239. return failed;
  240. if (Resize(hdr.dwLength) != no_error)
  241. return out_of_memory;
  242. DWORD dwRemainder = m_dwSize - sizeof(hdr);
  243. if (dwRemainder != fread(m_pBuffer + sizeof(hdr), sizeof(BYTE),
  244. dwRemainder, fStream))
  245. return failed;
  246. m_dwEndOfStream = hdr.dwLength;
  247. return no_error;
  248. }
  249. //***************************************************************************
  250. //
  251. // CMemStream::Deserialize
  252. //
  253. // This function deserializes a stream from a memory block.
  254. //
  255. // PARAMETERS:
  256. // pBlock
  257. // The memory block.
  258. // dwSize
  259. // The size of the memory block.
  260. //
  261. // RETURN VALUES:
  262. // failed, no_error
  263. //
  264. //***************************************************************************
  265. int CMemStream::Deserialize(LPBYTE pBlock, DWORD dwSize)
  266. {
  267. Reset();
  268. STREAM_HEADER *pHdr = (STREAM_HEADER *) pBlock;
  269. if (!pHdr->Verify())
  270. return failed;
  271. Resize(pHdr->dwLength);
  272. memcpy(
  273. m_pBuffer,
  274. pBlock,
  275. pHdr->dwLength
  276. );
  277. m_dwEndOfStream = pHdr->dwLength;
  278. return no_error;
  279. }
  280. //***************************************************************************
  281. //
  282. // CMemStream::Resize
  283. //
  284. // Increases the size of the internal buffer. Does not affect the
  285. // current offset or end-of-stream markers.
  286. //
  287. // RETURN VALUES:
  288. // no_error, out_of_memory
  289. //
  290. //***************************************************************************
  291. // ok
  292. int CMemStream::Resize(DWORD dwNewSize)
  293. {
  294. m_pBuffer = (BYTE *) m_pArena->Realloc(m_pBuffer, dwNewSize +
  295. sizeof(STREAM_HEADER));
  296. if (!m_pBuffer) {
  297. m_nStatus = out_of_memory;
  298. return m_nStatus;
  299. }
  300. STREAM_HEADER& hdr = *(STREAM_HEADER *) m_pBuffer;
  301. hdr.dwSignature = SIGNATURE_STREAM ;
  302. hdr.dwLength = dwNewSize + sizeof ( STREAM_HEADER ) ;
  303. m_dwSize = dwNewSize;
  304. return no_error;
  305. }
  306. //***************************************************************************
  307. //
  308. // CMemStream::Serialize
  309. //
  310. // Writes the object to a Win32 file.
  311. //
  312. // PARAMETERS:
  313. // hFile
  314. // The Win32 file handle to which to write the object.
  315. //
  316. // RETURN VALUES:
  317. // failed, no_error
  318. //
  319. //***************************************************************************
  320. // ok
  321. int CMemStream::Serialize(HANDLE hFile)
  322. {
  323. UpdateHdr();
  324. // Write body of stream. This includes the header.
  325. // ================================================
  326. DWORD dwWritten = 0;
  327. BOOL bRes = WriteFile(hFile, m_pBuffer, m_dwEndOfStream, &dwWritten, 0);
  328. if (!bRes || m_dwEndOfStream != dwWritten)
  329. return failed;
  330. return no_error;
  331. }
  332. //***************************************************************************
  333. //
  334. // CMemStream::Serialize
  335. //
  336. // Serializes the entire stream to the specified FILE object, which
  337. // must have been opened in binary mode for writing.
  338. //
  339. // PARAMETERS:
  340. // fStream
  341. // The ANSI C FILE object to which to write the object.
  342. //
  343. // RETURN VALUE:
  344. // no_error, failed
  345. //
  346. //***************************************************************************
  347. // ok
  348. int CMemStream::Serialize(FILE *fStream)
  349. {
  350. UpdateHdr();
  351. // Write body of stream.
  352. // =====================
  353. int nRes = fwrite(m_pBuffer, sizeof(BYTE), m_dwEndOfStream, fStream);
  354. if (nRes != (int) m_dwEndOfStream)
  355. return failed;
  356. return no_error;
  357. }
  358. //***************************************************************************
  359. //
  360. // CMemStream::Serialize
  361. //
  362. // Serializes the entire object to a memory block which is allocated
  363. // with HeapAlloc using the default process heap. The caller must call
  364. // FreeMem() when the block is no longer needed.
  365. //
  366. // PARAMETERS:
  367. // pBlock
  368. // Should point to NULL on entry and will be assigned to point to the
  369. // new memory block containing the serialized form of the object.
  370. // The receiver must call FreeMem() using the default process heap
  371. // when this block is no longer needed.
  372. // pdwSize
  373. // Points to a DWORD which will be set to the size in bytes
  374. // of the returned memory block.
  375. //
  376. // RETURN VALUES:
  377. // out_of_memory, no_error
  378. //
  379. //***************************************************************************
  380. int CMemStream::Serialize(BYTE **pBlock, DWORD *pdwSize, CArena *pArena)
  381. {
  382. UpdateHdr();
  383. if (!pArena)
  384. pArena = m_pArena;
  385. LPVOID pMem = pArena->Alloc(m_dwEndOfStream);
  386. if (!pMem)
  387. return out_of_memory;
  388. memcpy(pMem, m_pBuffer, m_dwEndOfStream);
  389. *pBlock = (BYTE *) pMem;
  390. *pdwSize = m_dwEndOfStream;
  391. return no_error;
  392. }
  393. //***************************************************************************
  394. //
  395. // CMemStream::Append
  396. //
  397. // Appends one CMemStream object onto the end of the current one.
  398. // When deserialization occurs, the stream will appear as one large object;
  399. // the original number of appended objects is lost information.
  400. //
  401. // PARAMETERS:
  402. // pSubStream
  403. // The stream which needs to be appended to 'this' object.
  404. //
  405. // RETURN VALUES:
  406. // no_error, out_of_memory
  407. //
  408. //***************************************************************************
  409. // ok
  410. int CMemStream::Append(CMemStream *pSubstream)
  411. {
  412. DWORD dwNumBytesToCopy = pSubstream->m_dwEndOfStream - sizeof(STREAM_HEADER);
  413. if (no_error != Resize(m_dwEndOfStream + dwNumBytesToCopy))
  414. return out_of_memory;
  415. memcpy(&m_pBuffer[m_dwEndOfStream],
  416. pSubstream->m_pBuffer + sizeof(STREAM_HEADER),
  417. dwNumBytesToCopy
  418. );
  419. m_dwEndOfStream += dwNumBytesToCopy;
  420. m_dwCurrentPos = m_dwEndOfStream;
  421. return no_error;
  422. }
  423. // SAFE AREA
  424. //***************************************************************************
  425. //
  426. // CMemStream::WriteBlob
  427. //
  428. // Return values:
  429. // no_error, out_of_memory
  430. //
  431. //***************************************************************************
  432. // ok
  433. int CMemStream::WriteBlob(BLOB *pBlob)
  434. {
  435. int nRes;
  436. nRes = WriteType(VT_BLOB);
  437. if (nRes) return nRes;
  438. DWORD dwSize = BlobLength(pBlob);
  439. if (WriteBytes(&dwSize, sizeof(DWORD)) != no_error)
  440. return out_of_memory;
  441. if (WriteBytes(BlobDataPtr(pBlob), dwSize) != no_error)
  442. return out_of_memory;
  443. return no_error;
  444. }
  445. //***************************************************************************
  446. //
  447. // CMemStream::WriteDouble
  448. //
  449. // Return values:
  450. // no_error, out_of_memory
  451. //
  452. //***************************************************************************
  453. // ok
  454. int CMemStream::WriteDouble(double dblVal)
  455. {
  456. int nRes;
  457. nRes = WriteType(VT_R8);
  458. if (nRes) return nRes;
  459. nRes = WriteBytes(&dblVal, sizeof(double));
  460. return nRes;
  461. }
  462. //***************************************************************************
  463. //
  464. // CMemStream::WriteFloat
  465. //
  466. // Return values:
  467. // no_error, out_of_memory
  468. //
  469. //***************************************************************************
  470. // ok
  471. int CMemStream::WriteFloat(float fltVal)
  472. {
  473. int nRes;
  474. nRes = WriteType(VT_R4);
  475. if (nRes) return nRes;
  476. nRes = WriteBytes(&fltVal, sizeof(float));
  477. return nRes;
  478. }
  479. //***************************************************************************
  480. //
  481. // CMemStream::WriteFloat
  482. //
  483. // Return values:
  484. // no_error, out_of_memory
  485. //
  486. //***************************************************************************
  487. // ok
  488. int CMemStream::WriteBool(VARIANT_BOOL bVal)
  489. {
  490. int nRes;
  491. nRes = WriteType(VT_BOOL);
  492. if (nRes) return nRes;
  493. nRes = WriteBytes(&bVal, sizeof(VARIANT_BOOL));
  494. return nRes;
  495. }
  496. //***************************************************************************
  497. //
  498. // CMemStream::WriteByte
  499. //
  500. // Return values:
  501. // no_error, out_of_memory
  502. //
  503. //***************************************************************************
  504. // ok
  505. int CMemStream::WriteByte(BYTE b)
  506. {
  507. int nRes;
  508. nRes = WriteType(VT_UI1);
  509. if (nRes) return nRes;
  510. nRes = WriteBytes(&b, sizeof(BYTE));
  511. return nRes;
  512. }
  513. //***************************************************************************
  514. //
  515. // CMemStream::WriteChar
  516. //
  517. // Return values:
  518. // no_error, out_of_memory
  519. //
  520. //***************************************************************************
  521. // ok
  522. int CMemStream::WriteChar(char c)
  523. {
  524. int nRes;
  525. nRes = WriteType(VT_I1);
  526. if (nRes) return nRes;
  527. nRes = WriteBytes(&c, sizeof(char));
  528. return nRes;
  529. }
  530. //***************************************************************************
  531. //
  532. // CMemStream::WriteLong
  533. //
  534. // Return values:
  535. // no_error, out_of_memory
  536. //
  537. //***************************************************************************
  538. // ok
  539. int CMemStream::WriteLong(LONG l)
  540. {
  541. int nRes;
  542. nRes = WriteType(VT_I4);
  543. if (nRes) return nRes;
  544. nRes = WriteBytes(&l, sizeof(LONG));
  545. return nRes;
  546. }
  547. //***************************************************************************
  548. //
  549. // CMemStream::WriteDWORD
  550. //
  551. // Return values:
  552. // no_error, out_of_memory
  553. //
  554. //***************************************************************************
  555. // ok
  556. int CMemStream::WriteDWORD(DWORD dwVal)
  557. {
  558. int nRes;
  559. nRes = WriteType(VT_UI4);
  560. if (nRes) return nRes;
  561. nRes = WriteBytes(&dwVal, sizeof(DWORD));
  562. return nRes;
  563. }
  564. //***************************************************************************
  565. //
  566. // CMemStream::WriteDWORD
  567. //
  568. // Return values:
  569. // no_error, out_of_memory
  570. //
  571. //***************************************************************************
  572. // ok
  573. int CMemStream::WriteWORD(WORD wVal)
  574. {
  575. int nRes;
  576. nRes = WriteType(VT_UI2);
  577. if (nRes) return nRes;
  578. nRes = WriteBytes(&wVal, sizeof(WORD));
  579. return nRes;
  580. }
  581. //***************************************************************************
  582. //
  583. // CMemStream::WriteShort
  584. //
  585. // Return values:
  586. // no_error, out_of_memory
  587. //
  588. //***************************************************************************
  589. // ok
  590. int CMemStream::WriteShort(SHORT iVal)
  591. {
  592. int nRes;
  593. nRes = WriteType(VT_I2);
  594. if (nRes) return nRes;
  595. nRes = WriteBytes(&iVal, sizeof(SHORT));
  596. return nRes;
  597. }
  598. //***************************************************************************
  599. //
  600. // CMemStream::WriteLPSTR
  601. //
  602. // Return values:
  603. // no_error, out_of_memory
  604. //
  605. //***************************************************************************
  606. // ok
  607. int CMemStream::WriteLPSTR(LPSTR pStr)
  608. {
  609. int nRes;
  610. nRes = WriteType(VT_LPSTR);
  611. if (nRes) return nRes;
  612. if (pStr)
  613. {
  614. DWORD dwLen = strlen(pStr);
  615. nRes = WriteBytes(&dwLen, sizeof(DWORD));
  616. if (nRes) return nRes;
  617. nRes = WriteBytes(pStr, strlen(pStr) + 1);
  618. }
  619. // Null pointers are encoded as 0xFFFFFFFF for the string length.
  620. // ==============================================================
  621. else
  622. {
  623. DWORD dwNullEncoding = 0xFFFFFFFF;
  624. nRes = WriteBytes(&dwNullEncoding, sizeof(DWORD));
  625. }
  626. return nRes;
  627. }
  628. //***************************************************************************
  629. //
  630. // CMemStream::WriteLPWSTR
  631. //
  632. // Return values:
  633. // no_error, out_of_memory
  634. //
  635. //***************************************************************************
  636. // ok
  637. int CMemStream::WriteLPWSTR(LPWSTR pStr)
  638. {
  639. int nRes;
  640. nRes = WriteType(VT_LPWSTR);
  641. if (nRes) return nRes;
  642. // If a non-NULL pointer, the length prefixes the string data.
  643. // ============================================================
  644. if (pStr)
  645. {
  646. DWORD dwLen = wcslen(pStr);
  647. nRes = WriteBytes(&dwLen, sizeof(DWORD));
  648. if (nRes) return nRes;
  649. nRes = WriteBytes(pStr, (wcslen(pStr) + 1) * 2);
  650. }
  651. // Null pointers are encoded as 0xFFFFFFFF for the string length.
  652. // ==============================================================
  653. else
  654. {
  655. DWORD dwNullEncoding = 0xFFFFFFFF;
  656. nRes = WriteBytes(&dwNullEncoding, sizeof(DWORD));
  657. }
  658. return nRes;
  659. }
  660. //***************************************************************************
  661. //
  662. // CMemStream::WriteBSTR
  663. //
  664. // Return values:
  665. // no_error, out_of_memory
  666. //
  667. //***************************************************************************
  668. // ok
  669. int CMemStream::WriteBSTR(BSTR pStr)
  670. {
  671. int nRes;
  672. nRes = WriteType(VT_BSTR);
  673. if (nRes) return nRes;
  674. if (pStr)
  675. {
  676. DWORD dwLen = wcslen(pStr);
  677. nRes = WriteBytes(&dwLen, sizeof(DWORD));
  678. if (nRes) return nRes;
  679. nRes = WriteBytes(pStr, (wcslen(pStr) + 1) * 2);
  680. }
  681. // NULL pointers are encoded as 0xFFFFFFFF for the length prefix.
  682. // ==============================================================
  683. else
  684. {
  685. DWORD dwNullEncoding = 0xFFFFFFFF;
  686. nRes = WriteBytes(&dwNullEncoding, sizeof(DWORD));
  687. }
  688. return nRes;
  689. }
  690. //***************************************************************************
  691. //
  692. // CMemStream::WriteCLSID
  693. //
  694. // Return values:
  695. // no_error, out_of_memory
  696. //
  697. //***************************************************************************
  698. // ok
  699. int CMemStream::WriteCLSID(CLSID *pClsId)
  700. {
  701. int nRes;
  702. nRes = WriteType(VT_CLSID);
  703. if (nRes) return nRes;
  704. return WriteBytes(pClsId, sizeof(CLSID));
  705. }
  706. //***************************************************************************
  707. //
  708. // CMemStream::WriteCLSID
  709. //
  710. // Serializes the literal value of a pointer.
  711. //
  712. // Return values:
  713. // no_error, out_of_memory
  714. //
  715. //***************************************************************************
  716. // ok
  717. int CMemStream::WriteUnknown(IUnknown *pObj)
  718. {
  719. int nRes;
  720. nRes = WriteType(VT_UNKNOWN);
  721. if (nRes) return nRes;
  722. return WriteBytes(pObj, sizeof(void *));
  723. }
  724. //***************************************************************************
  725. //
  726. // CMemStream::WriteFILETIME
  727. //
  728. // Return values:
  729. // no_error, out_of_memory
  730. //
  731. //***************************************************************************
  732. // ok
  733. int CMemStream::WriteFILETIME(FILETIME *pTime)
  734. {
  735. int nRes;
  736. nRes = WriteType(VT_FILETIME);
  737. if (nRes) return nRes;
  738. nRes = WriteBytes(pTime, sizeof(FILETIME));
  739. return nRes;
  740. }
  741. //***************************************************************************
  742. //
  743. // CMemStream::WriteCVar
  744. //
  745. // Writes a CVar into the stream.
  746. //
  747. // PARAMETERS:
  748. // pObj
  749. // Points to the CVar object to serialize. The CVar can contains
  750. // an embedded CVarVector array which itself consists of arbitrary
  751. // CVar objects.
  752. //
  753. // RETURN VALUES:
  754. // critical_error (unsupported type)
  755. // no_error
  756. // invalid_parameter
  757. // out_of_memory (returned by embedded calls)
  758. //
  759. //***************************************************************************
  760. // ok
  761. int CMemStream::WriteCVar(CVar *pObj)
  762. {
  763. if (!pObj)
  764. return invalid_parameter;
  765. // Write the CVar type indicator for the deserialization.
  766. // =======================================================
  767. int nRes = WriteType(VT_EX_CVAR);
  768. int nType = pObj->GetType();
  769. // Write out the field.
  770. // ====================
  771. switch (nType) {
  772. case VT_EMPTY:
  773. case VT_NULL: return WriteNull();
  774. case VT_I1: return WriteChar(pObj->GetChar());
  775. case VT_UI1: return WriteByte(pObj->GetByte());
  776. case VT_I2: return WriteShort(pObj->GetShort());
  777. case VT_UI2: return WriteWORD(pObj->GetWord());
  778. case VT_I4: return WriteLong(pObj->GetLong());
  779. case VT_UI4: return WriteDWORD(pObj->GetDWORD());
  780. case VT_BOOL: return WriteBool(pObj->GetBool());
  781. case VT_R4: return WriteFloat(pObj->GetFloat());
  782. case VT_R8: return WriteDouble(pObj->GetDouble());
  783. case VT_LPSTR: return WriteLPSTR(pObj->GetLPSTR());
  784. case VT_LPWSTR: return WriteLPWSTR((LPWSTR) pObj->GetLPWSTR());
  785. case VT_BSTR: return WriteBSTR((LPWSTR) pObj->GetLPWSTR());
  786. // Intentional type mismatch on pObj->GetLPWSTR
  787. // so we don't have to get a new BSTR and deallocate it.
  788. // CVar stores BSTR as LPWSTR internally, so this is ok.
  789. case VT_FILETIME:
  790. {
  791. FILETIME ft = pObj->GetFileTime();
  792. WriteFILETIME(&ft);
  793. return no_error;
  794. }
  795. case VT_BLOB: return WriteBlob((BLOB *) pObj->GetBlob());
  796. case VT_CLSID: return WriteCLSID((CLSID *) pObj->GetClsId());
  797. case VT_EX_CVARVECTOR: return WriteCVarVector((CVarVector *) pObj->GetVarVector());
  798. }
  799. return critical_error;
  800. }
  801. //***************************************************************************
  802. //
  803. // CMemStream::WriteCVarVector
  804. //
  805. // Write the incoming CVarVector to the stream. For efficiency,
  806. // the type indicator is not repeated for each element. However, each
  807. // element can be another embedded VT_EX_CVAR type.
  808. //
  809. // PARAMETERS:
  810. // pVec
  811. // The pointer to the CVarVector object to serialize.
  812. // RETURN VALUE:
  813. // no_error, invalid_parameter, out_of_memory, critical_error
  814. //
  815. //***************************************************************************
  816. // ok
  817. int CMemStream::WriteCVarVector(IN CVarVector *pVec)
  818. {
  819. if (!pVec)
  820. return invalid_parameter;
  821. // Write the CVarVector type indicator for the deserialization.
  822. // ============================================================
  823. if (WriteType(VT_EX_CVARVECTOR) != no_error)
  824. return out_of_memory;
  825. // Write the element type.
  826. // =======================
  827. int nElementType = pVec->GetType();
  828. if (WriteType(nElementType) != no_error)
  829. return out_of_memory;
  830. // Write out the vector length.
  831. // ============================
  832. DWORD dwSize = (DWORD) pVec->Size();
  833. int nRes = WriteBytes(&dwSize, sizeof(DWORD));
  834. // Write out the elements.
  835. // =======================
  836. for (int i = 0; i < pVec->Size(); i++) {
  837. CVar& v = pVec->GetAt(i);
  838. switch (pVec->GetType()) {
  839. case VT_EX_CVARVECTOR:
  840. if (WriteCVarVector((CVarVector *) v.GetVarVector()) != no_error)
  841. return out_of_memory;
  842. break;
  843. case VT_EX_CVAR:
  844. if (WriteCVar(&v) != no_error)
  845. return out_of_memory;
  846. break;
  847. case VT_I1:
  848. {
  849. char c = v.GetChar();
  850. if (WriteBytes(&c, sizeof(char)) != no_error)
  851. return out_of_memory;
  852. break;
  853. }
  854. case VT_UI1:
  855. {
  856. BYTE b = v.GetByte();
  857. if (WriteBytes(&b, sizeof(BYTE)) != no_error)
  858. return out_of_memory;
  859. break;
  860. }
  861. case VT_I2:
  862. {
  863. SHORT i = v.GetShort();
  864. if (WriteBytes(&i, sizeof(SHORT)) != no_error)
  865. return out_of_memory;
  866. break;
  867. }
  868. case VT_UI2:
  869. {
  870. WORD w = v.GetWord();
  871. if (WriteBytes(&w, sizeof(WORD)) != no_error)
  872. return out_of_memory;
  873. break;
  874. }
  875. case VT_I4:
  876. {
  877. LONG l = v.GetLong();
  878. if (WriteBytes(&l, sizeof(LONG)) != no_error)
  879. return out_of_memory;
  880. break;
  881. }
  882. case VT_UI4:
  883. {
  884. DWORD dw = v.GetDWORD();
  885. if (WriteBytes(&dw, sizeof(DWORD)) != no_error)
  886. return out_of_memory;
  887. break;
  888. }
  889. case VT_BOOL:
  890. {
  891. VARIANT_BOOL b = v.GetBool();
  892. if (WriteBytes(&b, sizeof(VARIANT_BOOL)) != no_error)
  893. return out_of_memory;
  894. break;
  895. }
  896. case VT_R4:
  897. {
  898. float f = v.GetFloat();
  899. if (WriteBytes(&f, sizeof(float)) != no_error)
  900. return out_of_memory;
  901. break;
  902. }
  903. case VT_R8:
  904. {
  905. double d = v.GetDouble();
  906. if (WriteBytes(&d, sizeof(double)) != no_error)
  907. return out_of_memory;
  908. break;
  909. }
  910. // NOTES: String types are written with a prefixed with
  911. // a DWORD length indicator so that during deserialization
  912. // the correct buffer length can be allocated before the
  913. // string is read back. The length indicator is in characters,
  914. // not bytes.
  915. case VT_LPSTR:
  916. {
  917. LPSTR pStr = v.GetLPSTR();
  918. DWORD dwLength = strlen(pStr) + 1;
  919. if (WriteBytes(&dwLength, sizeof(DWORD)) != no_error)
  920. return out_of_memory;
  921. if (WriteBytes(pStr, dwLength) != no_error)
  922. return out_of_memory;
  923. break;
  924. }
  925. case VT_LPWSTR:
  926. {
  927. LPWSTR pStr = v.GetLPWSTR();
  928. DWORD dwLength = wcslen(pStr) + 1;
  929. if (WriteBytes(&dwLength, sizeof(DWORD)) != no_error)
  930. return out_of_memory;
  931. if (WriteBytes(pStr, dwLength * 2) != no_error)
  932. return out_of_memory;
  933. break;
  934. }
  935. case VT_BSTR:
  936. {
  937. // Even though the type is BSTR, we request as
  938. // an LPWSTR so as to avoid the lost time of calling
  939. // SysAllocString/SysFreeString, etc.
  940. LPWSTR pStr = v.GetLPWSTR();
  941. DWORD dwLength = wcslen(pStr) + 1;
  942. if (WriteBytes(&dwLength, sizeof(DWORD)) != no_error)
  943. return out_of_memory;
  944. if (WriteBytes(pStr, dwLength * 2) != no_error)
  945. return out_of_memory;
  946. break;
  947. }
  948. case VT_FILETIME:
  949. {
  950. FILETIME ft = v.GetFileTime();
  951. if (WriteBytes(&ft, sizeof(FILETIME)) != no_error)
  952. return out_of_memory;
  953. break;
  954. }
  955. case VT_BLOB:
  956. {
  957. BLOB *p = v.GetBlob();
  958. DWORD dwLen = BlobLength(p);
  959. if (WriteBytes(&dwLen, sizeof(DWORD)) != no_error)
  960. return out_of_memory;
  961. if (WriteBytes(BlobDataPtr(p), dwLen) != no_error)
  962. return out_of_memory;
  963. break;
  964. }
  965. case VT_CLSID:
  966. {
  967. CLSID *p = v.GetClsId();
  968. if (WriteBytes(p, sizeof(CLSID)) != no_error)
  969. return out_of_memory;
  970. break;
  971. }
  972. // This should never execute.
  973. default:
  974. return critical_error;
  975. }
  976. }
  977. return no_error;
  978. }
  979. //***************************************************************************
  980. //
  981. // CMemStream::ReadNull
  982. //
  983. // Return values:
  984. // end_of_stream, type_mismatch, no_error
  985. //
  986. //***************************************************************************
  987. // ok
  988. int CMemStream::ReadNull()
  989. {
  990. int nRes = ReadType();
  991. if (nRes == VT_EMPTY)
  992. return end_of_stream;
  993. else if (nRes != VT_NULL)
  994. return type_mismatch;
  995. return no_error;
  996. }
  997. //***************************************************************************
  998. //
  999. // CMemStream::ReadBytes
  1000. //
  1001. // Return value:
  1002. // no_error, end_of_stream
  1003. //
  1004. //***************************************************************************
  1005. // ok
  1006. int CMemStream::ReadBytes(LPVOID pBlock, DWORD dwLength)
  1007. {
  1008. if (dwLength + m_dwCurrentPos > m_dwEndOfStream) {
  1009. m_dwCurrentPos = m_dwEndOfStream;
  1010. return end_of_stream;
  1011. }
  1012. memcpy(pBlock, &m_pBuffer[m_dwCurrentPos], dwLength);
  1013. m_dwCurrentPos += dwLength;
  1014. return no_error;
  1015. }
  1016. //***************************************************************************
  1017. //
  1018. // CMemStream::WriteBytes
  1019. //
  1020. // Writes the specified bytes at the current offset. The
  1021. // end-of-stream marker is unchanged, unless the current position
  1022. // has been advanced beyond the previous end-of-stream marker by
  1023. // the write. In the latter case, the end-of-stream marker is
  1024. // set to the byte immediately after the write.
  1025. //
  1026. // Return values:
  1027. // no_error, out_of_memory
  1028. //
  1029. //***************************************************************************
  1030. // ok
  1031. int CMemStream::WriteBytes(LPVOID pBlock, DWORD dwLength)
  1032. {
  1033. while (m_dwCurrentPos + dwLength > m_dwSize) {
  1034. m_dwSize += m_dwGrowBy;
  1035. if (Resize(m_dwSize) != no_error)
  1036. return out_of_memory;
  1037. }
  1038. memcpy(&m_pBuffer[m_dwCurrentPos], pBlock, dwLength);
  1039. m_dwCurrentPos += dwLength;
  1040. // Reset the end of stream pointer if we have grown
  1041. if (m_dwCurrentPos > m_dwEndOfStream)
  1042. m_dwEndOfStream = m_dwCurrentPos;
  1043. return no_error;
  1044. }
  1045. //***************************************************************************
  1046. //
  1047. // Macro TYPE_CHECK
  1048. //
  1049. // Checks that the next value in the stream is a type indicator which
  1050. /// matches the current type.
  1051. //
  1052. // Returns end_of_stream or type_mismatch on errors.
  1053. // On error, the current stream pointer is set back to where it was
  1054. // on entry. It is only allowed to advance on success.
  1055. //
  1056. //***************************************************************************
  1057. #define TYPE_CHECK(vt) \
  1058. { \
  1059. Push(); \
  1060. int nType = ReadType(); \
  1061. if (nType == VT_EMPTY) { \
  1062. Pop(FALSE); \
  1063. return end_of_stream; \
  1064. } \
  1065. if (nType != vt) { \
  1066. Pop(FALSE); \
  1067. return type_mismatch; \
  1068. } \
  1069. Pop(TRUE); \
  1070. }
  1071. //***************************************************************************
  1072. //
  1073. // CMemStream::ReadBlob
  1074. //
  1075. // Reads a BLOB and dynamically allocates buffer to hold it. The caller
  1076. // must call FreeMem to free the memory block.
  1077. //
  1078. // Parameters:
  1079. // pBytes
  1080. // A pointer to the user's pointer, which should point to NULL
  1081. // on entry. This will be assigned to point to the new block.
  1082. // pdwSize
  1083. // Points to a DWORD which will be assigned to the size of the
  1084. // returned block.
  1085. //
  1086. // Return values:
  1087. // end_of_stream, type_mismatch, no_error
  1088. //
  1089. //***************************************************************************
  1090. // ok
  1091. int CMemStream::ReadBlob(BLOB *pBlob)
  1092. {
  1093. TYPE_CHECK(VT_BLOB);
  1094. DWORD dwSize = 0;
  1095. int nRes = ReadBytes(&dwSize, sizeof(DWORD));
  1096. if (nRes != no_error)
  1097. return nRes;
  1098. LPVOID pBlock = _new BYTE[dwSize];
  1099. if (pBlock == NULL)
  1100. return out_of_memory;
  1101. nRes = ReadBytes(pBlock, dwSize);
  1102. if (nRes != no_error)
  1103. return end_of_stream;
  1104. pBlob->cbSize = dwSize;
  1105. pBlob->pBlobData = (BYTE *) pBlock;
  1106. return no_error;
  1107. }
  1108. //***************************************************************************
  1109. //
  1110. // CMemStream::ReadDouble
  1111. //
  1112. // Return values:
  1113. // no_error, end_of_stream
  1114. //
  1115. //***************************************************************************
  1116. // ok
  1117. int CMemStream::ReadDouble(double *pdblVal)
  1118. {
  1119. TYPE_CHECK(VT_R8);
  1120. return ReadBytes(pdblVal, sizeof(double));
  1121. }
  1122. //***************************************************************************
  1123. //
  1124. // CMemStream::ReadByte
  1125. //
  1126. // Return values:
  1127. // no_error, end_of_stream
  1128. //
  1129. //***************************************************************************
  1130. // ok
  1131. int CMemStream::ReadByte(BYTE *pByte)
  1132. {
  1133. TYPE_CHECK(VT_UI1);
  1134. return ReadBytes(pByte, sizeof(BYTE));
  1135. }
  1136. //***************************************************************************
  1137. //
  1138. // CMemStream::ReadFloat
  1139. //
  1140. // Return values:
  1141. // no_error, end_of_stream
  1142. //
  1143. //***************************************************************************
  1144. // ok
  1145. int CMemStream::ReadFloat(float *pfltVal)
  1146. {
  1147. TYPE_CHECK(VT_R4);
  1148. return ReadBytes(pfltVal, sizeof(float));
  1149. }
  1150. //***************************************************************************
  1151. //
  1152. // CMemStream::ReadFloat
  1153. //
  1154. // Return values:
  1155. // no_error, end_of_stream
  1156. //
  1157. //***************************************************************************
  1158. // ok
  1159. int CMemStream::ReadBool(VARIANT_BOOL *pBool)
  1160. {
  1161. TYPE_CHECK(VT_BOOL);
  1162. return ReadBytes(pBool, sizeof(VARIANT_BOOL));
  1163. }
  1164. //***************************************************************************
  1165. //
  1166. // CMemStream::ReadWORD
  1167. //
  1168. // Return values:
  1169. // no_error, end_of_stream
  1170. //
  1171. //***************************************************************************
  1172. // ok
  1173. int CMemStream::ReadWORD(WORD *pw)
  1174. {
  1175. TYPE_CHECK(VT_UI2);
  1176. return ReadBytes(pw, sizeof(WORD));
  1177. }
  1178. //***************************************************************************
  1179. //
  1180. // CMemStream::ReadChar
  1181. //
  1182. // Return values:
  1183. // no_error, end_of_stream
  1184. //
  1185. //***************************************************************************
  1186. // ok
  1187. int CMemStream::ReadChar(char *pc)
  1188. {
  1189. TYPE_CHECK(VT_I1);
  1190. return ReadBytes(pc, sizeof(char));
  1191. }
  1192. //***************************************************************************
  1193. //
  1194. // CMemStream::ReadLong
  1195. //
  1196. //***************************************************************************
  1197. // ok
  1198. int CMemStream::ReadLong(LONG *plVal)
  1199. {
  1200. TYPE_CHECK(VT_I4);
  1201. return ReadBytes(plVal, sizeof(LONG));
  1202. }
  1203. //***************************************************************************
  1204. //
  1205. // CMemStream::ReadDWORD
  1206. //
  1207. //***************************************************************************
  1208. // ok
  1209. int CMemStream::ReadDWORD(DWORD *pdwVal)
  1210. {
  1211. TYPE_CHECK(VT_UI4);
  1212. return ReadBytes(pdwVal, sizeof(DWORD));
  1213. }
  1214. //***************************************************************************
  1215. //
  1216. // CMemStream::ReadShort
  1217. //
  1218. //***************************************************************************
  1219. // ok
  1220. int CMemStream::ReadShort(SHORT *piVal)
  1221. {
  1222. TYPE_CHECK(VT_I2);
  1223. return ReadBytes(piVal, sizeof(SHORT));
  1224. }
  1225. //***************************************************************************
  1226. //
  1227. // CMemStream::ReadLPSTR
  1228. //
  1229. //***************************************************************************
  1230. // ok
  1231. int CMemStream::ReadLPSTR(LPSTR *pStr)
  1232. {
  1233. TYPE_CHECK(VT_LPSTR);
  1234. DWORD dwLength = 0;
  1235. int nRes = ReadBytes(&dwLength, sizeof(DWORD));
  1236. if (nRes)
  1237. return nRes;
  1238. // Check for encoded NULL pointer.
  1239. // ===============================
  1240. if (dwLength == 0xFFFFFFFF)
  1241. {
  1242. *pStr = 0;
  1243. return no_error;
  1244. }
  1245. // If here, there is at least a string of some kind,
  1246. // possibly zero length.
  1247. // ==================================================
  1248. *pStr = _new char[dwLength + 1];
  1249. nRes = ReadBytes(*pStr, dwLength + 1); // Include read of NULL
  1250. if (nRes != no_error)
  1251. return nRes;
  1252. return no_error;
  1253. }
  1254. //***************************************************************************
  1255. //
  1256. // CMemStream::ReadLPWSTR
  1257. //
  1258. //***************************************************************************
  1259. // ok
  1260. int CMemStream::ReadLPWSTR(LPWSTR *pStr)
  1261. {
  1262. TYPE_CHECK(VT_LPWSTR);
  1263. DWORD dwLength = 0;
  1264. int nRes = ReadBytes(&dwLength, sizeof(DWORD));
  1265. if (nRes)
  1266. return nRes;
  1267. // Check for encoded NULL pointer.
  1268. // ===============================
  1269. if (dwLength == 0xFFFFFFFF)
  1270. {
  1271. *pStr = 0;
  1272. return no_error;
  1273. }
  1274. // If here, there is at least a string of some kind,
  1275. // possibly zero length.
  1276. // ==================================================
  1277. *pStr = _new wchar_t[dwLength + 1];
  1278. nRes = ReadBytes(*pStr, (dwLength + 1) * 2);
  1279. if (nRes != no_error)
  1280. return nRes;
  1281. return no_error;
  1282. }
  1283. //***************************************************************************
  1284. //
  1285. // CMemStream::ReadBSTR
  1286. //
  1287. //***************************************************************************
  1288. // ok
  1289. int CMemStream::ReadBSTR(BSTR *pStr)
  1290. {
  1291. *pStr = 0;
  1292. TYPE_CHECK(VT_BSTR);
  1293. DWORD dwLength = 0;
  1294. int nRes = ReadBytes(&dwLength, sizeof(DWORD));
  1295. if (nRes)
  1296. return nRes;
  1297. // Check for encoded NULL pointer.
  1298. // ===============================
  1299. if (dwLength == 0xFFFFFFFF)
  1300. {
  1301. *pStr = 0;
  1302. return no_error;
  1303. }
  1304. // If here, there is at least a string of some kind,
  1305. // possibly zero length.
  1306. // ==================================================
  1307. wchar_t* pTemp = _new wchar_t[dwLength + 1];
  1308. nRes = ReadBytes(pTemp, (dwLength + 1) * 2);
  1309. if (nRes != no_error)
  1310. return nRes;
  1311. *pStr = SysAllocString(pTemp);
  1312. delete pTemp;
  1313. return no_error;
  1314. }
  1315. //***************************************************************************
  1316. //
  1317. // CMemStream::ReadCLSID
  1318. //
  1319. //***************************************************************************
  1320. // ok
  1321. int CMemStream::ReadCLSID(CLSID *pClsId)
  1322. {
  1323. TYPE_CHECK(VT_CLSID);
  1324. return ReadBytes(pClsId, sizeof(CLSID));
  1325. }
  1326. //***************************************************************************
  1327. //
  1328. // CMemStream::ReadUnknown
  1329. //
  1330. //***************************************************************************
  1331. // ok
  1332. int CMemStream::ReadUnknown(IUnknown **pObj)
  1333. {
  1334. TYPE_CHECK(VT_UNKNOWN);
  1335. return ReadBytes(*pObj, sizeof(LPVOID));
  1336. }
  1337. //***************************************************************************
  1338. //
  1339. // CMemStream::ReadFILETIME
  1340. //
  1341. // Reads a Win32 FILETIME struct.
  1342. //
  1343. //***************************************************************************
  1344. // ok
  1345. int CMemStream::ReadFILETIME(OUT FILETIME *pTime)
  1346. {
  1347. TYPE_CHECK(VT_FILETIME);
  1348. return ReadBytes(pTime, sizeof(FILETIME));
  1349. }
  1350. //***************************************************************************
  1351. //
  1352. // CMemStream::Read
  1353. //
  1354. // Reads a CVar from the stream.
  1355. //
  1356. // RETURN VALUES:
  1357. // no_error
  1358. // end_of_stream
  1359. //
  1360. //***************************************************************************
  1361. // ok
  1362. int CMemStream::ReadCVar(OUT CVar **pObj)
  1363. {
  1364. TYPE_CHECK(VT_EX_CVAR);
  1365. // Now read the internal type of the CVar. We read ahead, and then
  1366. // move the current pointer back so that subsequent calls to
  1367. // deserialize the typed value will work properly (they all need
  1368. // the type prefixes).
  1369. // ================================================================
  1370. CVar *pVar = _new CVar;
  1371. DWORD dwPos = GetCurrentPos();
  1372. int nVarType = ReadType();
  1373. int nErrorCode = no_error;
  1374. SetCurrentPos(dwPos);
  1375. switch (nVarType) {
  1376. case VT_EMPTY:
  1377. case VT_NULL:
  1378. pVar->SetAsNull();
  1379. break;
  1380. case VT_I1:
  1381. {
  1382. char c = 0;
  1383. if (ReadChar(&c) != no_error) {
  1384. nErrorCode = end_of_stream;
  1385. }
  1386. else
  1387. pVar->SetChar(c);
  1388. }
  1389. break;
  1390. case VT_UI1:
  1391. {
  1392. BYTE b = 0;
  1393. if (ReadByte(&b) != no_error) {
  1394. nErrorCode = end_of_stream;
  1395. }
  1396. else
  1397. pVar->SetByte(b);
  1398. }
  1399. break;
  1400. case VT_I2:
  1401. {
  1402. SHORT i = 0;
  1403. if (ReadShort(&i) != no_error) {
  1404. nErrorCode = end_of_stream;
  1405. }
  1406. else
  1407. pVar->SetShort(i);
  1408. }
  1409. break;
  1410. case VT_UI2:
  1411. {
  1412. WORD w = 0;
  1413. if (ReadWORD(&w) != no_error) {
  1414. nErrorCode = end_of_stream;
  1415. }
  1416. else
  1417. pVar->SetWord(w);
  1418. }
  1419. break;
  1420. case VT_I4:
  1421. {
  1422. LONG l = 0;
  1423. if (ReadLong(&l) != no_error) {
  1424. nErrorCode = end_of_stream;
  1425. }
  1426. else
  1427. pVar->SetLong(l);
  1428. }
  1429. break;
  1430. case VT_UI4:
  1431. {
  1432. DWORD dw = 0;
  1433. if (ReadDWORD(&dw) != no_error) {
  1434. nErrorCode = end_of_stream;
  1435. }
  1436. else
  1437. pVar->SetDWORD(dw);
  1438. }
  1439. break;
  1440. case VT_BOOL:
  1441. {
  1442. VARIANT_BOOL b = 0;
  1443. if (ReadBool(&b) != no_error) {
  1444. nErrorCode = end_of_stream;
  1445. }
  1446. else
  1447. pVar->SetBool(b);
  1448. }
  1449. break;
  1450. case VT_R4:
  1451. {
  1452. float f = (float) 0.0;
  1453. if (ReadFloat(&f) != no_error) {
  1454. nErrorCode = end_of_stream;
  1455. }
  1456. else
  1457. pVar->SetFloat(f);
  1458. }
  1459. break;
  1460. case VT_R8:
  1461. {
  1462. double d = 0.0;
  1463. if (ReadDouble(&d) != no_error) {
  1464. nErrorCode = end_of_stream;
  1465. }
  1466. else
  1467. pVar->SetDouble(d);
  1468. }
  1469. break;
  1470. case VT_LPSTR:
  1471. {
  1472. LPSTR pStr = 0;
  1473. if (ReadLPSTR(&pStr) != no_error) {
  1474. nErrorCode = end_of_stream;
  1475. }
  1476. else
  1477. pVar->SetLPSTR(pStr, TRUE);
  1478. }
  1479. break;
  1480. case VT_LPWSTR:
  1481. {
  1482. LPWSTR pStr = 0;
  1483. if (ReadLPWSTR(&pStr) != no_error) {
  1484. nErrorCode = end_of_stream;
  1485. }
  1486. else
  1487. pVar->SetLPWSTR(pStr, TRUE);
  1488. }
  1489. break;
  1490. case VT_BSTR:
  1491. {
  1492. BSTR Str = 0;
  1493. if (ReadBSTR(&Str) != no_error) {
  1494. nErrorCode = end_of_stream;
  1495. }
  1496. else {
  1497. pVar->SetBSTR(Str, FALSE);
  1498. SysFreeString(Str);
  1499. }
  1500. }
  1501. break;
  1502. case VT_FILETIME:
  1503. {
  1504. FILETIME f = {0};
  1505. if (ReadFILETIME(&f) != no_error) {
  1506. nErrorCode = end_of_stream;
  1507. }
  1508. else
  1509. pVar->SetFileTime(&f);
  1510. }
  1511. break;
  1512. case VT_BLOB:
  1513. {
  1514. BLOB b;
  1515. BlobInit(&b);
  1516. if (ReadBlob(&b) != no_error)
  1517. nErrorCode = end_of_stream;
  1518. else
  1519. pVar->SetBlob(&b, TRUE);
  1520. }
  1521. break;
  1522. case VT_CLSID:
  1523. {
  1524. CLSID ClsId = {0};
  1525. if (ReadCLSID(&ClsId) != no_error)
  1526. nErrorCode = end_of_stream;
  1527. else
  1528. pVar->SetClsId(&ClsId, FALSE);
  1529. }
  1530. break;
  1531. case VT_EX_CVARVECTOR:
  1532. {
  1533. CVarVector *pVec = 0;
  1534. if (ReadCVarVector(&pVec) != no_error)
  1535. nErrorCode = end_of_stream;
  1536. else
  1537. pVar->SetVarVector(pVec, TRUE);
  1538. }
  1539. break;
  1540. }
  1541. if (nErrorCode != no_error)
  1542. delete pVar;
  1543. else
  1544. *pObj = pVar;
  1545. return nErrorCode;
  1546. }
  1547. //***************************************************************************
  1548. //
  1549. // CMemStream::ReadCVarVector
  1550. //
  1551. //
  1552. //***************************************************************************
  1553. // ok
  1554. int CMemStream::ReadCVarVector(CVarVector **pObj)
  1555. {
  1556. *pObj = 0;
  1557. TYPE_CHECK(VT_EX_CVARVECTOR);
  1558. // Read the element type.
  1559. // ======================
  1560. DWORD dwPos = GetCurrentPos();
  1561. int nType = ReadType();
  1562. CVarVector *pVec = _new CVarVector(nType);
  1563. // Read the size of the vector.
  1564. // ============================
  1565. DWORD dwVecSize = 0;
  1566. if (ReadBytes(&dwVecSize, sizeof(DWORD)) != no_error)
  1567. return end_of_stream;
  1568. // Read each element.
  1569. // ==================
  1570. for (DWORD dwIx = 0; dwIx < dwVecSize; dwIx++) {
  1571. switch (nType) {
  1572. case VT_EX_CVARVECTOR:
  1573. {
  1574. CVarVector *pTmpVec = 0;
  1575. if (ReadCVarVector(&pTmpVec) != no_error)
  1576. return end_of_stream;
  1577. pVec->Add(CVar(pTmpVec, TRUE));
  1578. break;
  1579. }
  1580. case VT_EX_CVAR:
  1581. {
  1582. CVar *pVar = 0;
  1583. if (ReadCVar(&pVar) != no_error)
  1584. return end_of_stream;
  1585. pVec->Add(pVar);
  1586. break;
  1587. }
  1588. case VT_I1:
  1589. {
  1590. char c = 0;
  1591. if (ReadBytes(&c, sizeof(char)) != no_error)
  1592. return end_of_stream;
  1593. pVec->Add(CVar(c));
  1594. break;
  1595. }
  1596. case VT_UI1:
  1597. {
  1598. BYTE b = 0;
  1599. if (ReadBytes(&b, sizeof(BYTE)) != no_error)
  1600. return end_of_stream;
  1601. pVec->Add(CVar(b));
  1602. break;
  1603. }
  1604. case VT_I2:
  1605. {
  1606. SHORT i = 0;
  1607. if (ReadBytes(&i, sizeof(SHORT)) != no_error)
  1608. return end_of_stream;
  1609. pVec->Add(CVar(i));
  1610. break;
  1611. }
  1612. case VT_UI2:
  1613. {
  1614. WORD w = 0;
  1615. if (ReadBytes(&w, sizeof(WORD)) != no_error)
  1616. return end_of_stream;
  1617. pVec->Add(CVar(w));
  1618. break;
  1619. }
  1620. case VT_I4:
  1621. {
  1622. LONG l = 0;
  1623. if (ReadBytes(&l, sizeof(LONG)) != no_error)
  1624. return end_of_stream;
  1625. pVec->Add(CVar(l));
  1626. break;
  1627. }
  1628. case VT_UI4:
  1629. {
  1630. DWORD dw = 0;
  1631. if (ReadBytes(&dw, sizeof(DWORD)) != no_error)
  1632. return end_of_stream;
  1633. pVec->Add(CVar(dw));
  1634. break;
  1635. }
  1636. case VT_BOOL:
  1637. {
  1638. VARIANT_BOOL b = 0;
  1639. if (ReadBytes(&b, sizeof(VARIANT_BOOL)) != no_error)
  1640. return end_of_stream;
  1641. pVec->Add(CVar(b));
  1642. break;
  1643. }
  1644. case VT_R4:
  1645. {
  1646. float f = (float) 0.0;
  1647. if (ReadBytes(&f, sizeof(float)) != no_error)
  1648. return end_of_stream;
  1649. pVec->Add(CVar(f));
  1650. break;
  1651. }
  1652. case VT_R8:
  1653. {
  1654. double d = 0.0;
  1655. if (ReadBytes(&d, sizeof(double)) != no_error)
  1656. return end_of_stream;
  1657. pVec->Add(CVar(d));
  1658. break;
  1659. }
  1660. // NOTE: String types were written with a prefixed with
  1661. // a DWORD length indicator so that during deserialization
  1662. // the correct buffer length can be allocated before the
  1663. // string is read back. The length indicator is in characters,
  1664. // not bytes.
  1665. // ============================================================
  1666. case VT_LPSTR:
  1667. {
  1668. DWORD dwLen = 0;
  1669. if (ReadBytes(&dwLen, sizeof(DWORD)) != no_error)
  1670. return end_of_stream;
  1671. LPSTR pStr = _new char[dwLen];
  1672. if (ReadBytes(pStr, dwLen) != no_error)
  1673. return out_of_memory;
  1674. pVec->Add(CVar(pStr, TRUE));
  1675. break;
  1676. }
  1677. case VT_LPWSTR:
  1678. {
  1679. DWORD dwLen = 0;
  1680. if (ReadBytes(&dwLen, sizeof(DWORD)) != no_error)
  1681. return end_of_stream;
  1682. LPWSTR pStr = _new wchar_t[dwLen];
  1683. if (ReadBytes(pStr, dwLen * 2) != no_error)
  1684. return out_of_memory;
  1685. pVec->Add(CVar(pStr, TRUE));
  1686. break;
  1687. }
  1688. case VT_BSTR:
  1689. {
  1690. DWORD dwLen = 0;
  1691. if (ReadBytes(&dwLen, sizeof(DWORD)) != no_error)
  1692. return end_of_stream;
  1693. LPWSTR pStr = _new wchar_t[dwLen];
  1694. if (ReadBytes(pStr, dwLen * 2) != no_error)
  1695. return out_of_memory;
  1696. pVec->Add(CVar(VT_BSTR, pStr, FALSE));
  1697. delete pStr;
  1698. break;
  1699. }
  1700. case VT_FILETIME:
  1701. {
  1702. FILETIME ft = {0};
  1703. if (ReadBytes(&ft, sizeof(FILETIME)) != no_error)
  1704. return end_of_stream;
  1705. pVec->Add(CVar(&ft));
  1706. break;
  1707. }
  1708. case VT_BLOB:
  1709. {
  1710. BLOB b;
  1711. BlobInit(&b);
  1712. DWORD dwLen = 0;
  1713. if (ReadBytes(&dwLen, sizeof(DWORD)) != no_error)
  1714. return end_of_stream;
  1715. LPBYTE pBuf = _new BYTE[dwLen];
  1716. if (ReadBytes(pBuf, dwLen) != no_error)
  1717. return end_of_stream;
  1718. BlobAssign(&b, pBuf, dwLen, TRUE);
  1719. pVec->Add(CVar(&b, TRUE));
  1720. }
  1721. case VT_CLSID:
  1722. {
  1723. CLSID clsid = {0};
  1724. if (ReadBytes(&clsid, sizeof(CLSID)) != no_error)
  1725. return end_of_stream;
  1726. pVec->Add(CVar(&clsid));
  1727. break;
  1728. }
  1729. // This should never execute.
  1730. default:
  1731. return critical_error;
  1732. }
  1733. }
  1734. *pObj = pVec;
  1735. return no_error;
  1736. }
  1737. //***************************************************************************
  1738. //
  1739. // CMemStream::ReadError
  1740. //
  1741. //***************************************************************************
  1742. // ok
  1743. int CMemStream::ReadError(SCODE *pVal)
  1744. {
  1745. TYPE_CHECK(VT_ERROR);
  1746. return ReadBytes(pVal, sizeof(SCODE));
  1747. }
  1748. //***************************************************************************
  1749. //
  1750. // CMemStream::NextType
  1751. //
  1752. //***************************************************************************
  1753. // ok
  1754. int CMemStream::NextType()
  1755. {
  1756. Push();
  1757. int nType = ReadType();
  1758. Pop(FALSE);
  1759. return nType;
  1760. }
  1761. //***************************************************************************
  1762. //
  1763. // CMemStream::ReadType
  1764. //
  1765. // Returns a VT_ type indicator or VT_EMPTY on end-of-stream.
  1766. //
  1767. //***************************************************************************
  1768. // ok
  1769. int CMemStream::ReadType()
  1770. {
  1771. DWORD dwType = VT_EMPTY;
  1772. if (ReadBytes(&dwType, sizeof(DWORD)) == end_of_stream)
  1773. return VT_EMPTY;
  1774. return dwType;
  1775. }
  1776. //***************************************************************************
  1777. //
  1778. // CMemStream::Pop
  1779. //
  1780. //***************************************************************************
  1781. // ok
  1782. void CMemStream::Pop(BOOL bDiscard)
  1783. {
  1784. if (bDiscard)
  1785. m_nStackPtr--;
  1786. else
  1787. m_dwCurrentPos = m_dwStack[m_nStackPtr--];
  1788. }
  1789. //***************************************************************************
  1790. //
  1791. // CMemStream::~CMemStream
  1792. //
  1793. //***************************************************************************
  1794. // ok
  1795. CMemStream::~CMemStream()
  1796. {
  1797. //_ASSERT(m_lRef == 0, "CMemStream used for COM deleted without Release");
  1798. if (m_nFlags == auto_delete)
  1799. m_pArena->Free(m_pBuffer);
  1800. m_pArena->Release();
  1801. }
  1802. //***************************************************************************
  1803. //
  1804. // CMemStream::IStream implementation
  1805. //
  1806. //***************************************************************************
  1807. STDMETHODIMP CMemStream::QueryInterface(REFIID riid, void** ppv)
  1808. {
  1809. if(riid == IID_IUnknown || riid == IID_IStream)
  1810. {
  1811. *ppv = (void*)(IStream*)this;
  1812. AddRef();
  1813. return S_OK;
  1814. }
  1815. else return E_NOINTERFACE;
  1816. }
  1817. STDMETHODIMP CMemStream::Read(
  1818. void *pv,
  1819. ULONG cb,
  1820. ULONG *pcbRead)
  1821. {
  1822. if(ReadBytes(pv, cb) == no_error)
  1823. {
  1824. if(pcbRead) *pcbRead = cb;
  1825. return S_OK;
  1826. }
  1827. else
  1828. {
  1829. if(pcbRead) *pcbRead = 0;
  1830. return S_FALSE;
  1831. }
  1832. }
  1833. STDMETHODIMP CMemStream::Write(
  1834. const void *pv,
  1835. ULONG cb,
  1836. ULONG *pcbWritten)
  1837. {
  1838. if(WriteBytes((void*)pv, cb) == no_error)
  1839. {
  1840. if(pcbWritten) *pcbWritten = cb;
  1841. return S_OK;
  1842. }
  1843. else
  1844. {
  1845. if(pcbWritten) *pcbWritten = 0;
  1846. return S_FALSE;
  1847. }
  1848. }
  1849. STDMETHODIMP CMemStream::Seek(
  1850. LARGE_INTEGER dlibMove,
  1851. DWORD dwOrigin,
  1852. ULARGE_INTEGER *plibNewPosition)
  1853. {
  1854. switch(dwOrigin)
  1855. {
  1856. case STREAM_SEEK_SET:
  1857. SetCurrentPos(dlibMove.LowPart);
  1858. break;
  1859. case STREAM_SEEK_CUR:
  1860. SetCurrentPos(GetCurrentPos() + (long)dlibMove.QuadPart);
  1861. break;
  1862. case STREAM_SEEK_END:
  1863. SetCurrentPos(Size() + (long)dlibMove.QuadPart);
  1864. break;
  1865. }
  1866. if(plibNewPosition)
  1867. {
  1868. plibNewPosition->QuadPart = (LONGLONG)GetCurrentPos();
  1869. }
  1870. return S_OK;
  1871. }
  1872. STDMETHODIMP CMemStream::SetSize(
  1873. ULARGE_INTEGER libNewSize)
  1874. {
  1875. return S_OK;
  1876. }
  1877. STDMETHODIMP CMemStream::CopyTo(
  1878. IStream *pstm,
  1879. ULARGE_INTEGER cb,
  1880. ULARGE_INTEGER *pcbRead,
  1881. ULARGE_INTEGER *pcbWritten)
  1882. {
  1883. _ASSERT(0, __TEXT("CopyTo is called on CMemStream!"));
  1884. return STG_E_INVALIDFUNCTION;
  1885. }
  1886. STDMETHODIMP CMemStream::Commit(
  1887. DWORD grfCommitFlags)
  1888. {
  1889. return S_OK;
  1890. }
  1891. STDMETHODIMP CMemStream::Revert()
  1892. {
  1893. return S_OK;
  1894. }
  1895. STDMETHODIMP CMemStream::LockRegion(
  1896. ULARGE_INTEGER libOffset,
  1897. ULARGE_INTEGER cb,
  1898. DWORD dwLockType)
  1899. {
  1900. return S_OK;
  1901. }
  1902. STDMETHODIMP CMemStream::UnlockRegion(
  1903. ULARGE_INTEGER libOffset,
  1904. ULARGE_INTEGER cb,
  1905. DWORD dwLockType)
  1906. {
  1907. return STG_E_INVALIDFUNCTION;
  1908. }
  1909. STDMETHODIMP CMemStream::Stat(
  1910. STATSTG *pstatstg,
  1911. DWORD grfStatFlag)
  1912. {
  1913. pstatstg->pwcsName = NULL;
  1914. pstatstg->type = STGTY_STREAM;
  1915. pstatstg->cbSize.QuadPart = (LONGLONG)Size();
  1916. return S_OK;
  1917. }
  1918. STDMETHODIMP CMemStream::Clone(
  1919. IStream **ppstm)
  1920. {
  1921. *ppstm = new CMemStream(*this);
  1922. (*ppstm)->AddRef();
  1923. return S_OK;
  1924. }