Corel merge:
[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
12 #include <string.h>
13
14 #include "wine/obj_storage.h"
15 #include "heap.h"
16 #include "winerror.h"
17 #include "debugtools.h"
18 #include "shell32_main.h"
19
20 DEFAULT_DEBUG_CHANNEL(shell)
21
22 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj);
23 static ULONG WINAPI IStream_fnAddRef(IStream *iface);
24 static ULONG WINAPI IStream_fnRelease(IStream *iface);
25 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead);
26 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten);
27 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition);
28 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize);
29 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten);
30 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags);
31 static HRESULT WINAPI IStream_fnRevert (IStream * iface);
32 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
33 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
34 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag);
35 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm);
36
37 static ICOM_VTABLE(IStream) stvt = 
38 {       
39         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
40         IStream_fnQueryInterface,
41         IStream_fnAddRef,
42         IStream_fnRelease,
43         IStream_fnRead,
44         IStream_fnWrite,
45         IStream_fnSeek,
46         IStream_fnSetSize,
47         IStream_fnCopyTo,
48         IStream_fnCommit,
49         IStream_fnRevert,
50         IStream_fnLockRegion,
51         IStream_fnUnlockRegion,
52         IStream_fnStat,
53         IStream_fnClone
54         
55 };
56
57 typedef struct 
58 {       ICOM_VTABLE(IStream)    *lpvtst;
59         DWORD           ref;
60         LPBYTE          pImage;
61         HANDLE          hMapping;
62         DWORD           dwLength;
63         DWORD           dwPos;
64 } ISHFileStream;
65
66 /**************************************************************************
67  *   CreateStreamOnFile()
68  *
69  *   similar to CreateStreamOnHGlobal
70  */
71 HRESULT CreateStreamOnFile (LPCSTR pszFilename, IStream ** ppstm)
72 {
73         ISHFileStream*  fstr;
74         OFSTRUCT        ofs;
75         HFILE           hFile = OpenFile( pszFilename, &ofs, OF_READ );
76         HRESULT         ret = E_FAIL;
77         
78         fstr = (ISHFileStream*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ISHFileStream));
79         fstr->lpvtst=&stvt;
80         fstr->ref = 1;
81         fstr->dwLength = GetFileSize (hFile, NULL);
82
83         shell32_ObjCount++;
84
85         if (!(fstr->hMapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL)))
86         {
87           WARN("failed to create filemap.\n");
88           goto end_2;
89         }
90
91         if (!(fstr->pImage = MapViewOfFile(fstr->hMapping,FILE_MAP_READ,0,0,0)))
92         {
93           WARN("failed to mmap filemap.\n");
94           goto end_3;
95         }
96
97         ret = S_OK;
98         goto end_1;
99         
100 end_3:  CloseHandle(fstr->hMapping);
101 end_2:  HeapFree(GetProcessHeap(), 0, fstr);
102         fstr = NULL;
103
104 end_1:  _lclose(hFile);
105         (*ppstm) = (IStream*)fstr;
106         return ret;
107 }
108
109 /**************************************************************************
110 *  IStream_fnQueryInterface
111 */
112 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
113 {
114         ICOM_THIS(ISHFileStream, iface);
115
116         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
117
118         *ppvObj = NULL;
119
120         if(IsEqualIID(riid, &IID_IUnknown) ||
121            IsEqualIID(riid, &IID_IStream))
122         {
123           *ppvObj = This;
124         }
125
126         if(*ppvObj)
127         { 
128           IStream_AddRef((IStream*)*ppvObj);      
129           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
130           return S_OK;
131         }
132         TRACE("-- Interface: E_NOINTERFACE\n");
133         return E_NOINTERFACE;
134 }
135
136 /**************************************************************************
137 *  IStream_fnAddRef
138 */
139 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
140 {
141         ICOM_THIS(ISHFileStream, iface);
142
143         TRACE("(%p)->(count=%lu)\n",This, This->ref);
144
145         shell32_ObjCount++;
146         return ++(This->ref);
147 }
148
149 /**************************************************************************
150 *  IStream_fnRelease
151 */
152 static ULONG WINAPI IStream_fnRelease(IStream *iface)
153 {
154         ICOM_THIS(ISHFileStream, iface);
155
156         TRACE("(%p)->()\n",This);
157
158         shell32_ObjCount--;
159
160         if (!--(This->ref)) 
161         { TRACE(" destroying SHFileStream (%p)\n",This);
162
163           UnmapViewOfFile(This->pImage);
164           CloseHandle(This->hMapping);
165
166           HeapFree(GetProcessHeap(),0,This);
167           return 0;
168         }
169         return This->ref;
170 }
171
172 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
173 {
174         ICOM_THIS(ISHFileStream, iface);
175
176         DWORD dwBytesToRead, dwBytesLeft;
177         
178         TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
179         
180         if ( !pv )
181           return STG_E_INVALIDPOINTER;
182
183         dwBytesLeft = This->dwLength - This->dwPos;
184
185         if ( 0 >= dwBytesLeft )                                         /* end of buffer */
186           return S_FALSE;
187         
188         dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;
189
190         memmove ( pv, (This->pImage) + (This->dwPos), dwBytesToRead);
191         
192         This->dwPos += dwBytesToRead;                                   /* adjust pointer */
193
194         if (pcbRead)
195           *pcbRead = dwBytesToRead;
196
197         return S_OK;
198 }
199 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
200 {
201         ICOM_THIS(ISHFileStream, iface);
202
203         TRACE("(%p)\n",This);
204
205         return E_NOTIMPL;
206 }
207 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
208 {
209         ICOM_THIS(ISHFileStream, iface);
210
211         TRACE("(%p)\n",This);
212
213         return E_NOTIMPL;
214 }
215 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
216 {
217         ICOM_THIS(ISHFileStream, iface);
218
219         TRACE("(%p)\n",This);
220
221         return E_NOTIMPL;
222 }
223 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
224 {
225         ICOM_THIS(ISHFileStream, iface);
226
227         TRACE("(%p)\n",This);
228
229         return E_NOTIMPL;
230 }
231 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
232 {
233         ICOM_THIS(ISHFileStream, iface);
234
235         TRACE("(%p)\n",This);
236
237         return E_NOTIMPL;
238 }
239 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
240 {
241         ICOM_THIS(ISHFileStream, iface);
242
243         TRACE("(%p)\n",This);
244
245         return E_NOTIMPL;
246 }
247 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
248 {
249         ICOM_THIS(ISHFileStream, iface);
250
251         TRACE("(%p)\n",This);
252
253         return E_NOTIMPL;
254 }
255 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
256 {
257         ICOM_THIS(ISHFileStream, iface);
258
259         TRACE("(%p)\n",This);
260
261         return E_NOTIMPL;
262 }
263 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag)
264 {
265         ICOM_THIS(ISHFileStream, iface);
266
267         TRACE("(%p)\n",This);
268
269         return E_NOTIMPL;
270 }
271 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
272 {
273         ICOM_THIS(ISHFileStream, iface);
274
275         TRACE("(%p)\n",This);
276
277         return E_NOTIMPL;
278 }