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