Logo Search packages:      
Sourcecode: wine version File versions  Download package

loaderstream.c

/* IDirectMusicLoaderFileStream
 * IDirectMusicLoaderResourceStream
 * IDirectMusicLoaderGenericStream
 *
 * Copyright (C) 2003-2004 Rok Mandeljc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 */


/* SIDE NOTES:
 * After extensive testing and structure dumping I came to a conclusion that
 * DirectMusic as in present state implements three types of streams:
 *  1. IDirectMusicLoaderFileStream: stream that was most obvious, since 
 *     it's used for loading from files; it is sort of wrapper around 
 *     CreateFile, ReadFile, WriteFile and SetFilePointer and it supports 
 *     both read and write
 *  2. IDirectMusicLoaderResourceStream: a stream that had to exist, since 
 *     according to MSDN, IDirectMusicLoader supports loading from resource 
 *     as well; in this case, data is represented as a big chunk of bytes, 
 *     from which we "read" (copy) data and keep the trace of our position; 
 *      it supports read only
 *  3. IDirectMusicLoaderGenericStream: this one was the most problematic, 
 *     since I thought it was URL-related; besides, there's no obvious need 
 *     for it, since input streams can simply be cloned, lest loading from 
 *     stream is requested; but if one really thinks about it, input stream 
 *     could be none of 1. or 2.; in this case, a wrapper that offers
 *     IDirectMusicGetLoader interface would be nice, and this is what this 
 *     stream is; as such, all functions are supported, as long as underlying 
 *     ("low-level") stream supports them
 *
 * - Rok Mandeljc; 24. april, 2004
*/

#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "dmloader_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
WINE_DECLARE_DEBUG_CHANNEL(dmfileraw);

static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);
static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface);
static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface);


/*****************************************************************************
 * IDirectMusicLoaderFileStream implementation
 */
/* Custom : */
HRESULT WINAPI IDirectMusicLoaderFileStream_Attach (LPSTREAM iface, LPCWSTR wzFile, LPDIRECTMUSICLOADER8 pLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    TRACE("(%p, %s, %p)\n", This, debugstr_w(wzFile), pLoader);
    IDirectMusicLoaderFileStream_Detach (iface);
    This->hFile = CreateFileW (wzFile, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (This->hFile == INVALID_HANDLE_VALUE) {
        WARN(": failed\n");
        return DMUS_E_LOADER_FAILEDOPEN;
    }
    /* create IDirectMusicGetLoader */
    This->pLoader = pLoader;
    lstrcpynW (This->wzFileName, wzFile, MAX_PATH);
    TRACE(": succeeded\n");
    return S_OK;
}

void WINAPI IDirectMusicLoaderFileStream_Detach (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
      TRACE("(%p)\n", This);
      if (This->hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(This->hFile);
    }
    This->wzFileName[0] = (L'\0');
}


/* IUnknown/IStream part: */
static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
      
      TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
      if (IsEqualIID (riid, &IID_IUnknown) ||
            IsEqualIID (riid, &IID_IStream)) {
            *ppobj = (LPVOID)&This->StreamVtbl;
            IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
            return S_OK;
      } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
            *ppobj = (LPVOID)&This->GetLoaderVtbl;
            IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);         
            return S_OK;
      }

      WARN(": not found\n");
      return E_NOINTERFACE;
}

static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_AddRef (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
      TRACE("(%p): AddRef from %d\n", This, This->dwRef);
      return InterlockedIncrement (&This->dwRef);
}

static ULONG WINAPI IDirectMusicLoaderFileStream_IStream_Release (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
      
      DWORD dwRef = InterlockedDecrement (&This->dwRef);
      TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
      if (dwRef == 0) {
            if (This->hFile)
                  IDirectMusicLoaderFileStream_Detach (iface);
            HeapFree (GetProcessHeap(), 0, This);
      }
      
      return dwRef;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    ULONG cbRead;
      
      TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
    if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
    if (pcbRead == NULL) pcbRead = &cbRead;
    if (!ReadFile (This->hFile, pv, cb, pcbRead, NULL) || *pcbRead != cb) return E_FAIL;
      
      TRACE_(dmfileraw)(": data (size = 0x%08X): '%s'\n", *pcbRead, debugstr_an(pv, *pcbRead));
    return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    LARGE_INTEGER liNewPos;
      
      TRACE_(dmfileraw)("(%p, 0x%08llX, %s, %p)\n", This, dlibMove.QuadPart, resolve_STREAM_SEEK(dwOrigin), plibNewPosition);

      if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;

    liNewPos.u.HighPart = dlibMove.u.HighPart;
    liNewPos.u.LowPart = SetFilePointer (This->hFile, dlibMove.u.LowPart, &liNewPos.u.HighPart, dwOrigin);

    if (liNewPos.u.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) return E_FAIL;
    if (plibNewPosition) plibNewPosition->QuadPart = liNewPos.QuadPart;
    
    return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
      LPSTREAM pOther = NULL;
      HRESULT result;

      TRACE("(%p, %p)\n", iface, ppstm);
      result = DMUSIC_CreateDirectMusicLoaderFileStream ((LPVOID*)&pOther);
      if (FAILED(result)) return result;
      if (This->hFile != INVALID_HANDLE_VALUE) {
            ULARGE_INTEGER ullCurrentPosition;
            result = IDirectMusicLoaderFileStream_Attach (pOther, This->wzFileName, This->pLoader);
            if (SUCCEEDED(result)) {
                  LARGE_INTEGER liZero;
                  liZero.QuadPart = 0;
                  result = IDirectMusicLoaderFileStream_IStream_Seek (iface, liZero, STREAM_SEEK_CUR, &ullCurrentPosition); /* get current position in current stream */
        }
            if (SUCCEEDED(result)) {
                  LARGE_INTEGER liNewPosition;
                  liNewPosition.QuadPart = ullCurrentPosition.QuadPart;
                  result = IDirectMusicLoaderFileStream_IStream_Seek ((LPSTREAM)pOther, liNewPosition, STREAM_SEEK_SET, &ullCurrentPosition);
            }
            if (FAILED(result)) {
                  TRACE(": failed\n");
                  IDirectMusicLoaderFileStream_IStream_Release ((LPSTREAM)pOther);
                  return result;
            }
      }
      TRACE(": succeeded\n");
      *ppstm = (IStream*)pOther;
      return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, StreamVtbl, iface);
    ULONG cbWrite;
      
      TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbWritten);
    if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
    if (pcbWritten == NULL) pcbWritten = &cbWrite;
    if (!WriteFile (This->hFile, pv, cb, pcbWritten, NULL) || *pcbWritten != cb) return E_FAIL;
      
      TRACE_(dmfileraw)(": data (size = 0x%08X): '%s'\n", *pcbWritten, debugstr_an(pv, *pcbWritten));
    return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Revert (LPSTREAM iface) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static const IStreamVtbl DirectMusicLoaderFileStream_Stream_Vtbl = {
      IDirectMusicLoaderFileStream_IStream_QueryInterface,
      IDirectMusicLoaderFileStream_IStream_AddRef,
      IDirectMusicLoaderFileStream_IStream_Release,
      IDirectMusicLoaderFileStream_IStream_Read,
      IDirectMusicLoaderFileStream_IStream_Write,
      IDirectMusicLoaderFileStream_IStream_Seek,
      IDirectMusicLoaderFileStream_IStream_SetSize,
      IDirectMusicLoaderFileStream_IStream_CopyTo,
      IDirectMusicLoaderFileStream_IStream_Commit,
      IDirectMusicLoaderFileStream_IStream_Revert,
      IDirectMusicLoaderFileStream_IStream_LockRegion,
      IDirectMusicLoaderFileStream_IStream_UnlockRegion,
      IDirectMusicLoaderFileStream_IStream_Stat,
      IDirectMusicLoaderFileStream_IStream_Clone
};

/* IDirectMusicGetLoader part: */
static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderFileStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

static ULONG WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderFileStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

static HRESULT WINAPI IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderFileStream, GetLoaderVtbl, iface);

      TRACE("(%p, %p)\n", This, ppLoader);
      *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
      IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
      
      return S_OK;
}

static const IDirectMusicGetLoaderVtbl DirectMusicLoaderFileStream_GetLoader_Vtbl = {
      IDirectMusicLoaderFileStream_IDirectMusicGetLoader_QueryInterface,
      IDirectMusicLoaderFileStream_IDirectMusicGetLoader_AddRef,
      IDirectMusicLoaderFileStream_IDirectMusicGetLoader_Release,
      IDirectMusicLoaderFileStream_IDirectMusicGetLoader_GetLoader
};

HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderFileStream (LPVOID* ppobj) {
      IDirectMusicLoaderFileStream *obj;

      TRACE("(%p)\n", ppobj);
      obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderFileStream));
      if (NULL == obj) {
            *ppobj = NULL;
            return E_OUTOFMEMORY;
      }
      obj->StreamVtbl = &DirectMusicLoaderFileStream_Stream_Vtbl;
      obj->GetLoaderVtbl = &DirectMusicLoaderFileStream_GetLoader_Vtbl;
      obj->dwRef = 0; /* will be inited with QueryInterface */

      return IDirectMusicLoaderFileStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}


/*****************************************************************************
 * IDirectMusicLoaderResourceStream implementation
 */
/* Custom : */
HRESULT WINAPI IDirectMusicLoaderResourceStream_Attach (LPSTREAM iface, LPBYTE pbMemData, LONGLONG llMemLength, LONGLONG llPos, LPDIRECTMUSICLOADER8 pLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
    
      TRACE("(%p, %p, 0x%08llX, 0x%08llx, %p)\n", This, pbMemData, llMemLength, llPos, pLoader);
      if (!pbMemData || !llMemLength) {
            WARN(": invalid pbMemData or llMemLength\n");
            return E_FAIL;
      }
      IDirectMusicLoaderResourceStream_Detach (iface);
      This->pbMemData = pbMemData;
      This->llMemLength = llMemLength;
      This->llPos = llPos;
      This->pLoader = pLoader;
      
    return S_OK;
}

void WINAPI IDirectMusicLoaderResourceStream_Detach (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      TRACE("(%p)\n", This);
      
      This->pbMemData = NULL;
      This->llMemLength = 0;
}


/* IUnknown/IStream part: */
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      
      TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
      if (IsEqualIID (riid, &IID_IUnknown) ||
            IsEqualIID (riid, &IID_IStream)) {
            *ppobj = (LPVOID)&This->StreamVtbl;
            IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
            return S_OK;
      } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
            *ppobj = (LPVOID)&This->GetLoaderVtbl;
            IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);           
            return S_OK;
      }

      WARN(": not found\n");
      return E_NOINTERFACE;
}

static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_AddRef (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      TRACE("(%p): AddRef from %d\n", This, This->dwRef);
      return InterlockedIncrement (&This->dwRef);
}

static ULONG WINAPI IDirectMusicLoaderResourceStream_IStream_Release (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      
      DWORD dwRef = InterlockedDecrement (&This->dwRef);
      TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
      if (dwRef == 0) {
            IDirectMusicLoaderResourceStream_Detach (iface);
            HeapFree (GetProcessHeap(), 0, This);
      }
      
      return dwRef;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
      LPBYTE pByte;
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      
      TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p)\n", This, pv, cb, pcbRead);
      if ((This->llPos + cb) > This->llMemLength) {
            WARN_(dmfileraw)(": requested size out of range\n");
            return E_FAIL;
      }
      
      pByte = &This->pbMemData[This->llPos];
      memcpy (pv, pByte, cb);
      This->llPos += cb; /* move pointer */
      /* FIXME: error checking would be nice */
      if (pcbRead) *pcbRead = cb;
      
      TRACE_(dmfileraw)(": data (size = 0x%08X): '%s'\n", cb, debugstr_an(pv, cb));
    return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);   
      TRACE_(dmfileraw)("(%p, 0x%08llX, %s, %p)\n", This, dlibMove.QuadPart, resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
      
      switch (dwOrigin) {
            case STREAM_SEEK_CUR: {
                  if ((This->llPos + dlibMove.QuadPart) > This->llMemLength) {
                        WARN_(dmfileraw)(": requested offset out of range\n");
                        return E_FAIL;
                  }
                  break;
            }
            case STREAM_SEEK_SET: {
                  if (dlibMove.QuadPart > This->llMemLength) {
                        WARN_(dmfileraw)(": requested offset out of range\n");
                        return E_FAIL;
                  }
                  /* set to the beginning of the stream */
                  This->llPos = 0;
                  break;
            }
            case STREAM_SEEK_END: {
                  /* TODO: check if this is true... I do think offset should be negative in this case */
                  if (dlibMove.QuadPart > 0) {
                        WARN_(dmfileraw)(": requested offset out of range\n");
                        return E_FAIL;
                  }
                  /* set to the end of the stream */
                  This->llPos = This->llMemLength;
                  break;
            }
            default: {
                  ERR_(dmfileraw)(": invalid dwOrigin\n");
                  return E_FAIL;
            }
      }
      /* now simply add */
      This->llPos += dlibMove.QuadPart;

      if (plibNewPosition) plibNewPosition->QuadPart = This->llPos;
      
    return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, StreamVtbl, iface);
      LPSTREAM pOther = NULL;
      HRESULT result;

      TRACE("(%p, %p)\n", iface, ppstm);
      result = DMUSIC_CreateDirectMusicLoaderResourceStream ((LPVOID*)&pOther);
      if (FAILED(result)) return result;
      
      IDirectMusicLoaderResourceStream_Attach (pOther, This->pbMemData, This->llMemLength, This->llPos, This->pLoader);

      TRACE(": succeeded\n");
      *ppstm = (IStream*)pOther;
      return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Revert (LPSTREAM iface) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
      ERR(": should not be needed\n");
    return E_NOTIMPL;
}

static const IStreamVtbl DirectMusicLoaderResourceStream_Stream_Vtbl = {
      IDirectMusicLoaderResourceStream_IStream_QueryInterface,
      IDirectMusicLoaderResourceStream_IStream_AddRef,
      IDirectMusicLoaderResourceStream_IStream_Release,
      IDirectMusicLoaderResourceStream_IStream_Read,
      IDirectMusicLoaderResourceStream_IStream_Write,
      IDirectMusicLoaderResourceStream_IStream_Seek,
      IDirectMusicLoaderResourceStream_IStream_SetSize,
      IDirectMusicLoaderResourceStream_IStream_CopyTo,
      IDirectMusicLoaderResourceStream_IStream_Commit,
      IDirectMusicLoaderResourceStream_IStream_Revert,
      IDirectMusicLoaderResourceStream_IStream_LockRegion,
      IDirectMusicLoaderResourceStream_IStream_UnlockRegion,
      IDirectMusicLoaderResourceStream_IStream_Stat,
      IDirectMusicLoaderResourceStream_IStream_Clone
};

/* IDirectMusicGetLoader part: */
static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderResourceStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

static ULONG WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderResourceStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

static HRESULT WINAPI IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderResourceStream, GetLoaderVtbl, iface);

      TRACE("(%p, %p)\n", This, ppLoader);
      *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
      IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
      
      return S_OK;
}

static const IDirectMusicGetLoaderVtbl DirectMusicLoaderResourceStream_GetLoader_Vtbl = {
      IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_QueryInterface,
      IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_AddRef,
      IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_Release,
      IDirectMusicLoaderResourceStream_IDirectMusicGetLoader_GetLoader
};

HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderResourceStream (LPVOID* ppobj) {
      IDirectMusicLoaderResourceStream *obj;

      TRACE("(%p)\n", ppobj);
      obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderResourceStream));
      if (NULL == obj) {
            *ppobj = NULL;
            return E_OUTOFMEMORY;
      }
      obj->StreamVtbl = &DirectMusicLoaderResourceStream_Stream_Vtbl;
      obj->GetLoaderVtbl = &DirectMusicLoaderResourceStream_GetLoader_Vtbl;
      obj->dwRef = 0; /* will be inited with QueryInterface */

      return IDirectMusicLoaderResourceStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}


/*****************************************************************************
 * IDirectMusicLoaderGenericStream implementation
 */
/* Custom : */
HRESULT WINAPI IDirectMusicLoaderGenericStream_Attach (LPSTREAM iface, LPSTREAM pStream, LPDIRECTMUSICLOADER8 pLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
    
      TRACE("(%p, %p, %p)\n", This, pStream, pLoader);
      if (!pStream) {
            WARN(": invalid pStream\n");
            return E_FAIL;
      }
      if (!pLoader) {
            WARN(": invalid pLoader\n");
            return E_FAIL;
      }     
      
      IDirectMusicLoaderGenericStream_Detach (iface);
      IStream_Clone (pStream, &This->pStream);
      This->pLoader = pLoader;
      
    return S_OK;
}

void WINAPI IDirectMusicLoaderGenericStream_Detach (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
      
      if (This->pStream)
            IStream_Release (This->pStream);
      This->pStream = NULL;
}


/* IUnknown/IStream part: */
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
      
      TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
      if (IsEqualIID (riid, &IID_IUnknown) ||
            IsEqualIID (riid, &IID_IStream)) {
            *ppobj = (LPVOID)&This->StreamVtbl;
            IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
            return S_OK;
      } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
            *ppobj = (LPVOID)&This->GetLoaderVtbl;
            IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef ((LPDIRECTMUSICGETLOADER)&This->GetLoaderVtbl);            
            return S_OK;
      }

      WARN(": not found\n");
      return E_NOINTERFACE;
}

static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_AddRef (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
      TRACE("(%p): AddRef from %d\n", This, This->dwRef);
      return InterlockedIncrement (&This->dwRef);
}

static ULONG WINAPI IDirectMusicLoaderGenericStream_IStream_Release (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
      
      DWORD dwRef = InterlockedDecrement (&This->dwRef);
      TRACE("(%p): ReleaseRef to %d\n", This, dwRef);
      if (dwRef == 0) {
            IDirectMusicLoaderGenericStream_Detach (iface);
            HeapFree (GetProcessHeap(), 0, This);
      }
      
      return dwRef;
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);

      TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbRead);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Read (This->pStream, pv, cb, pcbRead);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE_(dmfileraw)("(%p, 0x%08llX, %s, %p): redirecting to low-level stream\n", This, dlibMove.QuadPart, resolve_STREAM_SEEK(dwOrigin), plibNewPosition);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Seek (This->pStream, dlibMove, dwOrigin, plibNewPosition);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Clone (LPSTREAM iface, IStream** ppstm) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);
      LPSTREAM pOther = NULL;
      LPSTREAM pLowLevel = NULL;
      HRESULT result;

      TRACE("(%p, %p)\n", iface, ppstm);
      result = DMUSIC_CreateDirectMusicLoaderGenericStream ((LPVOID*)&pOther);
      if (FAILED(result)) return result;
      
      if (FAILED(IStream_Clone (This->pStream, &pLowLevel)))
            return E_FAIL;
      
      IDirectMusicLoaderGenericStream_Attach (pOther, pLowLevel, This->pLoader);

      TRACE(": succeeded\n");
      *ppstm = (IStream*)pOther;
      return S_OK;
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE_(dmfileraw)("(%p, %p, 0x%08X, %p): redirecting to low-level stream\n", This, pv, cb, pcbWritten);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Write (This->pStream, pv, cb, pcbWritten);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, 0x%08llX): redirecting to low-level stream\n", This, libNewSize.QuadPart);
      if (!This->pStream)
            return E_FAIL;

      return IStream_SetSize (This->pStream, libNewSize);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, %p, 0x%08llX, %p, %p): redirecting to low-level stream\n", This, pstm, cb.QuadPart, pcbRead, pcbWritten);
      if (!This->pStream)
            return E_FAIL;

      return IStream_CopyTo (This->pStream, pstm, cb, pcbRead, pcbWritten);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, 0x%08X): redirecting to low-level stream\n", This, grfCommitFlags);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Commit (This->pStream, grfCommitFlags);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Revert (LPSTREAM iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p): redirecting to low-level stream\n", This);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Revert (This->pStream);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, 0x%08llX, 0x%08llX, 0x%08X): redirecting to low-level stream\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
      if (!This->pStream)
            return E_FAIL;

      return IStream_LockRegion (This->pStream, libOffset, cb, dwLockType);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, 0x%08llX, 0x%08llX, 0x%08X): redirecting to low-level stream\n", This, libOffset.QuadPart, cb.QuadPart, dwLockType);
      if (!This->pStream)
            return E_FAIL;

      return IStream_UnlockRegion (This->pStream, libOffset, cb, dwLockType);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);    
      TRACE("(%p, %p, 0x%08X): redirecting to low-level stream\n", This, pstatstg, grfStatFlag);
      if (!This->pStream)
            return E_FAIL;

      return IStream_Stat (This->pStream, pstatstg, grfStatFlag);
}

static const IStreamVtbl DirectMusicLoaderGenericStream_Stream_Vtbl = {
      IDirectMusicLoaderGenericStream_IStream_QueryInterface,
      IDirectMusicLoaderGenericStream_IStream_AddRef,
      IDirectMusicLoaderGenericStream_IStream_Release,
      IDirectMusicLoaderGenericStream_IStream_Read,
      IDirectMusicLoaderGenericStream_IStream_Write,
      IDirectMusicLoaderGenericStream_IStream_Seek,
      IDirectMusicLoaderGenericStream_IStream_SetSize,
      IDirectMusicLoaderGenericStream_IStream_CopyTo,
      IDirectMusicLoaderGenericStream_IStream_Commit,
      IDirectMusicLoaderGenericStream_IStream_Revert,
      IDirectMusicLoaderGenericStream_IStream_LockRegion,
      IDirectMusicLoaderGenericStream_IStream_UnlockRegion,
      IDirectMusicLoaderGenericStream_IStream_Stat,
      IDirectMusicLoaderGenericStream_IStream_Clone
};

/* IDirectMusicGetLoader part: */
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
}

static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderGenericStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
}

static ULONG WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);
      return IDirectMusicLoaderGenericStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
}

static HRESULT WINAPI IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader) {
      ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, GetLoaderVtbl, iface);

      TRACE("(%p, %p)\n", This, ppLoader);
      *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
      IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
      
      return S_OK;
}

static const IDirectMusicGetLoaderVtbl DirectMusicLoaderGenericStream_GetLoader_Vtbl = {
      IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_QueryInterface,
      IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_AddRef,
      IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_Release,
      IDirectMusicLoaderGenericStream_IDirectMusicGetLoader_GetLoader
};

HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderGenericStream (LPVOID* ppobj) {
      IDirectMusicLoaderGenericStream *obj;

      TRACE("(%p)\n", ppobj);
      obj = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicLoaderGenericStream));
      if (NULL == obj) {
            *ppobj = NULL;
            return E_OUTOFMEMORY;
      }
      obj->StreamVtbl = &DirectMusicLoaderGenericStream_Stream_Vtbl;
      obj->GetLoaderVtbl = &DirectMusicLoaderGenericStream_GetLoader_Vtbl;
      obj->dwRef = 0; /* will be inited with QueryInterface */

      return IDirectMusicLoaderGenericStream_IStream_QueryInterface ((LPSTREAM)&obj->StreamVtbl, &IID_IStream, ppobj);
}

Generated by  Doxygen 1.6.0   Back to index