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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(shell);
40 const IStreamVtbl *lpVtbl;
48 /**************************************************************************
49 * IStream_fnQueryInterface
51 static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
53 ISHRegStream *This = (ISHRegStream *)iface;
55 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
59 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
61 else if(IsEqualIID(riid, &IID_IStream)) /*IStream*/
66 IStream_AddRef((IStream*)*ppvObj);
67 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
70 TRACE("-- Interface: E_NOINTERFACE\n");
74 /**************************************************************************
77 static ULONG WINAPI IStream_fnAddRef(IStream *iface)
79 ISHRegStream *This = (ISHRegStream *)iface;
80 ULONG refCount = InterlockedIncrement(&This->ref);
82 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
87 /**************************************************************************
90 static ULONG WINAPI IStream_fnRelease(IStream *iface)
92 ISHRegStream *This = (ISHRegStream *)iface;
93 ULONG refCount = InterlockedDecrement(&This->ref);
95 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
99 TRACE(" destroying SHReg IStream (%p)\n",This);
101 HeapFree(GetProcessHeap(),0,This->pbBuffer);
104 RegCloseKey(This->hKey);
106 HeapFree(GetProcessHeap(),0,This);
113 /**************************************************************************
116 static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
118 ISHRegStream *This = (ISHRegStream *)iface;
121 TRACE("(%p)->(%p,0x%08x,%p)\n",This, pv, cb, pcbRead);
123 if (This->dwPos >= This->dwLength)
126 dwBytesToRead = This->dwLength - This->dwPos;
128 dwBytesToRead = (cb > dwBytesToRead) ? dwBytesToRead : cb;
129 if (dwBytesToRead != 0) /* not at end of buffer and we want to read something */
131 memmove(pv, This->pbBuffer + This->dwPos, dwBytesToRead);
132 This->dwPos += dwBytesToRead; /* adjust pointer */
136 *pcbRead = dwBytesToRead;
141 /**************************************************************************
144 static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
146 ISHRegStream *This = (ISHRegStream *)iface;
147 DWORD newLen = This->dwPos + cb;
149 TRACE("(%p, %p, %d, %p)\n",This, pv, cb, pcbWritten);
151 if (newLen < This->dwPos) /* overflow */
152 return STG_E_INSUFFICIENTMEMORY;
154 if (newLen > This->dwLength)
156 LPBYTE newBuf = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pbBuffer, newLen);
158 return STG_E_INSUFFICIENTMEMORY;
160 This->dwLength = newLen;
161 This->pbBuffer = newBuf;
163 memmove(This->pbBuffer + This->dwPos, pv, cb);
164 This->dwPos += cb; /* adjust pointer */
172 /**************************************************************************
175 static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
177 ISHRegStream *This = (ISHRegStream *)iface;
179 TRACE("(%p, %s, %d %p)\n", This,
180 wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, plibNewPosition);
182 if (dwOrigin == STREAM_SEEK_SET)
184 else if (dwOrigin == STREAM_SEEK_CUR)
185 tmp.QuadPart = This->dwPos + dlibMove.QuadPart;
186 else if (dwOrigin == STREAM_SEEK_END)
187 tmp.QuadPart = This->dwLength + dlibMove.QuadPart;
189 return STG_E_INVALIDPARAMETER;
191 if (tmp.QuadPart < 0)
192 return STG_E_INVALIDFUNCTION;
194 /* we cut off the high part here */
195 This->dwPos = tmp.LowPart;
198 plibNewPosition->QuadPart = This->dwPos;
202 /**************************************************************************
205 static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
207 ISHRegStream *This = (ISHRegStream *)iface;
211 TRACE("(%p, %s)\n", This, wine_dbgstr_longlong(libNewSize.QuadPart));
213 /* we cut off the high part here */
214 newLen = libNewSize.LowPart;
215 newBuf = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pbBuffer, newLen);
217 return STG_E_INSUFFICIENTMEMORY;
219 This->pbBuffer = newBuf;
220 This->dwLength = newLen;
225 /**************************************************************************
228 static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
230 ISHRegStream *This = (ISHRegStream *)iface;
232 TRACE("(%p)\n",This);
234 pcbRead->QuadPart = 0;
236 pcbWritten->QuadPart = 0;
242 /**************************************************************************
245 static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
247 ISHRegStream *This = (ISHRegStream *)iface;
249 TRACE("(%p)\n",This);
251 /* commit not supported by this stream */
255 /**************************************************************************
258 static HRESULT WINAPI IStream_fnRevert (IStream * iface)
260 ISHRegStream *This = (ISHRegStream *)iface;
262 TRACE("(%p)\n",This);
264 /* revert not supported by this stream */
268 /**************************************************************************
269 * IStream_fnLockUnlockRegion
271 static HRESULT WINAPI IStream_fnLockUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
273 ISHRegStream *This = (ISHRegStream *)iface;
275 TRACE("(%p)\n",This);
277 /* lock/unlock not supported by this stream */
281 /*************************************************************************
284 static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag)
286 ISHRegStream *This = (ISHRegStream *)iface;
288 TRACE("(%p, %p, %d)\n",This,pstatstg,grfStatFlag);
290 pstatstg->pwcsName = NULL;
291 pstatstg->type = STGTY_STREAM;
292 pstatstg->cbSize.QuadPart = This->dwLength;
293 pstatstg->mtime.dwHighDateTime = 0;
294 pstatstg->mtime.dwLowDateTime = 0;
295 pstatstg->ctime.dwHighDateTime = 0;
296 pstatstg->ctime.dwLowDateTime = 0;
297 pstatstg->atime.dwHighDateTime = 0;
298 pstatstg->atime.dwLowDateTime = 0;
299 pstatstg->grfMode = STGM_READWRITE;
300 pstatstg->grfLocksSupported = 0;
301 pstatstg->clsid = CLSID_NULL;
302 pstatstg->grfStateBits = 0;
303 pstatstg->reserved = 0;
308 /*************************************************************************
311 static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
313 ISHRegStream *This = (ISHRegStream *)iface;
315 TRACE("(%p)\n",This);
318 /* clone not supported by this stream */
322 static const IStreamVtbl rstvt =
324 IStream_fnQueryInterface,
334 IStream_fnLockUnlockRegion,
335 IStream_fnLockUnlockRegion,
340 /* Methods overridden by the dummy stream */
342 /**************************************************************************
343 * IStream_fnAddRefDummy
345 static ULONG WINAPI IStream_fnAddRefDummy(IStream *iface)
347 ISHRegStream *This = (ISHRegStream *)iface;
348 TRACE("(%p)\n", This);
352 /**************************************************************************
353 * IStream_fnReleaseDummy
355 static ULONG WINAPI IStream_fnReleaseDummy(IStream *iface)
357 ISHRegStream *This = (ISHRegStream *)iface;
358 TRACE("(%p)\n", This);
362 /**************************************************************************
363 * IStream_fnReadDummy
365 static HRESULT WINAPI IStream_fnReadDummy(IStream *iface, LPVOID pv, ULONG cb, ULONG* pcbRead)
372 static const IStreamVtbl DummyRegStreamVTable =
374 IStream_fnQueryInterface,
375 IStream_fnAddRefDummy, /* Overridden */
376 IStream_fnReleaseDummy, /* Overridden */
377 IStream_fnReadDummy, /* Overridden */
384 IStream_fnLockUnlockRegion,
385 IStream_fnLockUnlockRegion,
390 /* Dummy registry stream object */
391 static ISHRegStream rsDummyRegStream =
393 &DummyRegStreamVTable,
401 /**************************************************************************
404 * Internal helper: Create and initialise a new registry stream object.
406 static IStream *IStream_Create(HKEY hKey, LPBYTE pbBuffer, DWORD dwLength)
408 ISHRegStream* regStream;
410 regStream = HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream));
414 regStream->lpVtbl = &rstvt;
416 regStream->hKey = hKey;
417 regStream->pbBuffer = pbBuffer;
418 regStream->dwLength = dwLength;
419 regStream->dwPos = 0;
421 TRACE ("Returning %p\n", regStream);
422 return (IStream *)regStream;
425 /*************************************************************************
426 * SHOpenRegStream2A [SHLWAPI.@]
428 * Create a stream to read binary registry data.
431 * hKey [I] Registry handle
432 * pszSubkey [I] The sub key name
433 * pszValue [I] The value name under the sub key
437 * Success: An IStream interface referring to the registry data
438 * Failure: NULL, if the registry key could not be opened or is not binary.
440 IStream * WINAPI SHOpenRegStream2A(HKEY hKey, LPCSTR pszSubkey,
441 LPCSTR pszValue,DWORD dwMode)
445 LPBYTE lpBuff = NULL;
449 TRACE("(%p,%s,%s,0x%08x)\n", hKey, pszSubkey, pszValue, dwMode);
451 if (dwMode == STGM_READ)
452 ret = RegOpenKeyExA(hKey, pszSubkey, 0, KEY_READ, &hStrKey);
453 else /* in write mode we make sure the subkey exits */
454 ret = RegCreateKeyExA(hKey, pszSubkey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hStrKey, NULL);
456 if (ret == ERROR_SUCCESS)
458 if (dwMode == STGM_READ || dwMode == STGM_READWRITE)
460 /* read initial data */
461 ret = RegQueryValueExA(hStrKey, pszValue, 0, 0, 0, &dwLength);
462 if (ret == ERROR_SUCCESS && dwLength)
464 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwLength);
465 RegQueryValueExA(hStrKey, pszValue, 0, 0, lpBuff, &dwLength);
470 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwLength);
472 tmp = IStream_Create(hStrKey, lpBuff, dwLength);
477 HeapFree(GetProcessHeap(), 0, lpBuff);
479 RegCloseKey(hStrKey);
483 /*************************************************************************
484 * SHOpenRegStream2W [SHLWAPI.@]
486 * See SHOpenRegStream2A.
488 IStream * WINAPI SHOpenRegStream2W(HKEY hKey, LPCWSTR pszSubkey,
489 LPCWSTR pszValue, DWORD dwMode)
493 LPBYTE lpBuff = NULL;
497 TRACE("(%p,%s,%s,0x%08x)\n", hKey, debugstr_w(pszSubkey),
498 debugstr_w(pszValue), dwMode);
500 if (dwMode == STGM_READ)
501 ret = RegOpenKeyExW(hKey, pszSubkey, 0, KEY_READ, &hStrKey);
502 else /* in write mode we make sure the subkey exits */
503 ret = RegCreateKeyExW(hKey, pszSubkey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hStrKey, NULL);
505 if (ret == ERROR_SUCCESS)
507 if (dwMode == STGM_READ || dwMode == STGM_READWRITE)
509 /* read initial data */
510 ret = RegQueryValueExW(hStrKey, pszValue, 0, 0, 0, &dwLength);
511 if (ret == ERROR_SUCCESS && dwLength)
513 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwLength);
514 RegQueryValueExW(hStrKey, pszValue, 0, 0, lpBuff, &dwLength);
519 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwLength);
521 tmp = IStream_Create(hStrKey, lpBuff, dwLength);
526 HeapFree(GetProcessHeap(), 0, lpBuff);
528 RegCloseKey(hStrKey);
532 /*************************************************************************
533 * SHOpenRegStreamA [SHLWAPI.@]
535 * Create a stream to read binary registry data.
538 * hKey [I] Registry handle
539 * pszSubkey [I] The sub key name
540 * pszValue [I] The value name under the sub key
541 * dwMode [I] STGM mode for opening the file
544 * Success: An IStream interface referring to the registry data
545 * Failure: If the registry key could not be opened or is not binary,
546 * A dummy (empty) IStream object is returned.
548 IStream * WINAPI SHOpenRegStreamA(HKEY hkey, LPCSTR pszSubkey,
549 LPCSTR pszValue, DWORD dwMode)
553 TRACE("(%p,%s,%s,0x%08x)\n", hkey, pszSubkey, pszValue, dwMode);
555 iStream = SHOpenRegStream2A(hkey, pszSubkey, pszValue, dwMode);
556 return iStream ? iStream : (IStream *)&rsDummyRegStream;
559 /*************************************************************************
560 * SHOpenRegStreamW [SHLWAPI.@]
562 * See SHOpenRegStreamA.
564 IStream * WINAPI SHOpenRegStreamW(HKEY hkey, LPCWSTR pszSubkey,
565 LPCWSTR pszValue, DWORD dwMode)
569 TRACE("(%p,%s,%s,0x%08x)\n", hkey, debugstr_w(pszSubkey),
570 debugstr_w(pszValue), dwMode);
571 iStream = SHOpenRegStream2W(hkey, pszSubkey, pszValue, dwMode);
572 return iStream ? iStream : (IStream *)&rsDummyRegStream;
575 /*************************************************************************
578 * Create an IStream object on a block of memory.
581 * lpbData [I] Memory block to create the IStream object on
582 * dwDataLen [I] Length of data block
585 * Success: A pointer to the IStream object.
586 * Failure: NULL, if any parameters are invalid or an error occurs.
589 * A copy of the memory pointed to by lpbData is made, and is freed
590 * when the stream is released.
592 IStream * WINAPI SHCreateMemStream(const BYTE *lpbData, UINT dwDataLen)
594 IStream *iStrmRet = NULL;
597 TRACE("(%p,%d)\n", lpbData, dwDataLen);
602 lpbDup = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
606 memcpy(lpbDup, lpbData, dwDataLen);
607 iStrmRet = IStream_Create(NULL, lpbDup, dwDataLen);
610 HeapFree(GetProcessHeap(), 0, lpbDup);
615 /*************************************************************************
616 * SHCreateStreamWrapper [SHLWAPI.@]
618 * Create an IStream object on a block of memory.
621 * lpbData [I] Memory block to create the IStream object on
622 * dwDataLen [I] Length of data block
623 * dwReserved [I] Reserved, Must be 0.
624 * lppStream [O] Destination for IStream object
627 * Success: S_OK. lppStream contains the new IStream object.
628 * Failure: E_INVALIDARG, if any parameters are invalid,
629 * E_OUTOFMEMORY if memory allocation fails.
632 * The stream assumes ownership of the memory passed to it.
634 HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,
635 DWORD dwReserved, IStream **lppStream)
642 if(dwReserved || !lppStream)
645 lpStream = IStream_Create(NULL, lpbData, dwDataLen);
648 return E_OUTOFMEMORY;
650 IStream_QueryInterface(lpStream, &IID_IStream, (void**)lppStream);
651 IStream_Release(lpStream);