shlwapi: Implement SHGetShellKey

Samuel Lidén Borell samuellb at bredband.net
Wed Aug 9 15:57:53 CDT 2006


This patch implements SHGetShellKey. It's used by
SKAlloc/Delete/Get/SetValueW which I'm implementing and testing right now.

The function is documented here:
http://members.ozemail.com.au/~geoffch/samples/win32/shell/shlwapi/functions/shellkey/getkey.htm

I've made a simple GUI to test this function (as well as
SKAlloc/GetValueW), and tested it on WinXP SP2.
http://hem.bredband.net/lidsam/shellkeys.tar.bz2

---

 dlls/shlwapi/ordinal.c    |  167
++++++++++++++++++++++++++++++++++++++++++++-
 dlls/shlwapi/shlwapi.spec |    2 -
 2 files changed, 163 insertions(+), 6 deletions(-)

ffceaabd6babadf89075199de2cce1c779eb6d7d
diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 669cff0..e4cfea6 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -4306,13 +4306,170 @@ BOOL WINAPI SHSkipJunction(IBindCtx *pbc
   return bRet;
 }
 
-/***********************************************************************
- *        SHGetShellKey (SHLWAPI.@)
+/*************************************************************************
+ * SHGetShellKey   [SHLWAPI.491]
+ *
+ * This function creates a HKEY from an Shell-related registry key
+ * (SHELLKEY). This function is said to cache the keys on native Windows
+ * somehow, but we don't do that yet. The caching is NOT vital since the
+ * function always returns a new HKEY each time (on WinXP SP2).
+ *
+ * Geoff Chappell has documented this function here:
+ *
http://members.ozemail.com.au/~geoffch/samples/win32/shell/shlwapi/functions/shellkey/getkey.htm
+ *
+ * PARAMS
+ *   nShellKey  [I] Combination of a root key, key and subkey. See below
+ *   pszSubKey  [I] Optional name of a sub key
+ *   bCreate    [I] Whether the key should be created if non-existant
+ *
+ * Known nShellKey combinations:
+ * Mask          Value          Interpretation
+ * 0x0000000F (root)     0x00000001     HKEY_CURRENT_USER
+ *             0x00000002     HKEY_LOCAL_MACHINE
+ * 0x00000FF0 (key)     0x00000000    
Software\Microsoft\Windows\CurrentVersion\Explorer
+ *             0x00000010     Software\Microsoft\Windows\Shell
+ *             0x00000020     Software\Microsoft\Windows\ShellNoRoam
+ *             0x00000030     Software\Classes
+ * 0x000FF000 (subkey)     0x00000000     (no subkey)
+ *             0x00001000     LocalizedResourceName
+ *             0x00002000     Handlers
+ *             0x00003000     Associations
+ *             0x00004000     Volatile
+ *             0x00005000     MUICache
+ *             0x00006000     FileExts
+ *
+ * RETURNS
+ *   Success: The registry key.
+ *   Failure: NULL, error value can be retrived using GetLastError
+ *            The error value is E_INVALIDARG when an invalid nShellKey
+ *            is used. If the key does not exist and bCreate is false,
+ *            then the error value becomes ERROR_FILE_NOT_FOUND.
  */
-DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
+HKEY WINAPI SHGetShellKey(DWORD nShellKey, LPCWSTR pszSubKey, BOOL bCreate)
 {
-    FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
-    return 0x50;
+  /* Keys */
+  static const WCHAR SK_KEY_EXPLORER[] = {
+    'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f',
+    't','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t',
+    'V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\0'
+  };
+  static const WCHAR SK_KEY_SHELL[] = {
+    'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f',
+    't','\\','W','i','n','d','o','w','s','\\','S','h','e','l','l','\0'
+  };
+  static const WCHAR SK_KEY_SHELLNOROAM[] = {
+    'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f',
+    't','\\','W','i','n','d','o','w','s','\\','S','h','e','l','l','N','o',
+    'R','o','a','m','\0'
+  };
+  static const WCHAR SK_KEY_CLASSES[] = {
+    'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\0'
+  };
+  static const WCHAR *SK_KEYS[] = {
+    SK_KEY_EXPLORER,
+    SK_KEY_SHELL,
+    SK_KEY_SHELLNOROAM,
+    SK_KEY_CLASSES
+  };
+  /* Subkeys */
+  static const WCHAR SK_SUBKEY_NONE[] = {
+    '\0'
+  };
+  static const WCHAR SK_SUBKEY_RESNAME[] = {
+   
'\\','L','o','c','a','l','i','z','e','d','R','e','s','o','u','r','c','e',
+    'N','a','m','e','\0'
+  };
+  static const WCHAR SK_SUBKEY_HANDLERS[] = {
+    '\\','H','a','n','d','l','e','r','s','\0'
+  };
+  static const WCHAR SK_SUBKEY_ASSOCIATIONS[] = {
+    '\\','A','s','s','o','c','i','a','t','i','o','n','s','\0'
+  };
+  static const WCHAR SK_SUBKEY_VOLATILE[] = {
+    '\\','V','o','l','a','t','i','l','e','\0'
+  };
+  static const WCHAR SK_SUBKEY_MUICACHE[] = {
+    '\\','M','U','I','C','a','c','h','e','\0'
+  };
+  static const WCHAR SK_SUBKEY_FILEEXTS[] = {
+    '\\','F','i','l','e','E','x','t','s','\0'
+  };
+  static const WCHAR *SK_SUBKEYS[] = {
+    SK_SUBKEY_NONE,
+    SK_SUBKEY_RESNAME,
+    SK_SUBKEY_HANDLERS,
+    SK_SUBKEY_ASSOCIATIONS,
+    SK_SUBKEY_VOLATILE,
+    SK_SUBKEY_MUICACHE,
+    SK_SUBKEY_FILEEXTS
+  };
+
+  HKEY hRootKey = 0;
+  HKEY hKey = 0;
+  HKEY hFinalKey = 0;
+  DWORD dwDummy, dwRet;
+ 
+  /* Longest possible key + NULL:
+    
Software\Microsoft\Windows\CurrentVersion\Explorer\LocalizedResourceName */
+  WCHAR subkey[73];
+ 
+  TRACE("(%lx, %s, %s)\n", nShellKey, debugstr_w(pszSubKey), bCreate ?
"TRUE" : "FALSE");
+ 
+  /* Root key */
+  if ((nShellKey & 0x0000000F) == 0x00000001)
+    hRootKey = HKEY_CURRENT_USER;
+  else if ((nShellKey & 0x0000000F) == 0x00000002)
+    hRootKey = HKEY_LOCAL_MACHINE;
+  else
+  {
+    FIXME("Unknown root key: %lx. Falling back to HKCU\n", (nShellKey &
0x0000000F));
+    hRootKey = HKEY_CURRENT_USER;
+  }
+
+  /* Check for invalid values */
+  if (((nShellKey & 0x00000FF0) > 0x00000030) ||
+      ((nShellKey & 0x000FF000) > 0x00006000))
+  {
+    FIXME("Unsupported nShellKey %lx\n", nShellKey);
+    SetLastError(E_INVALIDARG);
+    return NULL;
+  }
+ 
+  /* Create subkey string */
+  lstrcpyW((WCHAR*)&subkey, SK_KEYS[(nShellKey & 0x00000FF0) >> 4]);
+  lstrcatW((WCHAR*)&subkey, SK_SUBKEYS[(nShellKey & 0x000FF000) >> 12]);
+ 
+  if (!bCreate)
+    dwRet = RegOpenKeyExW(hRootKey, subkey, 0, KEY_ALL_ACCESS, &hKey);
+  else
+    dwRet = RegCreateKeyExW(hRootKey, subkey, 0, NULL, 0,
+                            KEY_ALL_ACCESS, NULL, &hKey, &dwDummy);
+  if (dwRet)
+  {
+    SetLastError(ERROR_FILE_NOT_FOUND);
+    return NULL;
+  }
+  if ((!pszSubKey) || (*pszSubKey == '\0'))
+  {
+    SetLastError(ERROR_SUCCESS);
+    return hKey;
+  }
+ 
+  /* Open pszSubKey */
+  if (!bCreate)
+    dwRet = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_ALL_ACCESS, &hFinalKey);
+  else
+    dwRet = RegCreateKeyExW(hKey, pszSubKey, 0, NULL, 0,
+                            KEY_ALL_ACCESS, NULL, &hFinalKey, &dwDummy);
+  RegCloseKey(hKey);
+  if (dwRet)
+  {
+    SetLastError(ERROR_FILE_NOT_FOUND);
+    return NULL;
+  }
+ 
+  SetLastError(ERROR_SUCCESS);
+  return hFinalKey;
 }
 
 /***********************************************************************
diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec
index 0295e1b..ae42e85 100644
--- a/dlls/shlwapi/shlwapi.spec
+++ b/dlls/shlwapi/shlwapi.spec
@@ -488,7 +488,7 @@
 488 stub -noname SHConvertGraphicsFile
 489 stub -noname GlobalAddAtomWrapW
 490 stub -noname GlobalFindAtomWrapW
-491 stdcall -noname SHGetShellKey(long long long)
+491 stdcall -noname SHGetShellKey(long wstr long)
 492 stub -noname PrettifyFileDescriptionW
 493 stub -noname SHPropertyBag_ReadType
 494 stub -noname SHPropertyBag_ReadStr
-- 
1.2.4



More information about the wine-patches mailing list