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
26 IStream IStream_iface
;
40 static inline ISHRegStream
*impl_from_IStream(IStream
*iface
)
42 return CONTAINING_RECORD(iface
, ISHRegStream
, IStream_iface
);
45 /**************************************************************************
46 * IStream_fnQueryInterface
48 static HRESULT WINAPI
IStream_fnQueryInterface(IStream
*iface
, REFIID riid
, LPVOID
*ppvObj
)
50 ISHRegStream
*This
= impl_from_IStream(iface
);
52 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
56 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IStream
))
57 *ppvObj
= &This
->IStream_iface
;
61 IStream_AddRef((IStream
*)*ppvObj
);
62 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
65 TRACE("-- Interface: E_NOINTERFACE\n");
69 /**************************************************************************
72 static ULONG WINAPI
IStream_fnAddRef(IStream
*iface
)
74 ISHRegStream
*This
= impl_from_IStream(iface
);
75 ULONG refCount
= InterlockedIncrement(&This
->ref
);
77 TRACE("(%p)->(ref before=%u)\n",This
, refCount
- 1);
82 /**************************************************************************
85 static ULONG WINAPI
IStream_fnRelease(IStream
*iface
)
87 ISHRegStream
*This
= impl_from_IStream(iface
);
88 ULONG refCount
= InterlockedDecrement(&This
->ref
);
90 TRACE("(%p)->(ref before=%u)\n",This
, refCount
+ 1);
94 TRACE(" destroying SHReg IStream (%p)\n",This
);
98 /* write back data in REG_BINARY */
99 if (This
->dwMode
== STGM_READWRITE
|| This
->dwMode
== STGM_WRITE
)
104 RegSetValueExW(This
->hKey
, This
->u
.keyNameW
, 0, REG_BINARY
,
105 (const BYTE
*) This
->pbBuffer
, This
->dwLength
);
107 RegSetValueExA(This
->hKey
, This
->u
.keyNameA
, 0, REG_BINARY
,
108 (const BYTE
*) This
->pbBuffer
, This
->dwLength
);
113 RegDeleteValueW(This
->hKey
, This
->u
.keyNameW
);
115 RegDeleteValueA(This
->hKey
, This
->u
.keyNameA
);
119 RegCloseKey(This
->hKey
);
122 HeapFree(GetProcessHeap(),0,This
->u
.keyNameA
);
123 HeapFree(GetProcessHeap(),0,This
->pbBuffer
);
124 HeapFree(GetProcessHeap(),0,This
);
131 /**************************************************************************
134 static HRESULT WINAPI
IStream_fnRead (IStream
* iface
, void* pv
, ULONG cb
, ULONG
* pcbRead
)
136 ISHRegStream
*This
= impl_from_IStream(iface
);
139 TRACE("(%p)->(%p,0x%08x,%p)\n",This
, pv
, cb
, pcbRead
);
141 if (This
->dwPos
>= This
->dwLength
)
144 dwBytesToRead
= This
->dwLength
- This
->dwPos
;
146 dwBytesToRead
= (cb
> dwBytesToRead
) ? dwBytesToRead
: cb
;
147 if (dwBytesToRead
!= 0) /* not at end of buffer and we want to read something */
149 memmove(pv
, This
->pbBuffer
+ This
->dwPos
, dwBytesToRead
);
150 This
->dwPos
+= dwBytesToRead
; /* adjust pointer */
154 *pcbRead
= dwBytesToRead
;
159 /**************************************************************************
162 static HRESULT WINAPI
IStream_fnWrite (IStream
* iface
, const void* pv
, ULONG cb
, ULONG
* pcbWritten
)
164 ISHRegStream
*This
= impl_from_IStream(iface
);
165 DWORD newLen
= This
->dwPos
+ cb
;
167 TRACE("(%p, %p, %d, %p)\n",This
, pv
, cb
, pcbWritten
);
169 if (newLen
< This
->dwPos
) /* overflow */
170 return STG_E_INSUFFICIENTMEMORY
;
172 if (newLen
> This
->dwLength
)
174 LPBYTE newBuf
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pbBuffer
, newLen
);
176 return STG_E_INSUFFICIENTMEMORY
;
178 This
->dwLength
= newLen
;
179 This
->pbBuffer
= newBuf
;
181 memmove(This
->pbBuffer
+ This
->dwPos
, pv
, cb
);
182 This
->dwPos
+= cb
; /* adjust pointer */
190 /**************************************************************************
193 static HRESULT WINAPI
IStream_fnSeek (IStream
* iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
* plibNewPosition
)
195 ISHRegStream
*This
= impl_from_IStream(iface
);
197 TRACE("(%p, %s, %d %p)\n", This
,
198 wine_dbgstr_longlong(dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
200 if (dwOrigin
== STREAM_SEEK_SET
)
202 else if (dwOrigin
== STREAM_SEEK_CUR
)
203 tmp
.QuadPart
= This
->dwPos
+ dlibMove
.QuadPart
;
204 else if (dwOrigin
== STREAM_SEEK_END
)
205 tmp
.QuadPart
= This
->dwLength
+ dlibMove
.QuadPart
;
207 return STG_E_INVALIDPARAMETER
;
209 if (tmp
.QuadPart
< 0)
210 return STG_E_INVALIDFUNCTION
;
212 /* we cut off the high part here */
213 This
->dwPos
= tmp
.u
.LowPart
;
216 plibNewPosition
->QuadPart
= This
->dwPos
;
220 /**************************************************************************
223 static HRESULT WINAPI
IStream_fnSetSize (IStream
* iface
, ULARGE_INTEGER libNewSize
)
225 ISHRegStream
*This
= impl_from_IStream(iface
);
229 TRACE("(%p, %s)\n", This
, wine_dbgstr_longlong(libNewSize
.QuadPart
));
231 /* we cut off the high part here */
232 newLen
= libNewSize
.u
.LowPart
;
233 newBuf
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pbBuffer
, newLen
);
235 return STG_E_INSUFFICIENTMEMORY
;
237 This
->pbBuffer
= newBuf
;
238 This
->dwLength
= newLen
;
243 /**************************************************************************
246 static HRESULT WINAPI
IStream_fnCopyTo (IStream
* iface
, IStream
* pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
* pcbRead
, ULARGE_INTEGER
* pcbWritten
)
248 ISHRegStream
*This
= impl_from_IStream(iface
);
250 TRACE("(%p)\n",This
);
252 pcbRead
->QuadPart
= 0;
254 pcbWritten
->QuadPart
= 0;
260 /**************************************************************************
263 static HRESULT WINAPI
IStream_fnCommit (IStream
* iface
, DWORD grfCommitFlags
)
265 ISHRegStream
*This
= impl_from_IStream(iface
);
267 TRACE("(%p)\n",This
);
269 /* commit not supported by this stream */
273 /**************************************************************************
276 static HRESULT WINAPI
IStream_fnRevert (IStream
* iface
)
278 ISHRegStream
*This
= impl_from_IStream(iface
);
280 TRACE("(%p)\n",This
);
282 /* revert not supported by this stream */
286 /**************************************************************************
287 * IStream_fnLockUnlockRegion
289 static HRESULT WINAPI
IStream_fnLockUnlockRegion (IStream
* iface
, ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
291 ISHRegStream
*This
= impl_from_IStream(iface
);
293 TRACE("(%p)\n",This
);
295 /* lock/unlock not supported by this stream */
299 /*************************************************************************
302 static HRESULT WINAPI
IStream_fnStat (IStream
* iface
, STATSTG
* pstatstg
, DWORD grfStatFlag
)
304 ISHRegStream
*This
= impl_from_IStream(iface
);
306 TRACE("(%p, %p, %d)\n",This
,pstatstg
,grfStatFlag
);
308 pstatstg
->pwcsName
= NULL
;
309 pstatstg
->type
= STGTY_STREAM
;
310 pstatstg
->cbSize
.QuadPart
= This
->dwLength
;
311 pstatstg
->mtime
.dwHighDateTime
= 0;
312 pstatstg
->mtime
.dwLowDateTime
= 0;
313 pstatstg
->ctime
.dwHighDateTime
= 0;
314 pstatstg
->ctime
.dwLowDateTime
= 0;
315 pstatstg
->atime
.dwHighDateTime
= 0;
316 pstatstg
->atime
.dwLowDateTime
= 0;
317 pstatstg
->grfMode
= This
->dwMode
;
318 pstatstg
->grfLocksSupported
= 0;
319 pstatstg
->clsid
= CLSID_NULL
;
320 pstatstg
->grfStateBits
= 0;
321 pstatstg
->reserved
= 0;
326 /*************************************************************************
329 static HRESULT WINAPI
IStream_fnClone (IStream
* iface
, IStream
** ppstm
)
331 ISHRegStream
*This
= impl_from_IStream(iface
);
333 TRACE("(%p)\n",This
);
336 /* clone not supported by this stream */
340 static const IStreamVtbl rstvt
=
342 IStream_fnQueryInterface
,
352 IStream_fnLockUnlockRegion
,
353 IStream_fnLockUnlockRegion
,
358 /* Methods overridden by the dummy stream */
360 /**************************************************************************
361 * IStream_fnAddRefDummy
363 static ULONG WINAPI
IStream_fnAddRefDummy(IStream
*iface
)
365 ISHRegStream
*This
= impl_from_IStream(iface
);
366 TRACE("(%p)\n", This
);
370 /**************************************************************************
371 * IStream_fnReleaseDummy
373 static ULONG WINAPI
IStream_fnReleaseDummy(IStream
*iface
)
375 ISHRegStream
*This
= impl_from_IStream(iface
);
376 TRACE("(%p)\n", This
);
380 /**************************************************************************
381 * IStream_fnReadDummy
383 static HRESULT WINAPI
IStream_fnReadDummy(IStream
*iface
, LPVOID pv
, ULONG cb
, ULONG
* pcbRead
)
390 static const IStreamVtbl DummyRegStreamVTable
=
392 IStream_fnQueryInterface
,
393 IStream_fnAddRefDummy
, /* Overridden */
394 IStream_fnReleaseDummy
, /* Overridden */
395 IStream_fnReadDummy
, /* Overridden */
402 IStream_fnLockUnlockRegion
,
403 IStream_fnLockUnlockRegion
,
408 /* Dummy registry stream object */
409 static ISHRegStream rsDummyRegStream
=
411 { &DummyRegStreamVTable
},
422 /**************************************************************************
425 * Internal helper: Create and initialise a new registry stream object.
427 static ISHRegStream
*IStream_Create(HKEY hKey
, LPBYTE pbBuffer
, DWORD dwLength
)
429 ISHRegStream
* regStream
;
431 regStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream
));
435 regStream
->IStream_iface
.lpVtbl
= &rstvt
;
437 regStream
->hKey
= hKey
;
438 regStream
->pbBuffer
= pbBuffer
;
439 regStream
->dwLength
= dwLength
;
440 regStream
->dwPos
= 0;
441 regStream
->dwMode
= STGM_READWRITE
;
442 regStream
->u
.keyNameA
= NULL
;
443 regStream
->bUnicode
= FALSE
;
445 TRACE ("Returning %p\n", regStream
);
449 /*************************************************************************
450 * SHOpenRegStream2A [SHLWAPI.@]
452 * Create a stream to read binary registry data.
455 * hKey [I] Registry handle
456 * pszSubkey [I] The sub key name
457 * pszValue [I] The value name under the sub key
461 * Success: An IStream interface referring to the registry data
462 * Failure: NULL, if the registry key could not be opened or is not binary.
464 IStream
* WINAPI
SHOpenRegStream2A(HKEY hKey
, LPCSTR pszSubkey
,
465 LPCSTR pszValue
,DWORD dwMode
)
469 LPBYTE lpBuff
= NULL
;
473 TRACE("(%p,%s,%s,0x%08x)\n", hKey
, pszSubkey
, pszValue
, dwMode
);
475 if (dwMode
== STGM_READ
)
476 ret
= RegOpenKeyExA(hKey
, pszSubkey
, 0, KEY_READ
, &hStrKey
);
477 else /* in write mode we make sure the subkey exits */
478 ret
= RegCreateKeyExA(hKey
, pszSubkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
, &hStrKey
, NULL
);
480 if (ret
== ERROR_SUCCESS
)
482 if (dwMode
== STGM_READ
|| dwMode
== STGM_READWRITE
)
484 /* read initial data */
485 ret
= RegQueryValueExA(hStrKey
, pszValue
, 0, 0, 0, &dwLength
);
486 if (ret
== ERROR_SUCCESS
&& dwLength
)
488 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
489 RegQueryValueExA(hStrKey
, pszValue
, 0, 0, lpBuff
, &dwLength
);
494 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
496 tmp
= IStream_Create(hStrKey
, lpBuff
, dwLength
);
501 int len
= lstrlenA(pszValue
) + 1;
502 tmp
->u
.keyNameA
= HeapAlloc(GetProcessHeap(), 0, len
);
503 memcpy(tmp
->u
.keyNameA
, pszValue
, len
);
506 tmp
->dwMode
= dwMode
;
507 tmp
->bUnicode
= FALSE
;
508 return &tmp
->IStream_iface
;
512 HeapFree(GetProcessHeap(), 0, lpBuff
);
514 RegCloseKey(hStrKey
);
518 /*************************************************************************
519 * SHOpenRegStream2W [SHLWAPI.@]
521 * See SHOpenRegStream2A.
523 IStream
* WINAPI
SHOpenRegStream2W(HKEY hKey
, LPCWSTR pszSubkey
,
524 LPCWSTR pszValue
, DWORD dwMode
)
528 LPBYTE lpBuff
= NULL
;
532 TRACE("(%p,%s,%s,0x%08x)\n", hKey
, debugstr_w(pszSubkey
),
533 debugstr_w(pszValue
), dwMode
);
535 if (dwMode
== STGM_READ
)
536 ret
= RegOpenKeyExW(hKey
, pszSubkey
, 0, KEY_READ
, &hStrKey
);
537 else /* in write mode we make sure the subkey exits */
538 ret
= RegCreateKeyExW(hKey
, pszSubkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
, &hStrKey
, NULL
);
540 if (ret
== ERROR_SUCCESS
)
542 if (dwMode
== STGM_READ
|| dwMode
== STGM_READWRITE
)
544 /* read initial data */
545 ret
= RegQueryValueExW(hStrKey
, pszValue
, 0, 0, 0, &dwLength
);
546 if (ret
== ERROR_SUCCESS
&& dwLength
)
548 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
549 RegQueryValueExW(hStrKey
, pszValue
, 0, 0, lpBuff
, &dwLength
);
554 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
556 tmp
= IStream_Create(hStrKey
, lpBuff
, dwLength
);
561 int len
= lstrlenW(pszValue
) + 1;
562 tmp
->u
.keyNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
563 memcpy(tmp
->u
.keyNameW
, pszValue
, len
* sizeof(WCHAR
));
566 tmp
->dwMode
= dwMode
;
567 tmp
->bUnicode
= TRUE
;
568 return &tmp
->IStream_iface
;
572 HeapFree(GetProcessHeap(), 0, lpBuff
);
574 RegCloseKey(hStrKey
);
578 /*************************************************************************
579 * SHOpenRegStreamA [SHLWAPI.@]
581 * Create a stream to read binary registry data.
584 * hKey [I] Registry handle
585 * pszSubkey [I] The sub key name
586 * pszValue [I] The value name under the sub key
587 * dwMode [I] STGM mode for opening the file
590 * Success: An IStream interface referring to the registry data
591 * Failure: If the registry key could not be opened or is not binary,
592 * A dummy (empty) IStream object is returned.
594 IStream
* WINAPI
SHOpenRegStreamA(HKEY hkey
, LPCSTR pszSubkey
,
595 LPCSTR pszValue
, DWORD dwMode
)
599 TRACE("(%p,%s,%s,0x%08x)\n", hkey
, pszSubkey
, pszValue
, dwMode
);
601 iStream
= SHOpenRegStream2A(hkey
, pszSubkey
, pszValue
, dwMode
);
602 return iStream
? iStream
: &rsDummyRegStream
.IStream_iface
;
605 /*************************************************************************
606 * SHOpenRegStreamW [SHLWAPI.@]
608 * See SHOpenRegStreamA.
610 IStream
* WINAPI
SHOpenRegStreamW(HKEY hkey
, LPCWSTR pszSubkey
,
611 LPCWSTR pszValue
, DWORD dwMode
)
615 TRACE("(%p,%s,%s,0x%08x)\n", hkey
, debugstr_w(pszSubkey
),
616 debugstr_w(pszValue
), dwMode
);
617 iStream
= SHOpenRegStream2W(hkey
, pszSubkey
, pszValue
, dwMode
);
618 return iStream
? iStream
: &rsDummyRegStream
.IStream_iface
;
621 /*************************************************************************
624 * Create an IStream object on a block of memory.
627 * lpbData [I] Memory block to create the IStream object on
628 * dwDataLen [I] Length of data block
631 * Success: A pointer to the IStream object.
632 * Failure: NULL, if any parameters are invalid or an error occurs.
635 * A copy of the memory pointed to by lpbData is made, and is freed
636 * when the stream is released.
638 IStream
* WINAPI
SHCreateMemStream(const BYTE
*lpbData
, UINT dwDataLen
)
640 ISHRegStream
*strm
= NULL
;
643 TRACE("(%p,%d)\n", lpbData
, dwDataLen
);
648 lpbDup
= HeapAlloc(GetProcessHeap(), 0, dwDataLen
);
652 memcpy(lpbDup
, lpbData
, dwDataLen
);
653 strm
= IStream_Create(NULL
, lpbDup
, dwDataLen
);
656 HeapFree(GetProcessHeap(), 0, lpbDup
);
658 return &strm
->IStream_iface
;
661 /*************************************************************************
662 * SHCreateStreamWrapper [SHLWAPI.@]
664 * Create an IStream object on a block of memory.
667 * lpbData [I] Memory block to create the IStream object on
668 * dwDataLen [I] Length of data block
669 * dwReserved [I] Reserved, Must be 0.
670 * lppStream [O] Destination for IStream object
673 * Success: S_OK. lppStream contains the new IStream object.
674 * Failure: E_INVALIDARG, if any parameters are invalid,
675 * E_OUTOFMEMORY if memory allocation fails.
678 * The stream assumes ownership of the memory passed to it.
680 HRESULT WINAPI
SHCreateStreamWrapper(LPBYTE lpbData
, DWORD dwDataLen
,
681 DWORD dwReserved
, IStream
**lppStream
)
688 if(dwReserved
|| !lppStream
)
691 strm
= IStream_Create(NULL
, lpbData
, dwDataLen
);
694 return E_OUTOFMEMORY
;
696 IStream_QueryInterface(&strm
->IStream_iface
, &IID_IStream
, (void**)lppStream
);
697 IStream_Release(&strm
->IStream_iface
);