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
)) /*IUnknown*/
58 else if(IsEqualIID(riid
, &IID_IStream
)) /*IStream*/
63 IStream_AddRef((IStream
*)*ppvObj
);
64 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
67 TRACE("-- Interface: E_NOINTERFACE\n");
71 /**************************************************************************
74 static ULONG WINAPI
IStream_fnAddRef(IStream
*iface
)
76 ISHRegStream
*This
= impl_from_IStream(iface
);
77 ULONG refCount
= InterlockedIncrement(&This
->ref
);
79 TRACE("(%p)->(ref before=%u)\n",This
, refCount
- 1);
84 /**************************************************************************
87 static ULONG WINAPI
IStream_fnRelease(IStream
*iface
)
89 ISHRegStream
*This
= impl_from_IStream(iface
);
90 ULONG refCount
= InterlockedDecrement(&This
->ref
);
92 TRACE("(%p)->(ref before=%u)\n",This
, refCount
+ 1);
96 TRACE(" destroying SHReg IStream (%p)\n",This
);
100 /* write back data in REG_BINARY */
101 if (This
->dwMode
== STGM_READWRITE
|| This
->dwMode
== STGM_WRITE
)
106 RegSetValueExW(This
->hKey
, This
->u
.keyNameW
, 0, REG_BINARY
,
107 (const BYTE
*) This
->pbBuffer
, This
->dwLength
);
109 RegSetValueExA(This
->hKey
, This
->u
.keyNameA
, 0, REG_BINARY
,
110 (const BYTE
*) This
->pbBuffer
, This
->dwLength
);
115 RegDeleteValueW(This
->hKey
, This
->u
.keyNameW
);
117 RegDeleteValueA(This
->hKey
, This
->u
.keyNameA
);
121 RegCloseKey(This
->hKey
);
124 HeapFree(GetProcessHeap(),0,This
->u
.keyNameA
);
125 HeapFree(GetProcessHeap(),0,This
->pbBuffer
);
126 HeapFree(GetProcessHeap(),0,This
);
133 /**************************************************************************
136 static HRESULT WINAPI
IStream_fnRead (IStream
* iface
, void* pv
, ULONG cb
, ULONG
* pcbRead
)
138 ISHRegStream
*This
= impl_from_IStream(iface
);
141 TRACE("(%p)->(%p,0x%08x,%p)\n",This
, pv
, cb
, pcbRead
);
143 if (This
->dwPos
>= This
->dwLength
)
146 dwBytesToRead
= This
->dwLength
- This
->dwPos
;
148 dwBytesToRead
= (cb
> dwBytesToRead
) ? dwBytesToRead
: cb
;
149 if (dwBytesToRead
!= 0) /* not at end of buffer and we want to read something */
151 memmove(pv
, This
->pbBuffer
+ This
->dwPos
, dwBytesToRead
);
152 This
->dwPos
+= dwBytesToRead
; /* adjust pointer */
156 *pcbRead
= dwBytesToRead
;
161 /**************************************************************************
164 static HRESULT WINAPI
IStream_fnWrite (IStream
* iface
, const void* pv
, ULONG cb
, ULONG
* pcbWritten
)
166 ISHRegStream
*This
= impl_from_IStream(iface
);
167 DWORD newLen
= This
->dwPos
+ cb
;
169 TRACE("(%p, %p, %d, %p)\n",This
, pv
, cb
, pcbWritten
);
171 if (newLen
< This
->dwPos
) /* overflow */
172 return STG_E_INSUFFICIENTMEMORY
;
174 if (newLen
> This
->dwLength
)
176 LPBYTE newBuf
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pbBuffer
, newLen
);
178 return STG_E_INSUFFICIENTMEMORY
;
180 This
->dwLength
= newLen
;
181 This
->pbBuffer
= newBuf
;
183 memmove(This
->pbBuffer
+ This
->dwPos
, pv
, cb
);
184 This
->dwPos
+= cb
; /* adjust pointer */
192 /**************************************************************************
195 static HRESULT WINAPI
IStream_fnSeek (IStream
* iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
, ULARGE_INTEGER
* plibNewPosition
)
197 ISHRegStream
*This
= impl_from_IStream(iface
);
199 TRACE("(%p, %s, %d %p)\n", This
,
200 wine_dbgstr_longlong(dlibMove
.QuadPart
), dwOrigin
, plibNewPosition
);
202 if (dwOrigin
== STREAM_SEEK_SET
)
204 else if (dwOrigin
== STREAM_SEEK_CUR
)
205 tmp
.QuadPart
= This
->dwPos
+ dlibMove
.QuadPart
;
206 else if (dwOrigin
== STREAM_SEEK_END
)
207 tmp
.QuadPart
= This
->dwLength
+ dlibMove
.QuadPart
;
209 return STG_E_INVALIDPARAMETER
;
211 if (tmp
.QuadPart
< 0)
212 return STG_E_INVALIDFUNCTION
;
214 /* we cut off the high part here */
215 This
->dwPos
= tmp
.u
.LowPart
;
218 plibNewPosition
->QuadPart
= This
->dwPos
;
222 /**************************************************************************
225 static HRESULT WINAPI
IStream_fnSetSize (IStream
* iface
, ULARGE_INTEGER libNewSize
)
227 ISHRegStream
*This
= impl_from_IStream(iface
);
231 TRACE("(%p, %s)\n", This
, wine_dbgstr_longlong(libNewSize
.QuadPart
));
233 /* we cut off the high part here */
234 newLen
= libNewSize
.u
.LowPart
;
235 newBuf
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pbBuffer
, newLen
);
237 return STG_E_INSUFFICIENTMEMORY
;
239 This
->pbBuffer
= newBuf
;
240 This
->dwLength
= newLen
;
245 /**************************************************************************
248 static HRESULT WINAPI
IStream_fnCopyTo (IStream
* iface
, IStream
* pstm
, ULARGE_INTEGER cb
, ULARGE_INTEGER
* pcbRead
, ULARGE_INTEGER
* pcbWritten
)
250 ISHRegStream
*This
= impl_from_IStream(iface
);
252 TRACE("(%p)\n",This
);
254 pcbRead
->QuadPart
= 0;
256 pcbWritten
->QuadPart
= 0;
262 /**************************************************************************
265 static HRESULT WINAPI
IStream_fnCommit (IStream
* iface
, DWORD grfCommitFlags
)
267 ISHRegStream
*This
= impl_from_IStream(iface
);
269 TRACE("(%p)\n",This
);
271 /* commit not supported by this stream */
275 /**************************************************************************
278 static HRESULT WINAPI
IStream_fnRevert (IStream
* iface
)
280 ISHRegStream
*This
= impl_from_IStream(iface
);
282 TRACE("(%p)\n",This
);
284 /* revert not supported by this stream */
288 /**************************************************************************
289 * IStream_fnLockUnlockRegion
291 static HRESULT WINAPI
IStream_fnLockUnlockRegion (IStream
* iface
, ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
293 ISHRegStream
*This
= impl_from_IStream(iface
);
295 TRACE("(%p)\n",This
);
297 /* lock/unlock not supported by this stream */
301 /*************************************************************************
304 static HRESULT WINAPI
IStream_fnStat (IStream
* iface
, STATSTG
* pstatstg
, DWORD grfStatFlag
)
306 ISHRegStream
*This
= impl_from_IStream(iface
);
308 TRACE("(%p, %p, %d)\n",This
,pstatstg
,grfStatFlag
);
310 pstatstg
->pwcsName
= NULL
;
311 pstatstg
->type
= STGTY_STREAM
;
312 pstatstg
->cbSize
.QuadPart
= This
->dwLength
;
313 pstatstg
->mtime
.dwHighDateTime
= 0;
314 pstatstg
->mtime
.dwLowDateTime
= 0;
315 pstatstg
->ctime
.dwHighDateTime
= 0;
316 pstatstg
->ctime
.dwLowDateTime
= 0;
317 pstatstg
->atime
.dwHighDateTime
= 0;
318 pstatstg
->atime
.dwLowDateTime
= 0;
319 pstatstg
->grfMode
= This
->dwMode
;
320 pstatstg
->grfLocksSupported
= 0;
321 pstatstg
->clsid
= CLSID_NULL
;
322 pstatstg
->grfStateBits
= 0;
323 pstatstg
->reserved
= 0;
328 /*************************************************************************
331 static HRESULT WINAPI
IStream_fnClone (IStream
* iface
, IStream
** ppstm
)
333 ISHRegStream
*This
= impl_from_IStream(iface
);
335 TRACE("(%p)\n",This
);
338 /* clone not supported by this stream */
342 static const IStreamVtbl rstvt
=
344 IStream_fnQueryInterface
,
354 IStream_fnLockUnlockRegion
,
355 IStream_fnLockUnlockRegion
,
360 /* Methods overridden by the dummy stream */
362 /**************************************************************************
363 * IStream_fnAddRefDummy
365 static ULONG WINAPI
IStream_fnAddRefDummy(IStream
*iface
)
367 ISHRegStream
*This
= impl_from_IStream(iface
);
368 TRACE("(%p)\n", This
);
372 /**************************************************************************
373 * IStream_fnReleaseDummy
375 static ULONG WINAPI
IStream_fnReleaseDummy(IStream
*iface
)
377 ISHRegStream
*This
= impl_from_IStream(iface
);
378 TRACE("(%p)\n", This
);
382 /**************************************************************************
383 * IStream_fnReadDummy
385 static HRESULT WINAPI
IStream_fnReadDummy(IStream
*iface
, LPVOID pv
, ULONG cb
, ULONG
* pcbRead
)
392 static const IStreamVtbl DummyRegStreamVTable
=
394 IStream_fnQueryInterface
,
395 IStream_fnAddRefDummy
, /* Overridden */
396 IStream_fnReleaseDummy
, /* Overridden */
397 IStream_fnReadDummy
, /* Overridden */
404 IStream_fnLockUnlockRegion
,
405 IStream_fnLockUnlockRegion
,
410 /* Dummy registry stream object */
411 static ISHRegStream rsDummyRegStream
=
413 { &DummyRegStreamVTable
},
424 /**************************************************************************
427 * Internal helper: Create and initialise a new registry stream object.
429 static ISHRegStream
*IStream_Create(HKEY hKey
, LPBYTE pbBuffer
, DWORD dwLength
)
431 ISHRegStream
* regStream
;
433 regStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream
));
437 regStream
->IStream_iface
.lpVtbl
= &rstvt
;
439 regStream
->hKey
= hKey
;
440 regStream
->pbBuffer
= pbBuffer
;
441 regStream
->dwLength
= dwLength
;
442 regStream
->dwPos
= 0;
443 regStream
->dwMode
= STGM_READWRITE
;
444 regStream
->u
.keyNameA
= NULL
;
445 regStream
->bUnicode
= FALSE
;
447 TRACE ("Returning %p\n", regStream
);
451 /*************************************************************************
452 * SHOpenRegStream2A [SHLWAPI.@]
454 * Create a stream to read binary registry data.
457 * hKey [I] Registry handle
458 * pszSubkey [I] The sub key name
459 * pszValue [I] The value name under the sub key
463 * Success: An IStream interface referring to the registry data
464 * Failure: NULL, if the registry key could not be opened or is not binary.
466 IStream
* WINAPI
SHOpenRegStream2A(HKEY hKey
, LPCSTR pszSubkey
,
467 LPCSTR pszValue
,DWORD dwMode
)
471 LPBYTE lpBuff
= NULL
;
475 TRACE("(%p,%s,%s,0x%08x)\n", hKey
, pszSubkey
, pszValue
, dwMode
);
477 if (dwMode
== STGM_READ
)
478 ret
= RegOpenKeyExA(hKey
, pszSubkey
, 0, KEY_READ
, &hStrKey
);
479 else /* in write mode we make sure the subkey exits */
480 ret
= RegCreateKeyExA(hKey
, pszSubkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
, &hStrKey
, NULL
);
482 if (ret
== ERROR_SUCCESS
)
484 if (dwMode
== STGM_READ
|| dwMode
== STGM_READWRITE
)
486 /* read initial data */
487 ret
= RegQueryValueExA(hStrKey
, pszValue
, 0, 0, 0, &dwLength
);
488 if (ret
== ERROR_SUCCESS
&& dwLength
)
490 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
491 RegQueryValueExA(hStrKey
, pszValue
, 0, 0, lpBuff
, &dwLength
);
496 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
498 tmp
= IStream_Create(hStrKey
, lpBuff
, dwLength
);
503 int len
= lstrlenA(pszValue
) + 1;
504 tmp
->u
.keyNameA
= HeapAlloc(GetProcessHeap(), 0, len
);
505 memcpy(tmp
->u
.keyNameA
, pszValue
, len
);
508 tmp
->dwMode
= dwMode
;
509 tmp
->bUnicode
= FALSE
;
510 return &tmp
->IStream_iface
;
514 HeapFree(GetProcessHeap(), 0, lpBuff
);
516 RegCloseKey(hStrKey
);
520 /*************************************************************************
521 * SHOpenRegStream2W [SHLWAPI.@]
523 * See SHOpenRegStream2A.
525 IStream
* WINAPI
SHOpenRegStream2W(HKEY hKey
, LPCWSTR pszSubkey
,
526 LPCWSTR pszValue
, DWORD dwMode
)
530 LPBYTE lpBuff
= NULL
;
534 TRACE("(%p,%s,%s,0x%08x)\n", hKey
, debugstr_w(pszSubkey
),
535 debugstr_w(pszValue
), dwMode
);
537 if (dwMode
== STGM_READ
)
538 ret
= RegOpenKeyExW(hKey
, pszSubkey
, 0, KEY_READ
, &hStrKey
);
539 else /* in write mode we make sure the subkey exits */
540 ret
= RegCreateKeyExW(hKey
, pszSubkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
, &hStrKey
, NULL
);
542 if (ret
== ERROR_SUCCESS
)
544 if (dwMode
== STGM_READ
|| dwMode
== STGM_READWRITE
)
546 /* read initial data */
547 ret
= RegQueryValueExW(hStrKey
, pszValue
, 0, 0, 0, &dwLength
);
548 if (ret
== ERROR_SUCCESS
&& dwLength
)
550 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
551 RegQueryValueExW(hStrKey
, pszValue
, 0, 0, lpBuff
, &dwLength
);
556 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
558 tmp
= IStream_Create(hStrKey
, lpBuff
, dwLength
);
563 int len
= lstrlenW(pszValue
) + 1;
564 tmp
->u
.keyNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
565 memcpy(tmp
->u
.keyNameW
, pszValue
, len
* sizeof(WCHAR
));
568 tmp
->dwMode
= dwMode
;
569 tmp
->bUnicode
= TRUE
;
570 return &tmp
->IStream_iface
;
574 HeapFree(GetProcessHeap(), 0, lpBuff
);
576 RegCloseKey(hStrKey
);
580 /*************************************************************************
581 * SHOpenRegStreamA [SHLWAPI.@]
583 * Create a stream to read binary registry data.
586 * hKey [I] Registry handle
587 * pszSubkey [I] The sub key name
588 * pszValue [I] The value name under the sub key
589 * dwMode [I] STGM mode for opening the file
592 * Success: An IStream interface referring to the registry data
593 * Failure: If the registry key could not be opened or is not binary,
594 * A dummy (empty) IStream object is returned.
596 IStream
* WINAPI
SHOpenRegStreamA(HKEY hkey
, LPCSTR pszSubkey
,
597 LPCSTR pszValue
, DWORD dwMode
)
601 TRACE("(%p,%s,%s,0x%08x)\n", hkey
, pszSubkey
, pszValue
, dwMode
);
603 iStream
= SHOpenRegStream2A(hkey
, pszSubkey
, pszValue
, dwMode
);
604 return iStream
? iStream
: &rsDummyRegStream
.IStream_iface
;
607 /*************************************************************************
608 * SHOpenRegStreamW [SHLWAPI.@]
610 * See SHOpenRegStreamA.
612 IStream
* WINAPI
SHOpenRegStreamW(HKEY hkey
, LPCWSTR pszSubkey
,
613 LPCWSTR pszValue
, DWORD dwMode
)
617 TRACE("(%p,%s,%s,0x%08x)\n", hkey
, debugstr_w(pszSubkey
),
618 debugstr_w(pszValue
), dwMode
);
619 iStream
= SHOpenRegStream2W(hkey
, pszSubkey
, pszValue
, dwMode
);
620 return iStream
? iStream
: &rsDummyRegStream
.IStream_iface
;
623 /*************************************************************************
626 * Create an IStream object on a block of memory.
629 * lpbData [I] Memory block to create the IStream object on
630 * dwDataLen [I] Length of data block
633 * Success: A pointer to the IStream object.
634 * Failure: NULL, if any parameters are invalid or an error occurs.
637 * A copy of the memory pointed to by lpbData is made, and is freed
638 * when the stream is released.
640 IStream
* WINAPI
SHCreateMemStream(const BYTE
*lpbData
, UINT dwDataLen
)
642 ISHRegStream
*strm
= NULL
;
645 TRACE("(%p,%d)\n", lpbData
, dwDataLen
);
650 lpbDup
= HeapAlloc(GetProcessHeap(), 0, dwDataLen
);
654 memcpy(lpbDup
, lpbData
, dwDataLen
);
655 strm
= IStream_Create(NULL
, lpbDup
, dwDataLen
);
658 HeapFree(GetProcessHeap(), 0, lpbDup
);
660 return &strm
->IStream_iface
;
663 /*************************************************************************
664 * SHCreateStreamWrapper [SHLWAPI.@]
666 * Create an IStream object on a block of memory.
669 * lpbData [I] Memory block to create the IStream object on
670 * dwDataLen [I] Length of data block
671 * dwReserved [I] Reserved, Must be 0.
672 * lppStream [O] Destination for IStream object
675 * Success: S_OK. lppStream contains the new IStream object.
676 * Failure: E_INVALIDARG, if any parameters are invalid,
677 * E_OUTOFMEMORY if memory allocation fails.
680 * The stream assumes ownership of the memory passed to it.
682 HRESULT WINAPI
SHCreateStreamWrapper(LPBYTE lpbData
, DWORD dwDataLen
,
683 DWORD dwReserved
, IStream
**lppStream
)
690 if(dwReserved
|| !lppStream
)
693 strm
= IStream_Create(NULL
, lpbData
, dwDataLen
);
696 return E_OUTOFMEMORY
;
698 IStream_QueryInterface(&strm
->IStream_iface
, &IID_IStream
, (void**)lppStream
);
699 IStream_Release(&strm
->IStream_iface
);