-/*\r
- * SHLWAPI Registry Stream functions\r
- *\r
- * Copyright 1999 Juergen Schmied\r
- * Copyright 2002 Jon Griffiths\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-#include <stdarg.h>\r
-#include <string.h>\r
-\r
-#define COBJMACROS\r
-\r
-#include "winerror.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "objbase.h"\r
-#include "winreg.h"\r
-\r
-#include "wine/debug.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(shell);\r
-\r
-typedef struct\r
-{ IStreamVtbl *lpVtbl;\r
- DWORD ref;\r
- HKEY hKey;\r
- LPBYTE pbBuffer;\r
- DWORD dwLength;\r
- DWORD dwPos;\r
-} ISHRegStream;\r
-\r
-/**************************************************************************\r
-* IStream_fnQueryInterface\r
-*/\r
-static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);\r
-\r
- *ppvObj = NULL;\r
-\r
- if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/\r
- *ppvObj = This;\r
- else if(IsEqualIID(riid, &IID_IStream)) /*IStream*/\r
- *ppvObj = This;\r
-\r
- if(*ppvObj)\r
- {\r
- IStream_AddRef((IStream*)*ppvObj);\r
- TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);\r
- return S_OK;\r
- }\r
- TRACE("-- Interface: E_NOINTERFACE\n");\r
- return E_NOINTERFACE;\r
-}\r
-\r
-/**************************************************************************\r
-* IStream_fnAddRef\r
-*/\r
-static ULONG WINAPI IStream_fnAddRef(IStream *iface)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
- ULONG refCount = InterlockedIncrement(&This->ref);\r
- \r
- TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);\r
-\r
- return refCount;\r
-}\r
-\r
-/**************************************************************************\r
-* IStream_fnRelease\r
-*/\r
-static ULONG WINAPI IStream_fnRelease(IStream *iface)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
- ULONG refCount = InterlockedDecrement(&This->ref);\r
-\r
- TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);\r
-\r
- if (!refCount)\r
- {\r
- TRACE(" destroying SHReg IStream (%p)\n",This);\r
-\r
- HeapFree(GetProcessHeap(),0,This->pbBuffer);\r
-\r
- if (This->hKey)\r
- RegCloseKey(This->hKey);\r
-\r
- HeapFree(GetProcessHeap(),0,This);\r
- return 0;\r
- }\r
-\r
- return refCount;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnRead\r
- */\r
-static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- DWORD dwBytesToRead, dwBytesLeft;\r
-\r
- TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);\r
-\r
- if (!pv)\r
- return STG_E_INVALIDPOINTER;\r
-\r
- dwBytesLeft = This->dwLength - This->dwPos;\r
-\r
- if ( 0 >= dwBytesLeft ) /* end of buffer */\r
- return S_FALSE;\r
-\r
- dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;\r
-\r
- memmove ( pv, (This->pbBuffer) + (This->dwPos), dwBytesToRead);\r
-\r
- This->dwPos += dwBytesToRead; /* adjust pointer */\r
-\r
- if (pcbRead)\r
- *pcbRead = dwBytesToRead;\r
-\r
- return S_OK;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnWrite\r
- */\r
-static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- if (pcbWritten)\r
- *pcbWritten = 0;\r
-\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnSeek\r
- */\r
-static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- if (plibNewPosition)\r
- plibNewPosition->QuadPart = 0;\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnSetSize\r
- */\r
-static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnCopyTo\r
- */\r
-static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
- if (pcbRead)\r
- pcbRead->QuadPart = 0;\r
- if (pcbWritten)\r
- pcbWritten->QuadPart = 0;\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnCommit\r
- */\r
-static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnRevert\r
- */\r
-static HRESULT WINAPI IStream_fnRevert (IStream * iface)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- return E_NOTIMPL;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnLockUnlockRegion\r
- */\r
-static HRESULT WINAPI IStream_fnLockUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- return E_NOTIMPL;\r
-}\r
-\r
-/*************************************************************************\r
- * IStream_fnStat\r
- */\r
-static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- return E_NOTIMPL;\r
-}\r
-\r
-/*************************************************************************\r
- * IStream_fnClone\r
- */\r
-static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
- if (ppstm)\r
- *ppstm = NULL;\r
- return E_NOTIMPL;\r
-}\r
-\r
-static struct IStreamVtbl rstvt =\r
-{\r
- IStream_fnQueryInterface,\r
- IStream_fnAddRef,\r
- IStream_fnRelease,\r
- IStream_fnRead,\r
- IStream_fnWrite,\r
- IStream_fnSeek,\r
- IStream_fnSetSize,\r
- IStream_fnCopyTo,\r
- IStream_fnCommit,\r
- IStream_fnRevert,\r
- IStream_fnLockUnlockRegion,\r
- IStream_fnLockUnlockRegion,\r
- IStream_fnStat,\r
- IStream_fnClone\r
-};\r
-\r
-/* Methods overridden by the dummy stream */\r
-\r
-/**************************************************************************\r
- * IStream_fnAddRefDummy\r
- */\r
-static ULONG WINAPI IStream_fnAddRefDummy(IStream *iface)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
- TRACE("(%p)\n", This);\r
- return 2;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnReleaseDummy\r
- */\r
-static ULONG WINAPI IStream_fnReleaseDummy(IStream *iface)\r
-{\r
- ISHRegStream *This = (ISHRegStream *)iface;\r
- TRACE("(%p)\n", This);\r
- return 1;\r
-}\r
-\r
-/**************************************************************************\r
- * IStream_fnReadDummy\r
- */\r
-static HRESULT WINAPI IStream_fnReadDummy(IStream *iface, LPVOID pv, ULONG cb, ULONG* pcbRead)\r
-{\r
- if (pcbRead)\r
- *pcbRead = 0;\r
- return E_NOTIMPL;\r
-}\r
-\r
-static struct IStreamVtbl DummyRegStreamVTable =\r
-{\r
- IStream_fnQueryInterface,\r
- IStream_fnAddRefDummy, /* Overridden */\r
- IStream_fnReleaseDummy, /* Overridden */\r
- IStream_fnReadDummy, /* Overridden */\r
- IStream_fnWrite,\r
- IStream_fnSeek,\r
- IStream_fnSetSize,\r
- IStream_fnCopyTo,\r
- IStream_fnCommit,\r
- IStream_fnRevert,\r
- IStream_fnLockUnlockRegion,\r
- IStream_fnLockUnlockRegion,\r
- IStream_fnStat,\r
- IStream_fnClone\r
-};\r
-\r
-/* Dummy registry stream object */\r
-static ISHRegStream rsDummyRegStream =\r
-{\r
- &DummyRegStreamVTable,\r
- 1,\r
- NULL,\r
- NULL,\r
- 0,\r
- 0\r
-};\r
-\r
-/**************************************************************************\r
- * IStream_Create\r
- *\r
- * Internal helper: Create and initialise a new registry stream object.\r
- */\r
-static IStream *IStream_Create(HKEY hKey, LPBYTE pbBuffer, DWORD dwLength)\r
-{\r
- ISHRegStream* regStream;\r
-\r
- regStream = (ISHRegStream*)HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream));\r
-\r
- if (regStream)\r
- {\r
- regStream->lpVtbl = &rstvt;\r
- regStream->ref = 1;\r
- regStream->hKey = hKey;\r
- regStream->pbBuffer = pbBuffer;\r
- regStream->dwLength = dwLength;\r
- regStream->dwPos = 0;\r
- }\r
- TRACE ("Returning %p\n", regStream);\r
- return (IStream *)regStream;\r
-}\r
-\r
-/*************************************************************************\r
- * SHOpenRegStream2A [SHLWAPI.@]\r
- *\r
- * Create a stream to read binary registry data.\r
- *\r
- * PARAMS\r
- * hKey [I] Registry handle\r
- * pszSubkey [I] The sub key name\r
- * pszValue [I] The value name under the sub key\r
- * dwMode [I] Unused\r
- *\r
- * RETURNS\r
- * Success: An IStream interface referring to the registry data\r
- * Failure: NULL, if the registry key could not be opened or is not binary.\r
- */\r
-IStream * WINAPI SHOpenRegStream2A(HKEY hKey, LPCSTR pszSubkey,\r
- LPCSTR pszValue,DWORD dwMode)\r
-{\r
- HKEY hStrKey = NULL;\r
- LPBYTE lpBuff = NULL;\r
- DWORD dwLength, dwType;\r
-\r
- TRACE("(%p,%s,%s,0x%08lx)\n", hKey, pszSubkey, pszValue, dwMode);\r
-\r
- /* Open the key, read in binary data and create stream */\r
- if (!RegOpenKeyExA (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&\r
- !RegQueryValueExA (hStrKey, pszValue, 0, 0, 0, &dwLength) &&\r
- (lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&\r
- !RegQueryValueExA (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&\r
- dwType == REG_BINARY)\r
- return IStream_Create(hStrKey, lpBuff, dwLength);\r
-\r
- HeapFree (GetProcessHeap(), 0, lpBuff);\r
- if (hStrKey)\r
- RegCloseKey(hStrKey);\r
- return NULL;\r
-}\r
-\r
-/*************************************************************************\r
- * SHOpenRegStream2W [SHLWAPI.@]\r
- *\r
- * See SHOpenRegStream2A.\r
- */\r
-IStream * WINAPI SHOpenRegStream2W(HKEY hKey, LPCWSTR pszSubkey,\r
- LPCWSTR pszValue, DWORD dwMode)\r
-{\r
- HKEY hStrKey = NULL;\r
- LPBYTE lpBuff = NULL;\r
- DWORD dwLength, dwType;\r
-\r
- TRACE("(%p,%s,%s,0x%08lx)\n", hKey, debugstr_w(pszSubkey),\r
- debugstr_w(pszValue), dwMode);\r
-\r
- /* Open the key, read in binary data and create stream */\r
- if (!RegOpenKeyExW (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&\r
- !RegQueryValueExW (hStrKey, pszValue, 0, 0, 0, &dwLength) &&\r
- (lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&\r
- !RegQueryValueExW (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&\r
- dwType == REG_BINARY)\r
- return IStream_Create(hStrKey, lpBuff, dwLength);\r
-\r
- HeapFree (GetProcessHeap(), 0, lpBuff);\r
- if (hStrKey)\r
- RegCloseKey(hStrKey);\r
- return NULL;\r
-}\r
-\r
-/*************************************************************************\r
- * SHOpenRegStreamA [SHLWAPI.@]\r
- *\r
- * Create a stream to read binary registry data.\r
- *\r
- * PARAMS\r
- * hKey [I] Registry handle\r
- * pszSubkey [I] The sub key name\r
- * pszValue [I] The value name under the sub key\r
- * dwMode [I] STGM mode for opening the file\r
- *\r
- * RETURNS\r
- * Success: An IStream interface referring to the registry data\r
- * Failure: If the registry key could not be opened or is not binary,\r
- * A dummy (empty) IStream object is returned.\r
- */\r
-IStream * WINAPI SHOpenRegStreamA(HKEY hkey, LPCSTR pszSubkey,\r
- LPCSTR pszValue, DWORD dwMode)\r
-{\r
- IStream *iStream;\r
-\r
- TRACE("(%p,%s,%s,0x%08lx)\n", hkey, pszSubkey, pszValue, dwMode);\r
-\r
- iStream = SHOpenRegStream2A(hkey, pszSubkey, pszValue, dwMode);\r
- return iStream ? iStream : (IStream *)&rsDummyRegStream;\r
-}\r
-\r
-/*************************************************************************\r
- * SHOpenRegStreamW [SHLWAPI.@]\r
- *\r
- * See SHOpenRegStreamA.\r
- */\r
-IStream * WINAPI SHOpenRegStreamW(HKEY hkey, LPCWSTR pszSubkey,\r
- LPCWSTR pszValue, DWORD dwMode)\r
-{\r
- IStream *iStream;\r
-\r
- TRACE("(%p,%s,%s,0x%08lx)\n", hkey, debugstr_w(pszSubkey),\r
- debugstr_w(pszValue), dwMode);\r
- iStream = SHOpenRegStream2W(hkey, pszSubkey, pszValue, dwMode);\r
- return iStream ? iStream : (IStream *)&rsDummyRegStream;\r
-}\r
-\r
-/*************************************************************************\r
- * @ [SHLWAPI.12]\r
- *\r
- * Create an IStream object on a block of memory.\r
- *\r
- * PARAMS\r
- * lpbData [I] Memory block to create the IStream object on\r
- * dwDataLen [I] Length of data block\r
- *\r
- * RETURNS\r
- * Success: A pointer to the IStream object.\r
- * Failure: NULL, if any parameters are invalid or an error occurs.\r
- *\r
- * NOTES\r
- * A copy of the memory pointed to by lpbData is made, and is freed\r
- * when the stream is released.\r
- */\r
-IStream * WINAPI SHCreateMemStream(LPBYTE lpbData, DWORD dwDataLen)\r
-{\r
- IStream *iStrmRet = NULL;\r
-\r
- TRACE("(%p,%ld)\n", lpbData, dwDataLen);\r
-\r
- if (lpbData)\r
- {\r
- LPBYTE lpbDup = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwDataLen);\r
-\r
- if (lpbDup)\r
- {\r
- memcpy(lpbDup, lpbData, dwDataLen);\r
- iStrmRet = IStream_Create(NULL, lpbDup, dwDataLen);\r
-\r
- if (!iStrmRet)\r
- HeapFree(GetProcessHeap(), 0, lpbDup);\r
- }\r
- }\r
- return iStrmRet;\r
-}\r
-\r
-/*************************************************************************\r
- * SHCreateStreamWrapper [SHLWAPI.@]\r
- *\r
- * Create an IStream object on a block of memory.\r
- *\r
- * PARAMS\r
- * lpbData [I] Memory block to create the IStream object on\r
- * dwDataLen [I] Length of data block\r
- * dwReserved [I] Reserved, Must be 0.\r
- * lppStream [O] Destination for IStream object\r
- *\r
- * RETURNS\r
- * Success: S_OK. lppStream contains the new IStream object.\r
- * Failure: E_INVALIDARG, if any parameters are invalid,\r
- * E_OUTOFMEMORY if memory allocation fails.\r
- *\r
- * NOTES\r
- * The stream assumes ownership of the memory passed to it.\r
- */\r
-HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,\r
- DWORD dwReserved, IStream **lppStream)\r
-{\r
- IStream* lpStream;\r
-\r
- if (lppStream)\r
- *lppStream = NULL;\r
-\r
- if(dwReserved || !lppStream)\r
- return E_INVALIDARG;\r
-\r
- lpStream = IStream_Create(NULL, lpbData, dwDataLen);\r
-\r
- if(!lpStream)\r
- return E_OUTOFMEMORY;\r
-\r
- IStream_QueryInterface(lpStream, &IID_IStream, (void**)lppStream);\r
- IStream_Release(lpStream);\r
- return S_OK;\r
-}\r
+/*
+ * SHLWAPI Registry Stream functions
+ *
+ * Copyright 1999 Juergen Schmied
+ * Copyright 2002 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include <string.h>
+
+#define COBJMACROS
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "winreg.h"
+#include "shlwapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+typedef struct
+{
+ const IStreamVtbl *lpVtbl;
+ LONG ref;
+ HKEY hKey;
+ LPBYTE pbBuffer;
+ DWORD dwLength;
+ DWORD dwPos;
+} ISHRegStream;
+
+/**************************************************************************
+* IStream_fnQueryInterface
+*/
+static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
+
+ *ppvObj = NULL;
+
+ if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
+ *ppvObj = This;
+ else if(IsEqualIID(riid, &IID_IStream)) /*IStream*/
+ *ppvObj = This;
+
+ if(*ppvObj)
+ {
+ IStream_AddRef((IStream*)*ppvObj);
+ TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
+ return S_OK;
+ }
+ TRACE("-- Interface: E_NOINTERFACE\n");
+ return E_NOINTERFACE;
+}
+
+/**************************************************************************
+* IStream_fnAddRef
+*/
+static ULONG WINAPI IStream_fnAddRef(IStream *iface)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+ ULONG refCount = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n",This, refCount - 1);
+
+ return refCount;
+}
+
+/**************************************************************************
+* IStream_fnRelease
+*/
+static ULONG WINAPI IStream_fnRelease(IStream *iface)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+ ULONG refCount = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p)->(ref before=%lu)\n",This, refCount + 1);
+
+ if (!refCount)
+ {
+ TRACE(" destroying SHReg IStream (%p)\n",This);
+
+ HeapFree(GetProcessHeap(),0,This->pbBuffer);
+
+ if (This->hKey)
+ RegCloseKey(This->hKey);
+
+ HeapFree(GetProcessHeap(),0,This);
+ return 0;
+ }
+
+ return refCount;
+}
+
+/**************************************************************************
+ * IStream_fnRead
+ */
+static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ DWORD dwBytesToRead, dwBytesLeft;
+
+ TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
+
+ if (!pv)
+ return STG_E_INVALIDPOINTER;
+
+ dwBytesLeft = This->dwLength - This->dwPos;
+
+ if ( 0 >= dwBytesLeft ) /* end of buffer */
+ return S_FALSE;
+
+ dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;
+
+ memmove ( pv, (This->pbBuffer) + (This->dwPos), dwBytesToRead);
+
+ This->dwPos += dwBytesToRead; /* adjust pointer */
+
+ if (pcbRead)
+ *pcbRead = dwBytesToRead;
+
+ return S_OK;
+}
+
+/**************************************************************************
+ * IStream_fnWrite
+ */
+static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ if (pcbWritten)
+ *pcbWritten = 0;
+
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnSeek
+ */
+static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ if (plibNewPosition)
+ plibNewPosition->QuadPart = 0;
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnSetSize
+ */
+static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnCopyTo
+ */
+static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+ if (pcbRead)
+ pcbRead->QuadPart = 0;
+ if (pcbWritten)
+ pcbWritten->QuadPart = 0;
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnCommit
+ */
+static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnRevert
+ */
+static HRESULT WINAPI IStream_fnRevert (IStream * iface)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ return E_NOTIMPL;
+}
+
+/**************************************************************************
+ * IStream_fnLockUnlockRegion
+ */
+static HRESULT WINAPI IStream_fnLockUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ return E_NOTIMPL;
+}
+
+/*************************************************************************
+ * IStream_fnStat
+ */
+static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+
+ return E_NOTIMPL;
+}
+
+/*************************************************************************
+ * IStream_fnClone
+ */
+static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+
+ TRACE("(%p)\n",This);
+ if (ppstm)
+ *ppstm = NULL;
+ return E_NOTIMPL;
+}
+
+static const IStreamVtbl rstvt =
+{
+ IStream_fnQueryInterface,
+ IStream_fnAddRef,
+ IStream_fnRelease,
+ IStream_fnRead,
+ IStream_fnWrite,
+ IStream_fnSeek,
+ IStream_fnSetSize,
+ IStream_fnCopyTo,
+ IStream_fnCommit,
+ IStream_fnRevert,
+ IStream_fnLockUnlockRegion,
+ IStream_fnLockUnlockRegion,
+ IStream_fnStat,
+ IStream_fnClone
+};
+
+/* Methods overridden by the dummy stream */
+
+/**************************************************************************
+ * IStream_fnAddRefDummy
+ */
+static ULONG WINAPI IStream_fnAddRefDummy(IStream *iface)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+ TRACE("(%p)\n", This);
+ return 2;
+}
+
+/**************************************************************************
+ * IStream_fnReleaseDummy
+ */
+static ULONG WINAPI IStream_fnReleaseDummy(IStream *iface)
+{
+ ISHRegStream *This = (ISHRegStream *)iface;
+ TRACE("(%p)\n", This);
+ return 1;
+}
+
+/**************************************************************************
+ * IStream_fnReadDummy
+ */
+static HRESULT WINAPI IStream_fnReadDummy(IStream *iface, LPVOID pv, ULONG cb, ULONG* pcbRead)
+{
+ if (pcbRead)
+ *pcbRead = 0;
+ return E_NOTIMPL;
+}
+
+static const IStreamVtbl DummyRegStreamVTable =
+{
+ IStream_fnQueryInterface,
+ IStream_fnAddRefDummy, /* Overridden */
+ IStream_fnReleaseDummy, /* Overridden */
+ IStream_fnReadDummy, /* Overridden */
+ IStream_fnWrite,
+ IStream_fnSeek,
+ IStream_fnSetSize,
+ IStream_fnCopyTo,
+ IStream_fnCommit,
+ IStream_fnRevert,
+ IStream_fnLockUnlockRegion,
+ IStream_fnLockUnlockRegion,
+ IStream_fnStat,
+ IStream_fnClone
+};
+
+/* Dummy registry stream object */
+static ISHRegStream rsDummyRegStream =
+{
+ &DummyRegStreamVTable,
+ 1,
+ NULL,
+ NULL,
+ 0,
+ 0
+};
+
+/**************************************************************************
+ * IStream_Create
+ *
+ * Internal helper: Create and initialise a new registry stream object.
+ */
+static IStream *IStream_Create(HKEY hKey, LPBYTE pbBuffer, DWORD dwLength)
+{
+ ISHRegStream* regStream;
+
+ regStream = HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream));
+
+ if (regStream)
+ {
+ regStream->lpVtbl = &rstvt;
+ regStream->ref = 1;
+ regStream->hKey = hKey;
+ regStream->pbBuffer = pbBuffer;
+ regStream->dwLength = dwLength;
+ regStream->dwPos = 0;
+ }
+ TRACE ("Returning %p\n", regStream);
+ return (IStream *)regStream;
+}
+
+/*************************************************************************
+ * SHOpenRegStream2A [SHLWAPI.@]
+ *
+ * Create a stream to read binary registry data.
+ *
+ * PARAMS
+ * hKey [I] Registry handle
+ * pszSubkey [I] The sub key name
+ * pszValue [I] The value name under the sub key
+ * dwMode [I] Unused
+ *
+ * RETURNS
+ * Success: An IStream interface referring to the registry data
+ * Failure: NULL, if the registry key could not be opened or is not binary.
+ */
+IStream * WINAPI SHOpenRegStream2A(HKEY hKey, LPCSTR pszSubkey,
+ LPCSTR pszValue,DWORD dwMode)
+{
+ HKEY hStrKey = NULL;
+ LPBYTE lpBuff = NULL;
+ DWORD dwLength, dwType;
+
+ TRACE("(%p,%s,%s,0x%08lx)\n", hKey, pszSubkey, pszValue, dwMode);
+
+ /* Open the key, read in binary data and create stream */
+ if (!RegOpenKeyExA (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&
+ !RegQueryValueExA (hStrKey, pszValue, 0, 0, 0, &dwLength) &&
+ (lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&
+ !RegQueryValueExA (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&
+ dwType == REG_BINARY)
+ return IStream_Create(hStrKey, lpBuff, dwLength);
+
+ HeapFree (GetProcessHeap(), 0, lpBuff);
+ if (hStrKey)
+ RegCloseKey(hStrKey);
+ return NULL;
+}
+
+/*************************************************************************
+ * SHOpenRegStream2W [SHLWAPI.@]
+ *
+ * See SHOpenRegStream2A.
+ */
+IStream * WINAPI SHOpenRegStream2W(HKEY hKey, LPCWSTR pszSubkey,
+ LPCWSTR pszValue, DWORD dwMode)
+{
+ HKEY hStrKey = NULL;
+ LPBYTE lpBuff = NULL;
+ DWORD dwLength, dwType;
+
+ TRACE("(%p,%s,%s,0x%08lx)\n", hKey, debugstr_w(pszSubkey),
+ debugstr_w(pszValue), dwMode);
+
+ /* Open the key, read in binary data and create stream */
+ if (!RegOpenKeyExW (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&
+ !RegQueryValueExW (hStrKey, pszValue, 0, 0, 0, &dwLength) &&
+ (lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&
+ !RegQueryValueExW (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&
+ dwType == REG_BINARY)
+ return IStream_Create(hStrKey, lpBuff, dwLength);
+
+ HeapFree (GetProcessHeap(), 0, lpBuff);
+ if (hStrKey)
+ RegCloseKey(hStrKey);
+ return NULL;
+}
+
+/*************************************************************************
+ * SHOpenRegStreamA [SHLWAPI.@]
+ *
+ * Create a stream to read binary registry data.
+ *
+ * PARAMS
+ * hKey [I] Registry handle
+ * pszSubkey [I] The sub key name
+ * pszValue [I] The value name under the sub key
+ * dwMode [I] STGM mode for opening the file
+ *
+ * RETURNS
+ * Success: An IStream interface referring to the registry data
+ * Failure: If the registry key could not be opened or is not binary,
+ * A dummy (empty) IStream object is returned.
+ */
+IStream * WINAPI SHOpenRegStreamA(HKEY hkey, LPCSTR pszSubkey,
+ LPCSTR pszValue, DWORD dwMode)
+{
+ IStream *iStream;
+
+ TRACE("(%p,%s,%s,0x%08lx)\n", hkey, pszSubkey, pszValue, dwMode);
+
+ iStream = SHOpenRegStream2A(hkey, pszSubkey, pszValue, dwMode);
+ return iStream ? iStream : (IStream *)&rsDummyRegStream;
+}
+
+/*************************************************************************
+ * SHOpenRegStreamW [SHLWAPI.@]
+ *
+ * See SHOpenRegStreamA.
+ */
+IStream * WINAPI SHOpenRegStreamW(HKEY hkey, LPCWSTR pszSubkey,
+ LPCWSTR pszValue, DWORD dwMode)
+{
+ IStream *iStream;
+
+ TRACE("(%p,%s,%s,0x%08lx)\n", hkey, debugstr_w(pszSubkey),
+ debugstr_w(pszValue), dwMode);
+ iStream = SHOpenRegStream2W(hkey, pszSubkey, pszValue, dwMode);
+ return iStream ? iStream : (IStream *)&rsDummyRegStream;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.12]
+ *
+ * Create an IStream object on a block of memory.
+ *
+ * PARAMS
+ * lpbData [I] Memory block to create the IStream object on
+ * dwDataLen [I] Length of data block
+ *
+ * RETURNS
+ * Success: A pointer to the IStream object.
+ * Failure: NULL, if any parameters are invalid or an error occurs.
+ *
+ * NOTES
+ * A copy of the memory pointed to by lpbData is made, and is freed
+ * when the stream is released.
+ */
+IStream * WINAPI SHCreateMemStream(LPBYTE lpbData, DWORD dwDataLen)
+{
+ IStream *iStrmRet = NULL;
+
+ TRACE("(%p,%ld)\n", lpbData, dwDataLen);
+
+ if (lpbData)
+ {
+ LPBYTE lpbDup = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
+
+ if (lpbDup)
+ {
+ memcpy(lpbDup, lpbData, dwDataLen);
+ iStrmRet = IStream_Create(NULL, lpbDup, dwDataLen);
+
+ if (!iStrmRet)
+ HeapFree(GetProcessHeap(), 0, lpbDup);
+ }
+ }
+ return iStrmRet;
+}
+
+/*************************************************************************
+ * SHCreateStreamWrapper [SHLWAPI.@]
+ *
+ * Create an IStream object on a block of memory.
+ *
+ * PARAMS
+ * lpbData [I] Memory block to create the IStream object on
+ * dwDataLen [I] Length of data block
+ * dwReserved [I] Reserved, Must be 0.
+ * lppStream [O] Destination for IStream object
+ *
+ * RETURNS
+ * Success: S_OK. lppStream contains the new IStream object.
+ * Failure: E_INVALIDARG, if any parameters are invalid,
+ * E_OUTOFMEMORY if memory allocation fails.
+ *
+ * NOTES
+ * The stream assumes ownership of the memory passed to it.
+ */
+HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,
+ DWORD dwReserved, IStream **lppStream)
+{
+ IStream* lpStream;
+
+ if (lppStream)
+ *lppStream = NULL;
+
+ if(dwReserved || !lppStream)
+ return E_INVALIDARG;
+
+ lpStream = IStream_Create(NULL, lpbData, dwDataLen);
+
+ if(!lpStream)
+ return E_OUTOFMEMORY;
+
+ IStream_QueryInterface(lpStream, &IID_IStream, (void**)lppStream);
+ IStream_Release(lpStream);
+ return S_OK;
+}