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.

244 lines
7.1 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1998 Microsoft Corporation
  6. //
  7. // File: fileio.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // FileIO.cpp
  11. //
  12. #include "aariff.h"
  13. STDAPI AllocFileStream(LPCSTR szFileName, DWORD dwDesiredAccess, IStream **ppstream)
  14. {
  15. HANDLE hfile; // handle to open file
  16. CFileStream * pstream; // IStream implementation
  17. // in case of error...
  18. *ppstream = NULL;
  19. // open the file
  20. if( dwDesiredAccess == GENERIC_READ )
  21. {
  22. hfile = CreateFile( szFileName, dwDesiredAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  23. }
  24. else if( dwDesiredAccess == GENERIC_WRITE )
  25. {
  26. hfile = CreateFile( szFileName, dwDesiredAccess, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  27. }
  28. else
  29. {
  30. return E_INVALIDARG;
  31. }
  32. if( hfile == INVALID_HANDLE_VALUE )
  33. {
  34. //DisplayDebug( 5, "File open error: Can't open \"%s\", error code %d", szFileName, GetLastError() );
  35. return E_FAIL; // to do: real error code
  36. }
  37. // create the Windows object
  38. if ((pstream = new CFileStream(hfile)) == NULL)
  39. return E_OUTOFMEMORY;
  40. // return an IStream pointer
  41. *ppstream = (IStream *) pstream;
  42. return S_OK;
  43. }
  44. STDAPI AllocRIFFStream( IStream* pStream, IAARIFFStream** ppRiff )
  45. {
  46. if( ( *ppRiff = (IAARIFFStream*) new CRIFFStream( pStream ) ) == NULL )
  47. {
  48. return E_OUTOFMEMORY;
  49. }
  50. return S_OK;
  51. }
  52. /* MyRead, MyWrite, MySeek
  53. *
  54. * These are functionally identical to mmioRead, mmioWrite, and mmioSeek,
  55. * except for the absence of the HMMIO parameter.
  56. */
  57. long CRIFFStream::MyRead(void *pv, long cb)
  58. {
  59. ULONG cbRead;
  60. if (FAILED(m_pStream->Read(pv, cb, &cbRead)))
  61. return -1;
  62. return cbRead;
  63. }
  64. long CRIFFStream::MyWrite(const void *pv, long cb)
  65. {
  66. ULONG cbWritten;
  67. if (FAILED(m_pStream->Write(pv, cb, &cbWritten)))
  68. return -1;
  69. return cbWritten;
  70. }
  71. long CRIFFStream::MySeek(long lOffset, int iOrigin)
  72. {
  73. LARGE_INTEGER dlibSeekTo;
  74. ULARGE_INTEGER dlibNewPos;
  75. dlibSeekTo.HighPart = 0;
  76. dlibSeekTo.LowPart = lOffset;
  77. if (FAILED(m_pStream->Seek(dlibSeekTo, iOrigin, &dlibNewPos)))
  78. return -1;
  79. return dlibNewPos.LowPart;
  80. }
  81. UINT CRIFFStream::Descend(LPMMCKINFO lpck, LPMMCKINFO lpckParent, UINT wFlags)
  82. {
  83. FOURCC ckidFind; // chunk ID to find (or NULL)
  84. FOURCC fccTypeFind; // form/list type to find (or NULL)
  85. /* figure out what chunk id and form/list type to search for */
  86. if (wFlags & MMIO_FINDCHUNK)
  87. ckidFind = lpck->ckid, fccTypeFind = NULL;
  88. else
  89. if (wFlags & MMIO_FINDRIFF)
  90. ckidFind = FOURCC_RIFF, fccTypeFind = lpck->fccType;
  91. else
  92. if (wFlags & MMIO_FINDLIST)
  93. ckidFind = FOURCC_LIST, fccTypeFind = lpck->fccType;
  94. else
  95. ckidFind = fccTypeFind = NULL;
  96. lpck->dwFlags = 0L;
  97. for(;;)
  98. {
  99. UINT w;
  100. /* read the chunk header */
  101. if (MyRead(lpck, 2 * sizeof(DWORD)) !=
  102. 2 * sizeof(DWORD))
  103. return MMIOERR_CHUNKNOTFOUND;
  104. FixBytes( FBT_LONG, &lpck->cksize );
  105. /* store the offset of the data part of the chunk */
  106. if ((lpck->dwDataOffset = MySeek(0L, SEEK_CUR)) == -1)
  107. return MMIOERR_CANNOTSEEK;
  108. /* see if the chunk is within the parent chunk (if given) */
  109. if ((lpckParent != NULL) &&
  110. (lpck->dwDataOffset - 8L >=
  111. lpckParent->dwDataOffset + lpckParent->cksize))
  112. return MMIOERR_CHUNKNOTFOUND;
  113. /* if the chunk if a 'RIFF' or 'LIST' chunk, read the
  114. * form type or list type
  115. */
  116. if ((lpck->ckid == FOURCC_RIFF) || (lpck->ckid == FOURCC_LIST))
  117. {
  118. if (MyRead(&lpck->fccType,
  119. sizeof(DWORD)) != sizeof(DWORD))
  120. return MMIOERR_CHUNKNOTFOUND;
  121. }
  122. else
  123. lpck->fccType = NULL;
  124. /* if this is the chunk we're looking for, stop looking */
  125. if ( ((ckidFind == NULL) || (ckidFind == lpck->ckid)) &&
  126. ((fccTypeFind == NULL) || (fccTypeFind == lpck->fccType)) )
  127. break;
  128. /* ascend out of the chunk and try again */
  129. if ((w = Ascend(lpck, 0)) != 0)
  130. return w;
  131. }
  132. return 0;
  133. }
  134. UINT CRIFFStream::Ascend(LPMMCKINFO lpck, UINT /*wFlags*/)
  135. {
  136. if (lpck->dwFlags & MMIO_DIRTY)
  137. {
  138. /* <lpck> refers to a chunk created by CreateChunk();
  139. * check that the chunk size that was written when
  140. * CreateChunk() was called is the real chunk size;
  141. * if not, fix it
  142. */
  143. LONG lOffset; // current offset in file
  144. LONG lActualSize; // actual size of chunk data
  145. if ((lOffset = MySeek(0L, SEEK_CUR)) == -1)
  146. return MMIOERR_CANNOTSEEK;
  147. if ((lActualSize = lOffset - lpck->dwDataOffset) < 0)
  148. return MMIOERR_CANNOTWRITE;
  149. if (LOWORD(lActualSize) & 1)
  150. {
  151. /* chunk size is odd -- write a null pad byte */
  152. if (MyWrite("\0", 1) != 1)
  153. return MMIOERR_CANNOTWRITE;
  154. }
  155. if (lpck->cksize == (DWORD)lActualSize)
  156. return 0;
  157. /* fix the chunk header */
  158. lpck->cksize = lActualSize;
  159. if (MySeek(lpck->dwDataOffset - sizeof(DWORD), SEEK_SET) == -1)
  160. return MMIOERR_CANNOTSEEK;
  161. FixBytes( FBT_LONG, &lpck->cksize );
  162. if (MyWrite(&lpck->cksize, sizeof(DWORD)) != sizeof(DWORD)) {
  163. FixBytes( FBT_LONG, &lpck->cksize );
  164. return MMIOERR_CANNOTWRITE;
  165. }
  166. FixBytes( FBT_LONG, &lpck->cksize );
  167. }
  168. /* seek to the end of the chunk, past the null pad byte
  169. * (which is only there if chunk size is odd)
  170. */
  171. if (MySeek(lpck->dwDataOffset + lpck->cksize + (lpck->cksize & 1L),
  172. SEEK_SET) == -1)
  173. return MMIOERR_CANNOTSEEK;
  174. return 0;
  175. }
  176. UINT CRIFFStream::CreateChunk(LPMMCKINFO lpck, UINT wFlags)
  177. {
  178. int iBytes; // bytes to write
  179. LONG lOffset; // current offset in file
  180. /* store the offset of the data part of the chunk */
  181. if ((lOffset = MySeek(0L, SEEK_CUR)) == -1)
  182. return MMIOERR_CANNOTSEEK;
  183. lpck->dwDataOffset = lOffset + 2 * sizeof(DWORD);
  184. /* figure out if a form/list type needs to be written */
  185. if (wFlags & MMIO_CREATERIFF)
  186. lpck->ckid = FOURCC_RIFF, iBytes = 3 * sizeof(DWORD);
  187. else
  188. if (wFlags & MMIO_CREATELIST)
  189. lpck->ckid = FOURCC_LIST, iBytes = 3 * sizeof(DWORD);
  190. else
  191. iBytes = 2 * sizeof(DWORD);
  192. /* write the chunk header */
  193. FixBytes( FBT_MMCKINFO, lpck );
  194. if (MyWrite(lpck, (LONG) iBytes) != (LONG) iBytes) {
  195. FixBytes( FBT_MMCKINFO, lpck );
  196. return MMIOERR_CANNOTWRITE;
  197. }
  198. FixBytes( FBT_MMCKINFO, lpck );
  199. lpck->dwFlags = MMIO_DIRTY;
  200. return 0;
  201. }