reshuffling of dlls
[reactos.git] / reactos / dll / win32 / urlmon / umstream.c
1 /*
2 * Based on ../shell32/memorystream.c
3 *
4 * Copyright 1999 Juergen Schmied
5 * Copyright 2003 Mike McCormack for CodeWeavers
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <stdarg.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winternl.h"
30 #include "winuser.h"
31 #include "objbase.h"
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34 #include "ole2.h"
35 #include "urlmon.h"
36 #include "wininet.h"
37 #include "shlwapi.h"
38 #include "urlmon_main.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
41
42 static const IStreamVtbl stvt;
43
44 HRESULT UMCreateStreamOnCacheFile(LPCWSTR pszURL,
45 DWORD dwSize,
46 LPWSTR pszFileName,
47 HANDLE *phfile,
48 IUMCacheStream **ppstr)
49 {
50 IUMCacheStream* ucstr;
51 HANDLE handle;
52 LPWSTR ext;
53 LPCWSTR c;
54 LPCWSTR eloc = 0;
55 HRESULT hr;
56
57 for (c = pszURL; *c && *c != '#' && *c != '?'; ++c)
58 {
59 if (*c == '.')
60 eloc = c + 1;
61 else if (*c == '/' || *c == '\\')
62 eloc = 0;
63 }
64
65 if (!eloc)
66 eloc = c;
67
68 ext = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (c - eloc + 1));
69 memcpy(ext, eloc, sizeof(WCHAR) * (c - eloc));
70 ext[c - eloc] = 0;
71
72 if(!CreateUrlCacheEntryW(pszURL, dwSize, ext, pszFileName, 0))
73 hr = HRESULT_FROM_WIN32(GetLastError());
74 else
75 hr = 0;
76
77 HeapFree(GetProcessHeap(), 0, ext);
78
79 if (hr)
80 return hr;
81
82 TRACE("Opening %s\n", debugstr_w(pszFileName) );
83
84 handle = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL );
85 if( handle == INVALID_HANDLE_VALUE )
86 return HRESULT_FROM_WIN32(GetLastError());
87
88 if (phfile)
89 {
90 /* Call CreateFileW again because we need a handle with its own file pointer, and DuplicateHandle will return
91 * a handle that shares its file pointer with the original.
92 */
93 *phfile = CreateFileW( pszFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
94
95 if (*phfile == (HANDLE) HFILE_ERROR)
96 {
97 DWORD dwError = GetLastError();
98
99 CloseHandle(handle);
100 return HRESULT_FROM_WIN32(dwError);
101 }
102 }
103
104 ucstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(IUMCacheStream));
105 if(ucstr )
106 {
107 ucstr->pszURL = HeapAlloc(GetProcessHeap(),
108 HEAP_ZERO_MEMORY,
109 sizeof(WCHAR) * (lstrlenW(pszURL) + 1));
110 if (ucstr->pszURL)
111 {
112 ucstr->pszFileName = HeapAlloc(GetProcessHeap(),
113 HEAP_ZERO_MEMORY,
114 sizeof(WCHAR) * (lstrlenW(pszFileName) + 1));
115 if (ucstr->pszFileName)
116 {
117 ucstr->lpVtbl=&stvt;
118 ucstr->ref = 1;
119 ucstr->handle = handle;
120 ucstr->closed = 0;
121 lstrcpyW(ucstr->pszURL, pszURL);
122 lstrcpyW(ucstr->pszFileName, pszFileName);
123
124 *ppstr = ucstr;
125
126 return S_OK;
127 }
128 HeapFree(GetProcessHeap(), 0, ucstr->pszURL);
129 }
130 HeapFree(GetProcessHeap(), 0, ucstr);
131 }
132 CloseHandle(handle);
133 if (phfile)
134 CloseHandle(*phfile);
135 return E_OUTOFMEMORY;
136 }
137
138 void UMCloseCacheFileStream(IUMCacheStream *This)
139 {
140 if (!This->closed)
141 {
142 FILETIME ftZero;
143
144 ftZero.dwLowDateTime = ftZero.dwHighDateTime = 0;
145
146 This->closed = 1;
147 CommitUrlCacheEntryW(This->pszURL,
148 This->pszFileName,
149 ftZero,
150 ftZero,
151 NORMAL_CACHE_ENTRY,
152 0,
153 0,
154 0,
155 0);
156 }
157 }
158
159 /**************************************************************************
160 * IStream_fnQueryInterface
161 */
162 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface,
163 REFIID riid,
164 LPVOID *ppvObj)
165 {
166 IUMCacheStream *This = (IUMCacheStream *)iface;
167
168 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
169
170 *ppvObj = NULL;
171
172 if(IsEqualIID(riid, &IID_IUnknown) ||
173 IsEqualIID(riid, &IID_IStream))
174 {
175 *ppvObj = This;
176 }
177
178 if(*ppvObj)
179 {
180 IStream_AddRef((IStream*)*ppvObj);
181 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
182 return S_OK;
183 }
184 TRACE("-- Interface: E_NOINTERFACE\n");
185 return E_NOINTERFACE;
186 }
187
188 /**************************************************************************
189 * IStream_fnAddRef
190 */
191 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
192 {
193 IUMCacheStream *This = (IUMCacheStream *)iface;
194 ULONG refCount = InterlockedIncrement(&This->ref);
195
196 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
197
198 return refCount;
199 }
200
201 /**************************************************************************
202 * IStream_fnRelease
203 */
204 static ULONG WINAPI IStream_fnRelease(IStream *iface)
205 {
206 IUMCacheStream *This = (IUMCacheStream *)iface;
207 ULONG refCount = InterlockedDecrement(&This->ref);
208
209 TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
210
211 if (!refCount)
212 {
213 TRACE(" destroying UMCacheStream (%p)\n",This);
214 UMCloseCacheFileStream(This);
215 CloseHandle(This->handle);
216 HeapFree(GetProcessHeap(), 0, This->pszFileName);
217 HeapFree(GetProcessHeap(), 0, This->pszURL);
218 HeapFree(GetProcessHeap(),0,This);
219 }
220 return refCount;
221 }
222
223 static HRESULT WINAPI IStream_fnRead (IStream * iface,
224 void* pv,
225 ULONG cb,
226 ULONG* pcbRead)
227 {
228 ULONG dwBytesRead;
229 IUMCacheStream *This = (IUMCacheStream *)iface;
230
231 TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
232
233 if ( !pv )
234 return STG_E_INVALIDPOINTER;
235
236 if ( !pcbRead)
237 pcbRead = &dwBytesRead;
238
239 if ( ! ReadFile( This->handle, pv, cb, (LPDWORD)pcbRead, NULL ) )
240 return S_FALSE;
241
242 if (!*pcbRead)
243 return This->closed ? S_FALSE : E_PENDING;
244 return S_OK;
245 }
246
247 static HRESULT WINAPI IStream_fnWrite (IStream * iface,
248 const void* pv,
249 ULONG cb,
250 ULONG* pcbWritten)
251 {
252 return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI IStream_fnSeek ( IStream * iface,
256 LARGE_INTEGER dlibMove,
257 DWORD dwOrigin,
258 ULARGE_INTEGER* plibNewPosition)
259 {
260 DWORD pos, newposlo;
261 LONG newposhi;
262
263 IUMCacheStream *This = (IUMCacheStream *)iface;
264
265 TRACE("(%p)\n",This);
266
267 pos = dlibMove.QuadPart; /* FIXME: truncates */
268 newposhi = 0;
269 newposlo = SetFilePointer( This->handle, pos, &newposhi, dwOrigin );
270 if( newposlo == INVALID_SET_FILE_POINTER && GetLastError())
271 return E_FAIL;
272
273 if (plibNewPosition)
274 plibNewPosition->QuadPart = newposlo | ( (LONGLONG)newposhi<<32);
275
276 return S_OK;
277 }
278
279 static HRESULT WINAPI IStream_fnSetSize (IStream * iface,
280 ULARGE_INTEGER libNewSize)
281 {
282 IUMCacheStream *This = (IUMCacheStream *)iface;
283
284 TRACE("(%p)\n",This);
285
286 if( ! SetFilePointer( This->handle, libNewSize.QuadPart, NULL, FILE_BEGIN ) )
287 return E_FAIL;
288
289 if( ! SetEndOfFile( This->handle ) )
290 return E_FAIL;
291
292 return S_OK;
293 }
294
295 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface,
296 IStream* pstm,
297 ULARGE_INTEGER cb,
298 ULARGE_INTEGER* pcbRead,
299 ULARGE_INTEGER* pcbWritten)
300 {
301 IUMCacheStream *This = (IUMCacheStream *)iface;
302
303 TRACE("(%p)\n",This);
304
305 return E_NOTIMPL;
306 }
307
308 static HRESULT WINAPI IStream_fnCommit (IStream * iface,
309 DWORD grfCommitFlags)
310 {
311 IUMCacheStream *This = (IUMCacheStream *)iface;
312
313 TRACE("(%p)\n",This);
314
315 return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
319 {
320 IUMCacheStream *This = (IUMCacheStream *)iface;
321
322 TRACE("(%p)\n",This);
323
324 return E_NOTIMPL;
325 }
326 static HRESULT WINAPI IStream_fnLockRegion (IStream * iface,
327 ULARGE_INTEGER libOffset,
328 ULARGE_INTEGER cb,
329 DWORD dwLockType)
330 {
331 IUMCacheStream *This = (IUMCacheStream *)iface;
332
333 TRACE("(%p)\n",This);
334
335 return E_NOTIMPL;
336 }
337 static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface,
338 ULARGE_INTEGER libOffset,
339 ULARGE_INTEGER cb,
340 DWORD dwLockType)
341 {
342 IUMCacheStream *This = (IUMCacheStream *)iface;
343
344 TRACE("(%p)\n",This);
345
346 return E_NOTIMPL;
347 }
348 static HRESULT WINAPI IStream_fnStat (IStream * iface,
349 STATSTG* pstatstg,
350 DWORD grfStatFlag)
351 {
352 IUMCacheStream *This = (IUMCacheStream *)iface;
353
354 TRACE("(%p)\n",This);
355
356 return E_NOTIMPL;
357 }
358 static HRESULT WINAPI IStream_fnClone (IStream * iface,
359 IStream** ppstm)
360 {
361 IUMCacheStream *This = (IUMCacheStream *)iface;
362
363 TRACE("(%p)\n",This);
364
365 return E_NOTIMPL;
366 }
367
368 static const IStreamVtbl stvt =
369 {
370 IStream_fnQueryInterface,
371 IStream_fnAddRef,
372 IStream_fnRelease,
373 IStream_fnRead,
374 IStream_fnWrite,
375 IStream_fnSeek,
376 IStream_fnSetSize,
377 IStream_fnCopyTo,
378 IStream_fnCommit,
379 IStream_fnRevert,
380 IStream_fnLockRegion,
381 IStream_fnUnlockRegion,
382 IStream_fnStat,
383 IStream_fnClone
384
385 };