Sync to Wine-20050725:
[reactos.git] / reactos / lib / shlwapi / reg.c
index f18409b..ccee4a8 100644 (file)
@@ -133,7 +133,7 @@ LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSK
         *phNewUSKey = NULL;
 
     /* Create internal HUSKEY */
-    hKey = (LPSHUSKEY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
+    hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
     lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath));
 
     if (hRelativeUSKey)
@@ -206,6 +206,150 @@ LONG WINAPI SHRegCloseUSKey(
     return ret;
 }
 
+/*************************************************************************
+ * SHRegCreateUSKeyA  [SHLWAPI.@]
+ *
+ * Create or open a user-specific registry key.
+ * 
+ * PARAMS
+ *  pszPath        [I] Key name to create or open.
+ *  samDesired     [I] Wanted security access.
+ *  hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
+ *  phNewUSKey     [O] Receives a handle to the new or openened key.
+ *  dwFlags        [I] Base key under which the key should be opened.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Nonzero error code from winerror.h
+ */
+LONG WINAPI SHRegCreateUSKeyA(LPCSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
+                              PHUSKEY phNewUSKey, DWORD dwFlags)
+{
+    FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_a(pszPath), samDesired,
+          hRelativeUSKey, phNewUSKey, dwFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegCreateUSKeyW  [SHLWAPI.@]
+ *
+ * See SHRegCreateUSKeyA.
+ */
+LONG WINAPI SHRegCreateUSKeyW(LPCWSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
+                              PHUSKEY phNewUSKey, DWORD dwFlags)
+{
+    FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_w(pszPath), samDesired,
+          hRelativeUSKey, phNewUSKey, dwFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegDeleteEmptyUSKeyA  [SHLWAPI.@]
+ *
+ * Delete an empty user-specific registry key.
+ *
+ * PARAMS
+ *  hUSKey      [I] Handle to an open registry key.
+ *  pszValue    [I] Empty key name.
+ *  delRegFlags [I] Flag that specifies the base from which to delete 
+ *                  the key.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Nonzero error code from winerror.h
+ */
+LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
+{
+    FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegDeleteEmptyUSKeyW  [SHLWAPI.@]
+ *
+ * See SHRegDeleteEmptyUSKeyA.
+ */
+LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
+{
+    FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegDeleteUSValueA  [SHLWAPI.@]
+ *
+ * Delete a user-specific registry value.
+ *
+ * PARAMS
+ *  hUSKey      [I] Handle to an open registry key.
+ *  pszValue    [I] Specifies the value to delete.
+ *  delRegFlags [I] Flag that specifies the base of the key from which to
+ *                  delete the value.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Nonzero error code from winerror.h
+ */
+LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
+{
+    FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegDeleteUSValueW  [SHLWAPI.@]
+ *
+ * See SHRegDeleteUSValueA.
+ */
+LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
+{
+    FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegEnumUSValueA  [SHLWAPI.@]
+ *
+ * Enumerate values of a specified registry key.
+ *
+ * PARAMS
+ *  hUSKey           [I]   Handle to an open registry key.
+ *  dwIndex          [I]   Index of the value to be retrieved.
+ *  pszValueName     [O]   Buffer to receive the value name.
+ *  pcchValueNameLen [I]   Size of pszValueName in characters.
+ *  pdwType          [O]   Receives data type of the value.
+ *  pvData           [O]   Receives value data. May be NULL.
+ *  pcbData          [I/O] Size of pvData in bytes.
+ *  enumRegFlags     [I]   Flag that specifies the base key under which to
+ *                         enumerate values.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: Nonzero error code from winerror.h
+ */
+LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
+                              LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
+                              LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
+{
+    FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
+          debugstr_a(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
+    return ERROR_INVALID_FUNCTION;
+}
+
+/*************************************************************************
+ * SHRegEnumUSValueW  [SHLWAPI.@]
+ *
+ * See SHRegEnumUSValueA.
+ */
+LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
+                              LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
+                              LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
+{
+    FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
+          debugstr_w(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
+    return ERROR_INVALID_FUNCTION;
+}
+
 /*************************************************************************
  *      SHRegQueryUSValueA     [SHLWAPI.@]
  *
@@ -791,7 +935,7 @@ LONG  WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
 LONG  WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
                                 LPVOID pvData, DWORD cbData, DWORD dwFlags)
 {
-    LONG dummy;
+    DWORD dummy;
     LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
     LONG ret = ERROR_SUCCESS;
 
@@ -1047,13 +1191,13 @@ DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
 {
   DWORD dwRet = ERROR_SUCCESS, dwDummy;
   HKEY  hSubKey;
-  char  szEmpty[] = "";
+  static const char  szEmpty[] = { '\0' };
 
   TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
           debugstr_a(lpszValue), dwType, pvData, cbData);
 
   if (lpszSubKey && *lpszSubKey)
-    dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
+    dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, (LPSTR)szEmpty,
                             0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
   else
     hSubKey = hKey;
@@ -1076,13 +1220,13 @@ DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
 {
   DWORD dwRet = ERROR_SUCCESS, dwDummy;
   HKEY  hSubKey;
-  WCHAR szEmpty[] = { '\0' };
+  static const WCHAR szEmpty[] = { '\0' };
 
   TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
         debugstr_w(lpszValue), dwType, pvData, cbData);
 
   if (lpszSubKey && *lpszSubKey)
-    dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
+    dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, (LPWSTR)szEmpty,
                             0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
   else
     hSubKey = hKey;
@@ -1156,12 +1300,12 @@ LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
  *
  *   REG_EXPAND_SZ:
  *     case-1: the unexpanded string is smaller than the expanded one
- *       subcase-1: the buffer is to small to hold the unexpanded string:
+ *       subcase-1: the buffer is too small to hold the unexpanded string:
  *          function fails and returns the size of the unexpanded string.
  *
- *       subcase-2: buffer is to small to hold the expanded string:
+ *       subcase-2: buffer is too small to hold the expanded string:
  *          the function return success (!!) and the result is truncated
- *         *** This is clearly a error in the native implementation. ***
+ *         *** This is clearly an error in the native implementation. ***
  *
  *     case-2: the unexpanded string is bigger than the expanded one
  *       The buffer must have enough space to hold the unexpanded
@@ -1188,7 +1332,7 @@ DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
     /* Expand type REG_EXPAND_SZ into REG_SZ */
     LPSTR szData;
 
-    /* If the caller didn't supply a buffer or the buffer is to small we have
+    /* If the caller didn't supply a buffer or the buffer is too small we have
      * to allocate our own
      */
     if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
@@ -1196,7 +1340,7 @@ DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
       char cNull = '\0';
       nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
 
-      szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
+      szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
       RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
       dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
@@ -1204,8 +1348,8 @@ DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
     }
     else
     {
-      nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
-      szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
+      nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
+      szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
       lstrcpyA(szData, pvData);
       dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
       if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
@@ -1257,7 +1401,7 @@ DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
       WCHAR cNull = '\0';
       nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
 
-      szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
+      szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
       RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
       dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
@@ -1265,8 +1409,8 @@ DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
     }
     else
     {
-      nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
-      szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
+      nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
+      szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
       lstrcpyW(szData, pvData);
       dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
       if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
@@ -1298,7 +1442,7 @@ DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
  */
 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
 {
-  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
+  DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
   CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
   HKEY hSubKey = 0;
 
@@ -1307,8 +1451,8 @@ DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
   dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
   if(!dwRet)
   {
-    /* Find how many subkeys there are */
-    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+    /* Find the maximum subkey length so that we can allocate a buffer */
+    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
                              &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
     if(!dwRet)
     {
@@ -1321,14 +1465,15 @@ DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
         dwRet = ERROR_NOT_ENOUGH_MEMORY;
       else
       {
-        /* Recursively delete all the subkeys */
-        for(i = 0; i < dwKeyCount && !dwRet; i++)
+        while (dwRet == ERROR_SUCCESS)
         {
           dwSize = dwMaxSubkeyLen;
-          dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
-          if(!dwRet)
+          dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
+          if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
             dwRet = SHDeleteKeyA(hSubKey, lpszName);
         }
+        if (dwRet == ERROR_NO_MORE_ITEMS)
+          dwRet = ERROR_SUCCESS;
         if (lpszName != szNameBuf)
           HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
       }
@@ -1832,6 +1977,77 @@ BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
   return FALSE;
 }
 
+/*************************************************************************
+ * @   [SHLWAPI.330]
+ *
+ * Get the file extension for a given Mime type.
+ *
+ * PARAMS
+ *  lpszType [I] Mime type to get the file extension for
+ *  lpExt    [O] Destination for the resulting extension
+ *  iLen     [I] Length of lpExt in characters
+ *
+ * RETURNS
+ *  Success: TRUE. lpExt contains the file extension.
+ *  Failure: FALSE, if any parameter is invalid or the extension cannot be
+ *           retrieved. If iLen > 0, lpExt is set to an empty string.
+ *
+ * NOTES
+ *  - The extension returned in lpExt always has a leading '.' character, even
+ *  if the registry Mime database entry does not.
+ *  - iLen must be long enough for the file extension for this function to succeed.
+ */
+BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
+{
+  char szSubKey[MAX_PATH];
+  DWORD dwlen = iLen - 1, dwType;
+  BOOL bRet = FALSE;
+
+  if (iLen > 0 && lpExt)
+    *lpExt = '\0';
+
+  if (lpszType && lpExt && iLen > 2 &&
+      GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
+      !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
+      lpExt[1])
+  {
+    if (lpExt[1] == '.')
+      memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
+    else
+      *lpExt = '.'; /* Supply a '.' */
+    bRet = TRUE;
+  }
+  return bRet;
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.331]
+ *
+ * Unicode version of MIME_GetExtensionA.
+ */
+BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
+{
+  WCHAR szSubKey[MAX_PATH];
+  DWORD dwlen = iLen - 1, dwType;
+  BOOL bRet = FALSE;
+
+  if (iLen > 0 && lpExt)
+    *lpExt = '\0';
+
+  if (lpszType && lpExt && iLen > 2 &&
+      GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
+      !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
+      lpExt[1])
+  {
+    if (lpExt[1] == '.')
+      memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
+    else
+      *lpExt = '.'; /* Supply a '.' */
+    bRet = TRUE;
+  }
+  return bRet;
+}
+
 /*************************************************************************
  * @   [SHLWAPI.324]
  *
@@ -1966,9 +2182,9 @@ HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
  * Copy a key and its values/sub keys to another location.
  *
  * PARAMS
- *  hKeyDst    [I] Destination key
- *  lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
  *  hKeySrc    [I] Source key to copy from
+ *  lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
+ *  hKeyDst    [I] Destination key
  *  dwReserved [I] Reserved, must be 0
  *
  * RETURNS
@@ -1980,16 +2196,16 @@ HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
  *  (It will loop until out of stack, or the registry is full). This
  *  bug is present in Win32 also.
  */
-DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
+DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
 {
   WCHAR szSubKeyW[MAX_PATH];
 
-  TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
+  TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
 
-  if (lpszSubKey)
-    MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
+  if (lpszSrcSubKey)
+    MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
 
-  return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
+  return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
 }
 
 /*************************************************************************
@@ -1997,7 +2213,7 @@ DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwR
  *
  * See SHCopyKeyA.
  */
-DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
+DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
 {
   DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
   DWORD  dwMaxValueLen = 0, dwMaxDataLen = 0, i;
@@ -2006,18 +2222,18 @@ DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dw
   WCHAR szName[MAX_PATH], *lpszName = szName;
   DWORD dwRet = S_OK;
 
-  TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
+  TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
 
   if(!hKeyDst || !hKeySrc)
     dwRet = ERROR_INVALID_PARAMETER;
   else
   {
-    /* Open destination key */
-    if(lpszSubKey)
-      dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
+    /* Open source key */
+    if(lpszSrcSubKey)
+      dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
 
     if(dwRet)
-      hKeyDst = 0; /* Don't close this key since we didn't open it */
+      hKeyDst = NULL; /* Don't close this key since we didn't open it */
     else
     {
       /* Get details about sub keys and values */
@@ -2062,7 +2278,7 @@ DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dw
         if(!dwRet)
         {
           /* Recursively copy keys and values from the sub key */
-          dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
+          dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
           RegCloseKey(hSubKeyDst);
         }
       }
@@ -2087,7 +2303,7 @@ DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dw
   if (lpBuff != buff)
     HeapFree(GetProcessHeap(), 0, lpBuff);
 
-  if (lpszSubKey && hKeyDst)
+  if (lpszSrcSubKey && hKeyDst)
     RegCloseKey(hKeyDst);
   return dwRet;
 }