winedbg: Don't dereference possibly NULL thread pointer.
[wine/zf.git] / dlls / shlwapi / regstream.c
blobdecc1f666db011739f8100ee709b4c8f8f0c193e
1 /*
2 * SHLWAPI Registry Stream functions
4 * Copyright 1999 Juergen Schmied
5 * Copyright 2002 Jon Griffiths
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(shell);
38 typedef struct
40 IStream IStream_iface;
41 LONG ref;
42 LPBYTE pbBuffer;
43 DWORD dwLength;
44 DWORD dwPos;
45 DWORD dwMode;
46 } ISHRegStream;
48 static inline ISHRegStream *impl_from_IStream(IStream *iface)
50 return CONTAINING_RECORD(iface, ISHRegStream, IStream_iface);
53 /**************************************************************************
54 * IStream_fnQueryInterface
56 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
58 ISHRegStream *This = impl_from_IStream(iface);
60 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
62 *ppvObj = NULL;
64 if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IStream))
65 *ppvObj = &This->IStream_iface;
67 if(*ppvObj)
69 IStream_AddRef((IStream*)*ppvObj);
70 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
71 return S_OK;
73 TRACE("-- Interface: E_NOINTERFACE\n");
74 return E_NOINTERFACE;
77 /**************************************************************************
78 * IStream_fnAddRef
80 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
82 ISHRegStream *This = impl_from_IStream(iface);
83 ULONG refCount = InterlockedIncrement(&This->ref);
85 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
87 return refCount;
90 /**************************************************************************
91 * IStream_fnRelease
93 static ULONG WINAPI IStream_fnRelease(IStream *iface)
95 ISHRegStream *This = impl_from_IStream(iface);
96 ULONG refCount = InterlockedDecrement(&This->ref);
98 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
100 if (!refCount)
102 HeapFree(GetProcessHeap(),0,This->pbBuffer);
103 HeapFree(GetProcessHeap(),0,This);
104 return 0;
107 return refCount;
110 /**************************************************************************
111 * IStream_fnRead
113 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
115 ISHRegStream *This = impl_from_IStream(iface);
116 DWORD dwBytesToRead;
118 TRACE("(%p)->(%p,0x%08x,%p)\n",This, pv, cb, pcbRead);
120 if (This->dwPos >= This->dwLength)
121 dwBytesToRead = 0;
122 else
123 dwBytesToRead = This->dwLength - This->dwPos;
125 dwBytesToRead = (cb > dwBytesToRead) ? dwBytesToRead : cb;
126 if (dwBytesToRead != 0) /* not at end of buffer and we want to read something */
128 memmove(pv, This->pbBuffer + This->dwPos, dwBytesToRead);
129 This->dwPos += dwBytesToRead; /* adjust pointer */
132 if (pcbRead)
133 *pcbRead = dwBytesToRead;
135 return S_OK;
138 /**************************************************************************
139 * IStream_fnWrite
141 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
143 ISHRegStream *This = impl_from_IStream(iface);
144 DWORD newLen = This->dwPos + cb;
146 TRACE("(%p, %p, %d, %p)\n",This, pv, cb, pcbWritten);
148 if (newLen < This->dwPos) /* overflow */
149 return STG_E_INSUFFICIENTMEMORY;
151 if (newLen > This->dwLength)
153 LPBYTE newBuf = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pbBuffer, newLen);
154 if (!newBuf)
155 return STG_E_INSUFFICIENTMEMORY;
157 This->dwLength = newLen;
158 This->pbBuffer = newBuf;
160 memmove(This->pbBuffer + This->dwPos, pv, cb);
161 This->dwPos += cb; /* adjust pointer */
163 if (pcbWritten)
164 *pcbWritten = cb;
166 return S_OK;
169 /**************************************************************************
170 * IStream_fnSeek
172 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
174 ISHRegStream *This = impl_from_IStream(iface);
175 LARGE_INTEGER tmp;
176 TRACE("(%p, %s, %d %p)\n", This,
177 wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, plibNewPosition);
179 if (dwOrigin == STREAM_SEEK_SET)
180 tmp = dlibMove;
181 else if (dwOrigin == STREAM_SEEK_CUR)
182 tmp.QuadPart = This->dwPos + dlibMove.QuadPart;
183 else if (dwOrigin == STREAM_SEEK_END)
184 tmp.QuadPart = This->dwLength + dlibMove.QuadPart;
185 else
186 return STG_E_INVALIDPARAMETER;
188 if (tmp.QuadPart < 0)
189 return STG_E_INVALIDFUNCTION;
191 /* we cut off the high part here */
192 This->dwPos = tmp.u.LowPart;
194 if (plibNewPosition)
195 plibNewPosition->QuadPart = This->dwPos;
196 return S_OK;
199 /**************************************************************************
200 * IStream_fnSetSize
202 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
204 ISHRegStream *This = impl_from_IStream(iface);
205 DWORD newLen;
206 LPBYTE newBuf;
208 TRACE("(%p, %s)\n", This, wine_dbgstr_longlong(libNewSize.QuadPart));
210 /* we cut off the high part here */
211 newLen = libNewSize.u.LowPart;
212 newBuf = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pbBuffer, newLen);
213 if (!newBuf)
214 return STG_E_INSUFFICIENTMEMORY;
216 This->pbBuffer = newBuf;
217 This->dwLength = newLen;
219 return S_OK;
222 /**************************************************************************
223 * IStream_fnCopyTo
225 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
227 ISHRegStream *This = impl_from_IStream(iface);
229 TRACE("(%p)\n",This);
230 if (pcbRead)
231 pcbRead->QuadPart = 0;
232 if (pcbWritten)
233 pcbWritten->QuadPart = 0;
235 /* TODO implement */
236 return E_NOTIMPL;
239 /**************************************************************************
240 * IStream_fnCommit
242 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
244 ISHRegStream *This = impl_from_IStream(iface);
246 TRACE("(%p)\n",This);
248 /* commit not supported by this stream */
249 return E_NOTIMPL;
252 /**************************************************************************
253 * IStream_fnRevert
255 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
257 ISHRegStream *This = impl_from_IStream(iface);
259 TRACE("(%p)\n",This);
261 /* revert not supported by this stream */
262 return E_NOTIMPL;
265 /**************************************************************************
266 * IStream_fnLockUnlockRegion
268 static HRESULT WINAPI IStream_fnLockUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
270 ISHRegStream *This = impl_from_IStream(iface);
272 TRACE("(%p)\n",This);
274 /* lock/unlock not supported by this stream */
275 return E_NOTIMPL;
278 /*************************************************************************
279 * IStream_fnStat
281 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag)
283 ISHRegStream *This = impl_from_IStream(iface);
285 TRACE("(%p, %p, %d)\n",This,pstatstg,grfStatFlag);
287 pstatstg->pwcsName = NULL;
288 pstatstg->type = STGTY_STREAM;
289 pstatstg->cbSize.QuadPart = This->dwLength;
290 pstatstg->mtime.dwHighDateTime = 0;
291 pstatstg->mtime.dwLowDateTime = 0;
292 pstatstg->ctime.dwHighDateTime = 0;
293 pstatstg->ctime.dwLowDateTime = 0;
294 pstatstg->atime.dwHighDateTime = 0;
295 pstatstg->atime.dwLowDateTime = 0;
296 pstatstg->grfMode = This->dwMode;
297 pstatstg->grfLocksSupported = 0;
298 pstatstg->clsid = CLSID_NULL;
299 pstatstg->grfStateBits = 0;
300 pstatstg->reserved = 0;
302 return S_OK;
305 /*************************************************************************
306 * IStream_fnClone
308 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
310 ISHRegStream *This = impl_from_IStream(iface);
312 TRACE("(%p)\n",This);
313 *ppstm = NULL;
315 /* clone not supported by this stream */
316 return E_NOTIMPL;
319 static const IStreamVtbl rstvt =
321 IStream_fnQueryInterface,
322 IStream_fnAddRef,
323 IStream_fnRelease,
324 IStream_fnRead,
325 IStream_fnWrite,
326 IStream_fnSeek,
327 IStream_fnSetSize,
328 IStream_fnCopyTo,
329 IStream_fnCommit,
330 IStream_fnRevert,
331 IStream_fnLockUnlockRegion,
332 IStream_fnLockUnlockRegion,
333 IStream_fnStat,
334 IStream_fnClone
337 /**************************************************************************
338 * IStream_Create
340 * Internal helper: Create and initialise a new registry stream object.
342 static ISHRegStream *IStream_Create(HKEY hKey, LPBYTE pbBuffer, DWORD dwLength)
344 ISHRegStream* regStream;
346 regStream = HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream));
348 if (regStream)
350 regStream->IStream_iface.lpVtbl = &rstvt;
351 regStream->ref = 1;
352 regStream->pbBuffer = pbBuffer;
353 regStream->dwLength = dwLength;
354 regStream->dwPos = 0;
355 regStream->dwMode = STGM_READWRITE;
357 TRACE ("Returning %p\n", regStream);
358 return regStream;
361 /*************************************************************************
362 * SHCreateStreamWrapper [SHLWAPI.@]
364 * Create an IStream object on a block of memory.
366 * PARAMS
367 * lpbData [I] Memory block to create the IStream object on
368 * dwDataLen [I] Length of data block
369 * dwReserved [I] Reserved, Must be 0.
370 * lppStream [O] Destination for IStream object
372 * RETURNS
373 * Success: S_OK. lppStream contains the new IStream object.
374 * Failure: E_INVALIDARG, if any parameters are invalid,
375 * E_OUTOFMEMORY if memory allocation fails.
377 * NOTES
378 * The stream assumes ownership of the memory passed to it.
380 HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,
381 DWORD dwReserved, IStream **lppStream)
383 ISHRegStream *strm;
385 if (lppStream)
386 *lppStream = NULL;
388 if(dwReserved || !lppStream)
389 return E_INVALIDARG;
391 strm = IStream_Create(NULL, lpbData, dwDataLen);
393 if(!strm)
394 return E_OUTOFMEMORY;
396 IStream_QueryInterface(&strm->IStream_iface, &IID_IStream, (void**)lppStream);
397 IStream_Release(&strm->IStream_iface);
398 return S_OK;