Sync to Wine-0_9_4:
[reactos.git] / reactos / lib / shlwapi / regstream.c
index 172e1bb..b0f7117 100644 (file)
-/*\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;
+}