- Implement HUSKEY design.
- Implement functions: SHRegOpenUSKey{A|W}, SHRegCloseUSKey,
  SHRegGetUSValue{A|W}, SHRegQueryInfoUSKey{A|W}

diff --git a/dlls/shlwapi/reg.c b/dlls/shlwapi/reg.c
index 429109c..483bee0 100644
--- a/dlls/shlwapi/reg.c
+++ b/dlls/shlwapi/reg.c
@@ -8,6 +8,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "winerror.h"
+#include "winnls.h"
 #include "winreg.h"
 #include "debugtools.h"
 #include "shlwapi.h"
@@ -18,6 +19,143 @@
 static const char *lpszContentTypeA = "Content Type";
 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
 
+/* internal structure of what the HUSKEY points to */
+typedef struct {
+    HKEY     realkey;                  /* HKEY of opened key */
+    HKEY     start;                    /* HKEY of where to start */
+    WCHAR    key_string[MAX_PATH];     /* additional path from 'start' */
+} Internal_HUSKEY, *LPInternal_HUSKEY;
+
+
+/*************************************************************************
+ * SHRegOpenUSKeyA	[SHLWAPI.@]
+ *
+ * Opens a user-specific registry key
+ */
+LONG WINAPI SHRegOpenUSKeyA(
+        LPCSTR Path,
+        REGSAM AccessType,
+        HUSKEY hRelativeUSKey,
+        PHUSKEY phNewUSKey,
+        BOOL fIgnoreHKCU)
+{
+    HKEY startpoint, openkey;
+    LONG ret = ~ERROR_SUCCESS;
+    LPInternal_HUSKEY ihky;
+
+    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path), 
+	  (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey, 
+	  (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
+    if (hRelativeUSKey)
+	startpoint = ((LPInternal_HUSKEY)hRelativeUSKey)->realkey;
+    else {
+	startpoint = HKEY_LOCAL_MACHINE;
+	if (!fIgnoreHKCU) {
+	    ret = RegOpenKeyExA(HKEY_CURRENT_USER, Path, 
+				0, AccessType, &openkey);
+	    /* if successful, then save real starting point */
+	    if (ret == ERROR_SUCCESS)
+		startpoint = HKEY_CURRENT_USER;
+	}
+    }
+
+    /* if current_user didn't have it, or have relative start point,
+     * try it.
+     */
+    if (ret != ERROR_SUCCESS)
+	ret = RegOpenKeyExA(startpoint, Path, 0, AccessType, &openkey);
+
+    /* if all attempts have failed then bail */
+    if (ret != ERROR_SUCCESS) {
+	TRACE("failed %ld\n", ret);
+	return ret;
+    }
+
+    /* now create the internal version of HUSKEY */
+    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 , 
+					sizeof(Internal_HUSKEY));
+    ihky->realkey = openkey;
+    ihky->start = startpoint;
+    MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
+			sizeof(ihky->key_string)-1);
+    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
+    if (phNewUSKey)
+	*phNewUSKey = (HUSKEY)ihky;
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegOpenUSKeyW	[SHLWAPI.@]
+ *
+ * Opens a user-specific registry key
+ */
+LONG WINAPI SHRegOpenUSKeyW(
+        LPCWSTR Path,
+        REGSAM AccessType,
+        HUSKEY hRelativeUSKey,
+        PHUSKEY phNewUSKey,
+        BOOL fIgnoreHKCU)
+{
+    HKEY startpoint, openkey;
+    LONG ret = ~ERROR_SUCCESS;
+    LPInternal_HUSKEY ihky;
+
+    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path), 
+	  (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey, 
+	  (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
+    if (hRelativeUSKey)
+	startpoint = ((LPInternal_HUSKEY)hRelativeUSKey)->realkey;
+    else {
+	startpoint = HKEY_LOCAL_MACHINE;
+	if (!fIgnoreHKCU) {
+	    ret = RegOpenKeyExW(HKEY_CURRENT_USER, Path, 
+				0, AccessType, &openkey);
+	    /* if successful, then save real starting point */
+	    if (ret == ERROR_SUCCESS)
+		startpoint = HKEY_CURRENT_USER;
+	}
+    }
+
+    /* if current_user didn't have it, or have relative start point,
+     * try it.
+     */
+    if (ret != ERROR_SUCCESS)
+	ret = RegOpenKeyExW(startpoint, Path, 0, AccessType, &openkey);
+
+    /* if all attempts have failed then bail */
+    if (ret != ERROR_SUCCESS) {
+	TRACE("failed %ld\n", ret);
+	return ret;
+    }
+
+    /* now create the internal version of HUSKEY */
+    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 , 
+					sizeof(Internal_HUSKEY));
+    ihky->realkey = openkey;
+    ihky->start = startpoint;
+    lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
+    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
+    if (phNewUSKey)
+	*phNewUSKey = (HUSKEY)ihky;
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegCloseUSKey	[SHLWAPI.@]
+ *
+ * Closes a user-specific registry key
+ */
+LONG WINAPI SHRegCloseUSKey(
+        HUSKEY hUSKey)
+{
+    LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
+    LONG ret;
+
+    ret = RegCloseKey(mihk->realkey);
+    HeapFree(GetProcessHeap(), 0, mihk);
+    return ret;
+}
+
 /*************************************************************************
  * SHRegGetUSValueA	[SHLWAPI.@]
  *
@@ -28,13 +166,40 @@
 	LPCSTR   pValue,
 	LPDWORD  pwType,
 	LPVOID   pvData,
-	LPDWORD  pbData,
-	BOOL     fIgnoreHKCU,
+	LPDWORD  pcbData,
+	BOOL     flagIgnoreHKCU,
 	LPVOID   pDefaultData,
 	DWORD    wDefaultDataSize)
 {
-	FIXME("(%p),stub!\n", pSubKey);
-	return ERROR_SUCCESS;  /* return success */
+	HUSKEY myhuskey;
+	LPInternal_HUSKEY mihk;
+	LONG ret, maxmove, i;
+	CHAR *src, *dst;
+
+	if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
+	TRACE("key '%s', value '%s', datalen %ld,  %s\n",
+	      debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
+	      (flagIgnoreHKCU) ? "Ignoring HKCU" : "Trys HKCU then HKLM");
+
+	ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
+	if (ret == ERROR_SUCCESS) {
+	    mihk = (LPInternal_HUSKEY) myhuskey;
+	    ret = RegQueryValueExA(mihk->realkey, pValue, 0, pwType,
+				   (LPBYTE)pvData, pcbData);
+	    SHRegCloseUSKey(myhuskey);
+	}
+	if (ret != ERROR_SUCCESS) {
+	    if (pDefaultData && (wDefaultDataSize != 0)) {
+		maxmove = (wDefaultDataSize >= *pcbData) ? *pcbData : wDefaultDataSize;
+		src = (CHAR*)pDefaultData;
+		dst = (CHAR*)pvData;
+		for(i=0; i<maxmove; i++) *dst++ = *src++;
+		*pcbData = maxmove;
+		TRACE("setting default data\n");
+		ret = ERROR_SUCCESS;
+	    }
+	}
+	return ret;
 }
 
 /*************************************************************************
@@ -47,45 +212,40 @@
 	LPCWSTR  pValue,
 	LPDWORD  pwType,
 	LPVOID   pvData,
-	LPDWORD  pbData,
+	LPDWORD  pcbData,
 	BOOL     flagIgnoreHKCU,
 	LPVOID   pDefaultData,
 	DWORD    wDefaultDataSize)
 {
-	FIXME("(%p),stub!\n", pSubKey);
-	return ERROR_SUCCESS;  /* return success */
-}
+	HUSKEY myhuskey;
+	LPInternal_HUSKEY mihk;
+	LONG ret, maxmove, i;
+	CHAR *src, *dst;
 
-/*************************************************************************
- * SHRegOpenUSKeyA	[SHLWAPI.@]
- *
- * Opens a user-specific registry key
- */
-LONG WINAPI SHRegOpenUSKeyA(
-        LPCSTR Path,
-        REGSAM AccessType,
-        HKEY hRelativeUSKey,
-        HKEY hNewUSKey,
-        BOOL fIgnoreHKCU)
-{
-	FIXME("stub!\n");
-	return ERROR_SUCCESS;  /* return success */
-}
+	if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
+	TRACE("key '%s', value '%s', datalen %ld,  %s\n",
+	      debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
+	      (flagIgnoreHKCU) ? "Ignoring HKCU" : "Trys HKCU then HKLM");
 
-/*************************************************************************
- * SHRegOpenUSKeyW	[SHLWAPI.@]
- *
- * Openss a user-specific registry key
- */
-LONG WINAPI SHRegOpenUSKeyW(
-        LPCSTR Path,
-        REGSAM AccessType,
-        HKEY hRelativeUSKey,
-        HKEY hNewUSKey,
-        BOOL fIgnoreHKCU)
-{
-	FIXME("stub!\n");
-	return ERROR_SUCCESS;  /* return success */
+	ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
+	if (ret == ERROR_SUCCESS) {
+	    mihk = (LPInternal_HUSKEY) myhuskey;
+	    ret = RegQueryValueExW(mihk->realkey, pValue, 0, pwType,
+				   (LPBYTE)pvData, pcbData);
+	    SHRegCloseUSKey(myhuskey);
+	}
+	if (ret != ERROR_SUCCESS) {
+	    if (pDefaultData && (wDefaultDataSize != 0)) {
+		maxmove = (wDefaultDataSize >= *pcbData) ? *pcbData : wDefaultDataSize;
+		src = (CHAR*)pDefaultData;
+		dst = (CHAR*)pvData;
+		for(i=0; i<maxmove; i++) *dst++ = *src++;
+		*pcbData = maxmove;
+		TRACE("setting default data\n");
+		ret = ERROR_SUCCESS;
+	    }
+	}
+	return ret;
 }
 
 /*************************************************************************
@@ -118,7 +278,7 @@
  *      SHRegQueryUSValueA	[SHLWAPI.@]
  */
 LONG WINAPI SHRegQueryUSValueA(
-	HKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	HUSKEY hUSKey,             /* [in]  */
 	LPCSTR pszValue,
 	LPDWORD pdwType,
 	void *pvData,
@@ -135,7 +295,7 @@
  *      SHRegQueryUSValueW	[SHLWAPI.@]
  */
 LONG WINAPI SHRegQueryUSValueW(
-	HKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	HUSKEY hUSKey,             /* [in]  */
 	LPCSTR pszValue,
 	LPDWORD pdwType,
 	void *pvData,
@@ -149,14 +309,52 @@
 }
 
 /*************************************************************************
+ *      SHRegQueryInfoUSKeyA	[SHLWAPI.@]
+ */
+DWORD WINAPI SHRegQueryInfoUSKeyA(
+	HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	LPDWORD pcSubKeys,
+	LPDWORD pcchMaxSubKeyLen,
+	LPDWORD pcValues,
+	LPDWORD pcchMaxValueNameLen,
+	SHREGENUM_FLAGS enumRegFlags)
+{
+	TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
+	      (LONG)hUSKey, pcSubKeys, pcchMaxSubKeyLen, pcValues,
+	      pcchMaxValueNameLen, enumRegFlags);
+	return RegQueryInfoKeyA(((LPInternal_HUSKEY)hUSKey)->realkey, 0, 0, 0, 
+				pcSubKeys, pcchMaxSubKeyLen, 0,
+				pcValues, pcchMaxValueNameLen, 0, 0, 0);
+}
+
+/*************************************************************************
+ *      SHRegQueryInfoUSKeyW	[SHLWAPI.@]
+ */
+DWORD WINAPI SHRegQueryInfoUSKeyW(
+	HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	LPDWORD pcSubKeys,
+	LPDWORD pcchMaxSubKeyLen,
+	LPDWORD pcValues,
+	LPDWORD pcchMaxValueNameLen,
+	SHREGENUM_FLAGS enumRegFlags)
+{
+	TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
+	      (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
+	      pcchMaxValueNameLen,enumRegFlags);
+	return RegQueryInfoKeyW(((LPInternal_HUSKEY)hUSKey)->realkey, 0, 0, 0, 
+				pcSubKeys, pcchMaxSubKeyLen, 0,
+				pcValues, pcchMaxValueNameLen, 0, 0, 0);
+}
+
+/*************************************************************************
  *      SHRegEnumUSKeyA   	[SHLWAPI.@]
  */
 LONG WINAPI SHRegEnumUSKeyA(
-	HKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	HUSKEY hUSKey,                 /* [in]  */
 	DWORD dwIndex,
 	LPSTR pszName,
 	LPDWORD pcchValueNameLen,
-	DWORD enumRegFlags)      /* [in] FIXME: SHREGENUM_FLAGS */
+	SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
 {
 	FIXME("%s stub\n",debugstr_a(pszName));
 	return ERROR_NO_MORE_ITEMS;
@@ -166,11 +364,11 @@
  *      SHRegEnumUSKeyW   	[SHLWAPI.@]
  */
 LONG WINAPI SHRegEnumUSKeyW(
-	HKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	HUSKEY hUSKey,                 /* [in]  */
 	DWORD dwIndex,
 	LPWSTR pszName,
 	LPDWORD pcchValueNameLen,
-	DWORD enumRegFlags)      /* [in] FIXME: SHREGENUM_FLAGS */
+	SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
 {
 	FIXME("%s stub\n",debugstr_w(pszName));
 	return ERROR_NO_MORE_ITEMS;
diff --git a/include/shlwapi.h b/include/shlwapi.h
index 1de8c38..e403fb2 100644
--- a/include/shlwapi.h
+++ b/include/shlwapi.h
@@ -214,6 +214,9 @@
 HRESULT WINAPI StrRetToBufW(struct _STRRET *src, const struct _ITEMIDLIST *pidl, LPWSTR dest, DWORD len);
 #define StrRetToBuf WINELIB_NAME_AW(StrRetToBuf)
 
+
+/* Shell Registry interfaces */
+
 HRESULT WINAPI SHQueryValueExA(HKEY hkey, LPSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
 HRESULT WINAPI SHQueryValueExW(HKEY hkey, LPWSTR pszValue, LPDWORD pdwReserved, LPDWORD pdwType, LPVOID pvData, LPDWORD pcbData);
 #define SHQueryValueEx WINELIB_NAME_AW(SHQueryValueEx)
@@ -226,6 +229,26 @@
 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey);
 #define  SHDeleteEmptyKey WINELIB_NAME_AW(SHDeleteEmptyKey)
 
+
+typedef HANDLE HUSKEY;
+typedef HUSKEY *PHUSKEY;
+
+typedef enum {
+    SHREGDEL_DEFAULT = 0,   /* delete HKCU if found or HKLM if not */
+    SHREGDEL_HKCU = 0x01,   /* delete HKCU */
+    SHREGDEL_HKLM = 0x10,   /* delete HKLM */
+    SHREGDEL_BOTH = 0x11,   /* delete HKCU *and* HKLM */
+} SHREGDEL_FLAGS; 
+
+typedef enum {
+    SHREGENUM_DEFAULT = 0,  /* do HKCU or HKLM if not found */
+    SHREGENUM_HKCU = 0x01,  /* do HKCU only  */
+    SHREGENUM_HKLM = 0x10,  /* do HKLM only  */
+    SHREGENUM_BOTH = 0x11,  /* do both HKCU and HKLM without dups */
+} SHREGENUM_FLAGS; 
+
+
+
 HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized, 
 				LPDWORD pcchCanonicalized, DWORD dwFlags);
 HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,