Fix incorrect calculation of transport_addr.
[wine] / dlls / dmloader / loaderstream.c
1 /* ILoaderStream Implementation
2  *
3  * Copyright (C) 2003 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "wingdi.h"
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
30
31 #include "dmloader_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(dmloader);
34
35 /*****************************************************************************
36  * Custom functions:
37  */
38 HRESULT WINAPI ILoaderStream_Attach (ILoaderStream* This, LPCWSTR wzFile, IDirectMusicLoader *pLoader)
39 {
40     TRACE("(%p, %s, %p)\n", This, debugstr_w(wzFile), pLoader);
41     ILoaderStream_Detach (This);
42     This->hFile = CreateFileW (wzFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
43     if (This->hFile == INVALID_HANDLE_VALUE) {
44         TRACE(": failed\n");
45         return E_FAIL;
46     }
47     /* create IDirectMusicGetLoader */
48     (LPDIRECTMUSICLOADER) This->pLoader = pLoader;
49     strncpyW (This->wzFileName, wzFile, MAX_PATH);
50     TRACE(": succeeded\n");
51     return S_OK;
52 }
53
54 void WINAPI ILoaderStream_Detach (ILoaderStream* This)
55 {
56         if (This->hFile != INVALID_HANDLE_VALUE) {
57         CloseHandle(This->hFile);
58     }
59     This->wzFileName[0] = (L'\0');
60 }
61
62 /*****************************************************************************
63  * ILoaderStream IStream:
64  */
65 HRESULT WINAPI ILoaderStream_IStream_QueryInterface (LPSTREAM iface, REFIID riid, void** ppobj)
66 {
67         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
68         
69         if (IsEqualIID (riid, &IID_IUnknown)
70                 || IsEqualIID (riid, &IID_IStream)) {
71                 *ppobj = (LPVOID)&This->StreamVtbl;
72                 ILoaderStream_IStream_AddRef (iface);
73                 return S_OK;
74         } else if (IsEqualIID (riid, &IID_IDirectMusicGetLoader)) {
75                 *ppobj = (LPVOID)&This->GetLoaderVtbl;
76                 ILoaderStream_IStream_AddRef (iface);           
77                 return S_OK;
78         }
79
80         WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
81         return E_NOINTERFACE;
82 }
83
84 ULONG WINAPI ILoaderStream_IStream_AddRef (LPSTREAM iface)
85 {
86         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
87         TRACE("(%p) : AddRef from %ld\n", This, This->ref);
88         return ++(This->ref);
89 }
90
91 ULONG WINAPI ILoaderStream_IStream_Release (LPSTREAM iface)
92 {
93         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
94         ULONG ref = --This->ref;
95         TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
96         if (ref == 0) {
97                 HeapFree(GetProcessHeap(), 0, This);
98         }
99         return ref;
100 }
101
102 HRESULT WINAPI ILoaderStream_IStream_Read (LPSTREAM iface, void* pv, ULONG cb, ULONG* pcbRead)
103 {
104         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
105     ULONG cbRead;
106
107     if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
108     if (pcbRead == NULL) pcbRead = &cbRead;
109     if (!ReadFile (This->hFile, pv, cb, pcbRead, NULL) || *pcbRead != cb) return E_FAIL;
110
111     return S_OK;
112 }
113
114 HRESULT WINAPI ILoaderStream_IStream_Seek (LPSTREAM iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
115 {
116         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
117     LARGE_INTEGER liNewPos;
118
119         if (This->hFile == INVALID_HANDLE_VALUE) return E_FAIL;
120
121     liNewPos.s.HighPart = dlibMove.s.HighPart;
122     liNewPos.s.LowPart = SetFilePointer (This->hFile, dlibMove.s.LowPart, &liNewPos.s.HighPart, dwOrigin);
123
124     if (liNewPos.s.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) return E_FAIL;
125     if (plibNewPosition) plibNewPosition->QuadPart = liNewPos.QuadPart;
126     
127     return S_OK;
128 }
129
130 HRESULT WINAPI ILoaderStream_IStream_Clone (LPSTREAM iface, IStream** ppstm)
131 {
132         ICOM_THIS_MULTI(ILoaderStream, StreamVtbl, iface);
133         ILoaderStream* pOther = NULL;
134         HRESULT result;
135
136         TRACE("(%p, %p)\n", iface, ppstm);
137         result = DMUSIC_CreateLoaderStream ((LPSTREAM*)&pOther);
138         if (FAILED(result)) return result;
139         if (This->hFile != INVALID_HANDLE_VALUE) {
140                 ULARGE_INTEGER ullCurrentPosition;
141                 result = ILoaderStream_Attach (pOther, This->wzFileName, (LPDIRECTMUSICLOADER)This->pLoader);
142                 if (SUCCEEDED(result)) {
143                         LARGE_INTEGER liZero;
144                         liZero.QuadPart = 0;
145                         result = ILoaderStream_IStream_Seek (iface, liZero, STREAM_SEEK_CUR, &ullCurrentPosition); /* get current position in current stream */
146         }
147                 if (SUCCEEDED(result)) {
148                         LARGE_INTEGER liNewPosition;
149                         liNewPosition.QuadPart = ullCurrentPosition.QuadPart;
150                         result = ILoaderStream_IStream_Seek ((LPSTREAM)pOther, liNewPosition, STREAM_SEEK_SET, &ullCurrentPosition);
151                 }
152                 if (FAILED(result)) {
153                         TRACE(": failed\n");
154                         ILoaderStream_IStream_Release ((LPSTREAM)pOther);
155                         return result;
156                 }
157         }
158         TRACE(": succeeded\n");
159         *ppstm = (IStream*)pOther;
160         return S_OK;
161 }
162
163 /* not needed*/
164 HRESULT WINAPI ILoaderStream_IStream_Write (LPSTREAM iface, const void* pv, ULONG cb, ULONG* pcbWritten)
165 {
166         ERR(": should not be needed\n");
167         return E_NOTIMPL;
168 }
169
170 HRESULT WINAPI ILoaderStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize)
171 {
172         ERR(": should not be needed\n");
173     return E_NOTIMPL;
174 }
175
176 HRESULT WINAPI ILoaderStream_IStream_CopyTo (LPSTREAM iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
177 {
178         ERR(": should not be needed\n");
179     return E_NOTIMPL;
180 }
181
182 HRESULT WINAPI ILoaderStream_IStream_Commit (LPSTREAM iface, DWORD grfCommitFlags)
183 {
184         ERR(": should not be needed\n");
185     return E_NOTIMPL;
186 }
187
188 HRESULT WINAPI ILoaderStream_IStream_Revert (LPSTREAM iface)
189 {
190         ERR(": should not be needed\n");
191     return E_NOTIMPL;
192 }
193
194 HRESULT WINAPI ILoaderStream_IStream_LockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
195 {
196         ERR(": should not be needed\n");
197     return E_NOTIMPL;
198 }
199
200 HRESULT WINAPI ILoaderStream_IStream_UnlockRegion (LPSTREAM iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
201 {
202         ERR(": should not be needed\n");
203     return E_NOTIMPL;
204 }
205
206 HRESULT WINAPI ILoaderStream_IStream_Stat (LPSTREAM iface, STATSTG* pstatstg, DWORD grfStatFlag)
207 {
208         ERR(": should not be needed\n");
209     return E_NOTIMPL;
210 }
211
212 ICOM_VTABLE(IStream) LoaderStream_Stream_Vtbl =
213 {
214     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
215         ILoaderStream_IStream_QueryInterface,
216         ILoaderStream_IStream_AddRef,
217         ILoaderStream_IStream_Release,
218         ILoaderStream_IStream_Read,
219         ILoaderStream_IStream_Write,
220         ILoaderStream_IStream_Seek,
221         ILoaderStream_IStream_SetSize,
222         ILoaderStream_IStream_CopyTo,
223         ILoaderStream_IStream_Commit,
224         ILoaderStream_IStream_Revert,
225         ILoaderStream_IStream_LockRegion,
226         ILoaderStream_IStream_UnlockRegion,
227         ILoaderStream_IStream_Stat,
228         ILoaderStream_IStream_Clone
229 };
230
231 /*****************************************************************************
232  * ILoaderStream IDirectMusicGetLoader:
233  */
234 HRESULT WINAPI ILoaderStream_IDirectMusicGetLoader_QueryInterface (LPDIRECTMUSICGETLOADER iface, REFIID riid, void** ppobj)
235 {
236         ICOM_THIS_MULTI(ILoaderStream, GetLoaderVtbl, iface);
237         return ILoaderStream_IStream_QueryInterface ((LPSTREAM)&This->StreamVtbl, riid, ppobj);
238 }
239
240 ULONG WINAPI ILoaderStream_IDirectMusicGetLoader_AddRef (LPDIRECTMUSICGETLOADER iface)
241 {
242         ICOM_THIS_MULTI(ILoaderStream, GetLoaderVtbl, iface);
243         return ILoaderStream_IStream_AddRef ((LPSTREAM)&This->StreamVtbl);
244 }
245
246 ULONG WINAPI ILoaderStream_IDirectMusicGetLoader_Release (LPDIRECTMUSICGETLOADER iface)
247 {
248         ICOM_THIS_MULTI(ILoaderStream, GetLoaderVtbl, iface);
249         return ILoaderStream_IStream_Release ((LPSTREAM)&This->StreamVtbl);
250 }
251
252 HRESULT WINAPI ILoaderStream_IDirectMusicGetLoader_GetLoader (LPDIRECTMUSICGETLOADER iface, IDirectMusicLoader **ppLoader)
253 {
254         ICOM_THIS_MULTI(ILoaderStream, GetLoaderVtbl, iface);
255
256         TRACE("(%p, %p)\n", This, ppLoader);
257         *ppLoader = (LPDIRECTMUSICLOADER)This->pLoader;
258         IDirectMusicLoader8_AddRef ((LPDIRECTMUSICLOADER8)*ppLoader);
259         
260         return S_OK;
261 }
262
263 ICOM_VTABLE(IDirectMusicGetLoader) LoaderStream_GetLoader_Vtbl =
264 {
265     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
266         ILoaderStream_IDirectMusicGetLoader_QueryInterface,
267         ILoaderStream_IDirectMusicGetLoader_AddRef,
268         ILoaderStream_IDirectMusicGetLoader_Release,
269         ILoaderStream_IDirectMusicGetLoader_GetLoader
270 };
271
272
273 HRESULT WINAPI DMUSIC_CreateLoaderStream (LPSTREAM* ppStream)
274 {
275         ILoaderStream *pStream;
276
277         TRACE("(%p)\n", ppStream);
278
279         pStream = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(ILoaderStream));
280         if (NULL == pStream) {
281                 *ppStream = (LPSTREAM)NULL;
282                 return E_OUTOFMEMORY;
283         }
284         pStream->StreamVtbl = &LoaderStream_Stream_Vtbl;
285         pStream->GetLoaderVtbl = &LoaderStream_GetLoader_Vtbl;
286         pStream->ref = 1;
287         
288         *ppStream = (LPSTREAM)pStream;
289         return S_OK;
290 }