Added some more tests.
[wine] / dlls / shell32 / memorystream.c
1 /*
2  *      this class implements a pure IStream object
3  *      and can be used for many purposes
4  *
5  *      the main reason for implementing this was
6  *      a cleaner implementation of IShellLink which
7  *      needs to be able to load lnk's from a IStream
8  *      interface so it was obvious to capsule the file
9  *      access in a IStream to.
10  *
11  * Copyright 1999 Juergen Schmied
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #include <string.h>
29
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "shlobj.h"
33 #include "wine/debug.h"
34 #include "shell32_main.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37
38 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj);
39 static ULONG WINAPI IStream_fnAddRef(IStream *iface);
40 static ULONG WINAPI IStream_fnRelease(IStream *iface);
41 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead);
42 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten);
43 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition);
44 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize);
45 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten);
46 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags);
47 static HRESULT WINAPI IStream_fnRevert (IStream * iface);
48 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
49 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
50 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag);
51 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm);
52
53 static ICOM_VTABLE(IStream) stvt = 
54 {       
55         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
56         IStream_fnQueryInterface,
57         IStream_fnAddRef,
58         IStream_fnRelease,
59         IStream_fnRead,
60         IStream_fnWrite,
61         IStream_fnSeek,
62         IStream_fnSetSize,
63         IStream_fnCopyTo,
64         IStream_fnCommit,
65         IStream_fnRevert,
66         IStream_fnLockRegion,
67         IStream_fnUnlockRegion,
68         IStream_fnStat,
69         IStream_fnClone
70         
71 };
72
73 typedef struct 
74 {       ICOM_VTABLE(IStream)    *lpvtst;
75         DWORD           ref;
76         LPBYTE          pImage;
77         HANDLE          hMapping;
78         DWORD           dwLength;
79         DWORD           dwPos;
80 } ISHFileStream;
81
82 /**************************************************************************
83  *   CreateStreamOnFile()
84  *
85  *   similar to CreateStreamOnHGlobal
86  */
87 HRESULT CreateStreamOnFile (LPCSTR pszFilename, IStream ** ppstm)
88 {
89         ISHFileStream*  fstr;
90         OFSTRUCT        ofs;
91         HFILE           hFile = OpenFile( pszFilename, &ofs, OF_READ );
92         HRESULT         ret = E_FAIL;
93         
94         fstr = (ISHFileStream*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ISHFileStream));
95         fstr->lpvtst=&stvt;
96         fstr->ref = 1;
97         fstr->dwLength = GetFileSize (hFile, NULL);
98
99         shell32_ObjCount++;
100
101         if (!(fstr->hMapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL)))
102         {
103           WARN("failed to create filemap.\n");
104           goto end_2;
105         }
106
107         if (!(fstr->pImage = MapViewOfFile(fstr->hMapping,FILE_MAP_READ,0,0,0)))
108         {
109           WARN("failed to mmap filemap.\n");
110           goto end_3;
111         }
112
113         ret = S_OK;
114         goto end_1;
115         
116 end_3:  CloseHandle(fstr->hMapping);
117 end_2:  HeapFree(GetProcessHeap(), 0, fstr);
118         fstr = NULL;
119
120 end_1:  _lclose(hFile);
121         (*ppstm) = (IStream*)fstr;
122         return ret;
123 }
124
125 /**************************************************************************
126 *  IStream_fnQueryInterface
127 */
128 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
129 {
130         ICOM_THIS(ISHFileStream, iface);
131
132         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
133
134         *ppvObj = NULL;
135
136         if(IsEqualIID(riid, &IID_IUnknown) ||
137            IsEqualIID(riid, &IID_IStream))
138         {
139           *ppvObj = This;
140         }
141
142         if(*ppvObj)
143         { 
144           IStream_AddRef((IStream*)*ppvObj);      
145           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
146           return S_OK;
147         }
148         TRACE("-- Interface: E_NOINTERFACE\n");
149         return E_NOINTERFACE;
150 }
151
152 /**************************************************************************
153 *  IStream_fnAddRef
154 */
155 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
156 {
157         ICOM_THIS(ISHFileStream, iface);
158
159         TRACE("(%p)->(count=%lu)\n",This, This->ref);
160
161         shell32_ObjCount++;
162         return ++(This->ref);
163 }
164
165 /**************************************************************************
166 *  IStream_fnRelease
167 */
168 static ULONG WINAPI IStream_fnRelease(IStream *iface)
169 {
170         ICOM_THIS(ISHFileStream, iface);
171
172         TRACE("(%p)->()\n",This);
173
174         shell32_ObjCount--;
175
176         if (!--(This->ref)) 
177         { TRACE(" destroying SHFileStream (%p)\n",This);
178
179           UnmapViewOfFile(This->pImage);
180           CloseHandle(This->hMapping);
181
182           HeapFree(GetProcessHeap(),0,This);
183           return 0;
184         }
185         return This->ref;
186 }
187
188 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
189 {
190         ICOM_THIS(ISHFileStream, iface);
191
192         DWORD dwBytesToRead, dwBytesLeft;
193         
194         TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
195         
196         if ( !pv )
197           return STG_E_INVALIDPOINTER;
198
199         dwBytesLeft = This->dwLength - This->dwPos;
200
201         if ( 0 >= dwBytesLeft )                                         /* end of buffer */
202           return S_FALSE;
203         
204         dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;
205
206         memmove ( pv, (This->pImage) + (This->dwPos), dwBytesToRead);
207         
208         This->dwPos += dwBytesToRead;                                   /* adjust pointer */
209
210         if (pcbRead)
211           *pcbRead = dwBytesToRead;
212
213         return S_OK;
214 }
215 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
216 {
217         ICOM_THIS(ISHFileStream, iface);
218
219         TRACE("(%p)\n",This);
220
221         return E_NOTIMPL;
222 }
223 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
224 {
225         ICOM_THIS(ISHFileStream, iface);
226
227         TRACE("(%p)\n",This);
228
229         return E_NOTIMPL;
230 }
231 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
232 {
233         ICOM_THIS(ISHFileStream, iface);
234
235         TRACE("(%p)\n",This);
236
237         return E_NOTIMPL;
238 }
239 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
240 {
241         ICOM_THIS(ISHFileStream, iface);
242
243         TRACE("(%p)\n",This);
244
245         return E_NOTIMPL;
246 }
247 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
248 {
249         ICOM_THIS(ISHFileStream, iface);
250
251         TRACE("(%p)\n",This);
252
253         return E_NOTIMPL;
254 }
255 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
256 {
257         ICOM_THIS(ISHFileStream, iface);
258
259         TRACE("(%p)\n",This);
260
261         return E_NOTIMPL;
262 }
263 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
264 {
265         ICOM_THIS(ISHFileStream, iface);
266
267         TRACE("(%p)\n",This);
268
269         return E_NOTIMPL;
270 }
271 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
272 {
273         ICOM_THIS(ISHFileStream, iface);
274
275         TRACE("(%p)\n",This);
276
277         return E_NOTIMPL;
278 }
279 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag)
280 {
281         ICOM_THIS(ISHFileStream, iface);
282
283         TRACE("(%p)\n",This);
284
285         return E_NOTIMPL;
286 }
287 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
288 {
289         ICOM_THIS(ISHFileStream, iface);
290
291         TRACE("(%p)\n",This);
292
293         return E_NOTIMPL;
294 }