Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.8 KiB

  1. #ifndef COMSTRM_H
  2. #define COMSTRM_H
  3. //
  4. // JonN 12/01/99
  5. // 384722: compmgmt: GetDataHere is not returning an error
  6. // if buffer is too small
  7. // The callers routinely assume that if stream_ptr is initialized
  8. // using a STGMEDIUM with TYMED_GLOBAL, that STGMEDIUM.hGlobal will
  9. // be kept up to date with each Write(). This is not strictly true
  10. // of a normal IStream, but we will build in this behavior in order
  11. // to avoid changing too much client code. However, since GetDataHere
  12. // (MSDN) specifies that the HGLOBAL should not be changed, we return
  13. // STG_E_MEDIUMFULL if it changes; but we do still replace the HGLOBAL,
  14. // since the old one is implicitly freed and the new one needs to be freed.
  15. //
  16. #ifndef COMPTRS_H
  17. #include <comptrs.h>
  18. #endif
  19. namespace microsoft {
  20. namespace com {
  21. class stream_ptr
  22. {
  23. // Construction
  24. public: stream_ptr() throw()
  25. // Sets the stream to NULL
  26. : m_pStream()
  27. , m_pWritebackHGlobal( NULL )
  28. , m_hgOriginalHGlobal( NULL )
  29. {
  30. }
  31. public: explicit stream_ptr(const stream_ptr& pStream) throw()
  32. : m_pStream()
  33. , m_pWritebackHGlobal( NULL )
  34. , m_hgOriginalHGlobal( NULL )
  35. {
  36. Initialize(pStream.m_pStream);
  37. }
  38. public: explicit stream_ptr(IStream* pStream) throw()
  39. // Saves the stream
  40. : m_pStream()
  41. , m_pWritebackHGlobal( NULL )
  42. , m_hgOriginalHGlobal( NULL )
  43. {
  44. Initialize(pStream);
  45. }
  46. //REVIEW: add template constructors
  47. public: explicit stream_ptr(HGLOBAL global) throw()
  48. // Creates a stream on top of the global
  49. : m_pStream()
  50. , m_pWritebackHGlobal( NULL )
  51. , m_hgOriginalHGlobal( NULL )
  52. {
  53. Initialize(global);
  54. }
  55. public: explicit stream_ptr(LPCOLESTR filename) throw()
  56. // Creates a stream on top of the specified file
  57. : m_pStream()
  58. , m_pWritebackHGlobal( NULL )
  59. , m_hgOriginalHGlobal( NULL )
  60. {
  61. Initialize(filename);
  62. }
  63. public: explicit stream_ptr(STGMEDIUM& stgMedium) throw()
  64. // Saves the provided stream.
  65. : m_pStream()
  66. , m_pWritebackHGlobal( NULL )
  67. , m_hgOriginalHGlobal( NULL )
  68. {
  69. Initialize(stgMedium);
  70. }
  71. public: explicit stream_ptr(STGMEDIUM* pStgMedium) throw()
  72. // Saves the provided stream.
  73. : m_pStream()
  74. , m_pWritebackHGlobal( NULL )
  75. , m_hgOriginalHGlobal( NULL )
  76. {
  77. if (pStgMedium)
  78. Initialize(*pStgMedium);
  79. }
  80. //REVIEW: Add Create and Open functions
  81. //REVIEW: Add all of the assignment operators, cast operators, attach, detach, ->, *, etc.
  82. public: operator IStream*() const throw()
  83. {
  84. //REVIEW: trace on null would be helpful
  85. return m_pStream;
  86. }
  87. public: IStream* operator->() const throw()
  88. {
  89. //REVIEW: trace on null would be helpful
  90. return m_pStream;
  91. }
  92. public: IStream& operator*() const throw()
  93. {
  94. //REVIEW: trace on null would be helpful
  95. return *m_pStream;
  96. }
  97. // Write interfaces
  98. public: HRESULT Write(
  99. const void* pBuffer, unsigned long writeCount, unsigned long& written) throw()
  100. // Write the data contained in the buffer
  101. {
  102. if (m_pStream == NULL)
  103. return E_FAIL; //REVIEW: correct failure code?
  104. HRESULT hr = m_pStream->Write(pBuffer, writeCount, &written);
  105. if (SUCCEEDED(hr) && NULL != m_pWritebackHGlobal)
  106. {
  107. HGLOBAL hgNew = NULL;
  108. hr = GetHGlobalFromStream(m_pStream, &hgNew);
  109. if (SUCCEEDED(hr))
  110. {
  111. if (NULL == m_hgOriginalHGlobal)
  112. *m_pWritebackHGlobal = hgNew;
  113. else if (m_hgOriginalHGlobal != hgNew)
  114. {
  115. //
  116. // When this occurs, the old HGLOBAL has already been freed
  117. //
  118. *m_pWritebackHGlobal = hgNew;
  119. hr = STG_E_MEDIUMFULL;
  120. }
  121. }
  122. }
  123. return hr;
  124. }
  125. public: HRESULT Write(const void* pBuffer, unsigned long writeCount) throw()
  126. {
  127. unsigned long written = 0;
  128. HRESULT hr = Write(pBuffer, writeCount, written);
  129. // 2002/02/15-JonN Security push: do not ignore written!=writeCount
  130. if (SUCCEEDED(hr) && written != writeCount)
  131. hr = STG_E_MEDIUMFULL;
  132. return hr;
  133. }
  134. public: HRESULT Write(const wchar_t* string) throw()
  135. {
  136. // 2002/02/15-JonN pointer check
  137. if (IsBadStringPtrW(string,(UINT_PTR)-1))
  138. {
  139. ASSERT(FALSE);
  140. return E_POINTER;
  141. }
  142. unsigned long len=(unsigned long)(wcslen(string)+1);
  143. return Write(string, len*sizeof(wchar_t), len);
  144. }
  145. public: HRESULT Write(const char* string) throw()
  146. {
  147. // 2002/02/15-JonN pointer check
  148. if (IsBadStringPtrA(string,(UINT_PTR)-1))
  149. {
  150. ASSERT(FALSE);
  151. return E_POINTER;
  152. }
  153. unsigned long len=(unsigned long)(strlen(string)+1);
  154. return Write(string, len, len);
  155. }
  156. //REVIEW: Read interfaces
  157. //REVIEW: Seek
  158. //REVIEW: Stat - broken out
  159. // Initialization. May be used by derived classes to setup the stream for
  160. // different types of storage mediums. These functions are all re-entrant,
  161. // and may be called at any time. They perform all of the appropriate
  162. // clean up and releasing of any resources in previous use.
  163. protected: void Initialize(HGLOBAL hg) throw()
  164. {
  165. //REVIEW: make re-entrant and bullet proof
  166. HRESULT const hr = CreateStreamOnHGlobal(hg, FALSE, &m_pStream);
  167. ASSERT(SUCCEEDED(hr));
  168. }
  169. protected: void Initialize(IStream* pStream) throw()
  170. {
  171. //REVIEW: make re-entrant and bullet proof
  172. m_pStream = pStream;
  173. }
  174. protected: void Initialize(LPCOLESTR filename) throw()
  175. {
  176. UNREFERENCED_PARAMETER (filename);
  177. //REVIEW: make re-entrant and bullet proof
  178. #if 0 //REVIEW: need to create FileStream before this can be enabled
  179. if (!filename || !*filename)
  180. return false;
  181. cip<FileStream> fs = new CComObject<FileStream>;
  182. if (!fs)
  183. return false;
  184. HRESULT hr = fs->Open(filename);
  185. if (FAILED(hr))
  186. return false;
  187. m_pStream = fs;
  188. return true;
  189. #endif // 0
  190. }
  191. protected: void Initialize(STGMEDIUM& storage) throw()
  192. // Initializes the read/write functions based on the type of storage
  193. // medium. If there is a problem, the reader/writer is not set.
  194. {
  195. //REVIEW: make re-entrant and bullet proof
  196. switch (storage.tymed)
  197. {
  198. case TYMED_HGLOBAL:
  199. Initialize(storage.hGlobal);
  200. m_hgOriginalHGlobal = storage.hGlobal;
  201. m_pWritebackHGlobal = &(storage.hGlobal);
  202. return;
  203. case TYMED_FILE:
  204. Initialize(storage.lpszFileName);
  205. return;
  206. case TYMED_ISTREAM:
  207. Initialize(storage.pstm);
  208. return;
  209. }
  210. }
  211. // Implementation
  212. private: IStreamCIP m_pStream;
  213. // This stream is created and used when the TYMED type is HGLOBAL.
  214. //
  215. // JonN 12/01/99 384722: see comments at top of file
  216. //
  217. HGLOBAL m_hgOriginalHGlobal;
  218. HGLOBAL* m_pWritebackHGlobal;
  219. }; // class streamptr
  220. } // namespace com
  221. } // namespace microsoft
  222. #ifndef MICROSOFT_NAMESPACE_ON
  223. using namespace microsoft;
  224. #ifndef COM_NAMESPACE_ON
  225. using namespace com;
  226. #endif // COM_NAMESPACE_ON
  227. #endif // MICROSOFT_NAMESPACE_ON
  228. #endif // COMSTRM_H