[ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / reg / reg.c
index 7add1b1..b390f9c 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <advapi32.h>
+
+#include <ndk/cmfuncs.h>
+#include <pseh/pseh2.h>
+
+#include "reg.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
 /* DEFINES ******************************************************************/
@@ -227,10 +233,11 @@ CloseDefaultKeys(VOID)
 
 
 static NTSTATUS
-OpenClassesRootKey(PHANDLE KeyHandle)
+OpenClassesRootKey(_Out_ PHANDLE KeyHandle)
 {
     OBJECT_ATTRIBUTES Attributes;
     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
+    NTSTATUS Status;
 
     TRACE("OpenClassesRootKey()\n");
 
@@ -239,9 +246,17 @@ OpenClassesRootKey(PHANDLE KeyHandle)
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL);
-    return NtOpenKey(KeyHandle,
-                     MAXIMUM_ALLOWED,
-                     &Attributes);
+    Status = NtOpenKey(KeyHandle,
+                       MAXIMUM_ALLOWED,
+                       &Attributes);
+
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* Mark it as HKCR */
+    MakeHKCRKey((HKEY*)KeyHandle);
+
+    return Status;
 }
 
 
@@ -931,7 +946,7 @@ CreateNestedKey(PHKEY KeyHandle,
     LocalObjectAttributes.ObjectName = &LocalKeyName;
     FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
 
-  LocalKeyHandle = NULL;
+    LocalKeyHandle = NULL;
 
     /* Remove the last part of the key name and try to create the key again. */
     while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
@@ -1009,71 +1024,39 @@ CreateNestedKey(PHKEY KeyHandle,
  * @implemented
  */
 LONG WINAPI
-RegCreateKeyExA(HKEY hKey,
-                LPCSTR lpSubKey,
-                DWORD Reserved,
-                LPSTR lpClass,
-                DWORD dwOptions,
-                REGSAM samDesired,
-                LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-                PHKEY phkResult,
-                LPDWORD lpdwDisposition)
+RegCreateKeyExA(
+    _In_ HKEY hKey,
+    _In_ LPCSTR lpSubKey,
+    _In_ DWORD Reserved,
+    _In_ LPSTR lpClass,
+    _In_ DWORD dwOptions,
+    _In_ REGSAM samDesired,
+    _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+    _Out_ PHKEY phkResult,
+    _Out_ LPDWORD lpdwDisposition)
 {
     UNICODE_STRING SubKeyString;
     UNICODE_STRING ClassString;
-    OBJECT_ATTRIBUTES Attributes;
-    HANDLE ParentKey;
-    NTSTATUS Status;
-
-    TRACE("RegCreateKeyExA() called\n");
-
-    if (lpSecurityAttributes && lpSecurityAttributes->nLength != sizeof(SECURITY_ATTRIBUTES))
-        return ERROR_INVALID_USER_BUFFER;
-
-    /* get the real parent key */
-    Status = MapDefaultKey(&ParentKey,
-                           hKey);
-    if (!NT_SUCCESS(Status))
-    {
-        return RtlNtStatusToDosError(Status);
-    }
+    DWORD ErrorCode;
 
-    TRACE("ParentKey %p\n", ParentKey);
+    RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass);
+    RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
 
-    if (lpClass != NULL)
-    {
-        RtlCreateUnicodeStringFromAsciiz(&ClassString,
-                                         lpClass);
-    }
+    ErrorCode = RegCreateKeyExW(
+        hKey,
+        SubKeyString.Buffer,
+        Reserved,
+        ClassString.Buffer,
+        dwOptions,
+        samDesired,
+        lpSecurityAttributes,
+        phkResult,
+        lpdwDisposition);
 
-    RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
-                                     (LPSTR)lpSubKey);
-    InitializeObjectAttributes(&Attributes,
-                               &SubKeyString,
-                               OBJ_CASE_INSENSITIVE,
-                               (HANDLE)ParentKey,
-                               lpSecurityAttributes ? (PSECURITY_DESCRIPTOR)lpSecurityAttributes->lpSecurityDescriptor : NULL);
-    Status = CreateNestedKey(phkResult,
-                             &Attributes,
-                             (lpClass == NULL)? NULL : &ClassString,
-                             dwOptions,
-                             samDesired,
-                             lpdwDisposition);
     RtlFreeUnicodeString(&SubKeyString);
-    if (lpClass != NULL)
-    {
-        RtlFreeUnicodeString(&ClassString);
-    }
-
-    ClosePredefKey(ParentKey);
-
-    TRACE("Status %x\n", Status);
-    if (!NT_SUCCESS(Status))
-    {
-        return RtlNtStatusToDosError(Status);
-    }
+    RtlFreeUnicodeString(&ClassString);
 
-    return ERROR_SUCCESS;
+    return ErrorCode;
 }
 
 
@@ -1095,8 +1078,9 @@ RegCreateKeyExW(HKEY hKey,
 {
     UNICODE_STRING SubKeyString;
     UNICODE_STRING ClassString;
-    OBJECT_ATTRIBUTES Attributes;
+    OBJECT_ATTRIBUTES ObjectAttributes;
     HANDLE ParentKey;
+    ULONG Attributes = OBJ_CASE_INSENSITIVE;
     NTSTATUS Status;
 
     TRACE("RegCreateKeyExW() called\n");
@@ -1114,17 +1098,20 @@ RegCreateKeyExW(HKEY hKey,
 
     TRACE("ParentKey %p\n", ParentKey);
 
+    if (dwOptions & REG_OPTION_OPEN_LINK)
+        Attributes |= OBJ_OPENLINK;
+
     RtlInitUnicodeString(&ClassString,
                          lpClass);
     RtlInitUnicodeString(&SubKeyString,
                          lpSubKey);
-    InitializeObjectAttributes(&Attributes,
+    InitializeObjectAttributes(&ObjectAttributes,
                                &SubKeyString,
-                               OBJ_CASE_INSENSITIVE,
+                               Attributes,
                                (HANDLE)ParentKey,
                                lpSecurityAttributes ? (PSECURITY_DESCRIPTOR)lpSecurityAttributes->lpSecurityDescriptor : NULL);
     Status = CreateNestedKey(phkResult,
-                             &Attributes,
+                             &ObjectAttributes,
                              (lpClass == NULL)? NULL : &ClassString,
                              dwOptions,
                              samDesired,
@@ -1194,6 +1181,28 @@ RegCreateKeyW(HKEY hKey,
 LONG WINAPI
 RegDeleteKeyA(HKEY hKey,
               LPCSTR lpSubKey)
+{
+    LONG ErrorCode;
+    UNICODE_STRING SubKeyName;
+
+    RtlCreateUnicodeStringFromAsciiz(&SubKeyName, (LPSTR)lpSubKey);
+
+    ErrorCode = RegDeleteKeyW(hKey, SubKeyName.Buffer);
+
+    RtlFreeUnicodeString(&SubKeyName);
+
+    return ErrorCode;
+}
+
+
+/************************************************************************
+ *  RegDeleteKeyW
+ *
+ * @implemented
+ */
+LONG WINAPI
+RegDeleteKeyW(HKEY hKey,
+              LPCWSTR lpSubKey)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING SubKeyName;
@@ -1215,25 +1224,23 @@ RegDeleteKeyA(HKEY hKey,
         return RtlNtStatusToDosError(Status);
     }
 
-    RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
-                                     (LPSTR)lpSubKey);
+    RtlInitUnicodeString(&SubKeyName,
+                         (LPWSTR)lpSubKey);
     InitializeObjectAttributes(&ObjectAttributes,
                                &SubKeyName,
                                OBJ_CASE_INSENSITIVE,
                                ParentKey,
                                NULL);
-
     Status = NtOpenKey(&TargetKey,
                        DELETE,
                        &ObjectAttributes);
-    RtlFreeUnicodeString(&SubKeyName);
     if (!NT_SUCCESS(Status))
     {
         goto Cleanup;
     }
 
     Status = NtDeleteKey(TargetKey);
-    NtClose (TargetKey);
+    NtClose(TargetKey);
 
 Cleanup:
     ClosePredefKey(ParentKey);
@@ -1248,13 +1255,16 @@ Cleanup:
 
 
 /************************************************************************
- *  RegDeleteKeyW
+ *  RegDeleteKeyExA
  *
  * @implemented
  */
-LONG WINAPI
-RegDeleteKeyW(HKEY hKey,
-              LPCWSTR lpSubKey)
+LONG
+WINAPI
+RegDeleteKeyExA(HKEY hKey,
+                LPCSTR lpSubKey,
+                REGSAM samDesired,
+                DWORD Reserved)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING SubKeyName;
@@ -1276,23 +1286,31 @@ RegDeleteKeyW(HKEY hKey,
         return RtlNtStatusToDosError(Status);
     }
 
-    RtlInitUnicodeString(&SubKeyName,
-                         (LPWSTR)lpSubKey);
+    if (samDesired & KEY_WOW64_32KEY)
+        ERR("Wow64 not yet supported!\n");
+
+    if (samDesired & KEY_WOW64_64KEY)
+        ERR("Wow64 not yet supported!\n");
+
+    RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
+                                     (LPSTR)lpSubKey);
     InitializeObjectAttributes(&ObjectAttributes,
                                &SubKeyName,
                                OBJ_CASE_INSENSITIVE,
                                ParentKey,
                                NULL);
+
     Status = NtOpenKey(&TargetKey,
                        DELETE,
                        &ObjectAttributes);
+    RtlFreeUnicodeString(&SubKeyName);
     if (!NT_SUCCESS(Status))
     {
         goto Cleanup;
     }
 
     Status = NtDeleteKey(TargetKey);
-    NtClose(TargetKey);
+    NtClose (TargetKey);
 
 Cleanup:
     ClosePredefKey(ParentKey);
@@ -1306,27 +1324,10 @@ Cleanup:
 }
 
 
-/************************************************************************
- *  RegDeleteKeyExA
- *
- * @unimplemented
- */
-LONG
-WINAPI
-RegDeleteKeyExA(HKEY hKey,
-                LPCSTR lpSubKey,
-                REGSAM samDesired,
-                DWORD Reserved)
-{
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
-
 /************************************************************************
  *  RegDeleteKeyExW
  *
- * @unimplemented
+ * @implemented
  */
 LONG
 WINAPI
@@ -1335,8 +1336,60 @@ RegDeleteKeyExW(HKEY hKey,
                 REGSAM samDesired,
                 DWORD Reserved)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING SubKeyName;
+    HANDLE ParentKey;
+    HANDLE TargetKey;
+    NTSTATUS Status;
+
+    /* Make sure we got a subkey */
+    if (!lpSubKey)
+    {
+        /* Fail */
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    Status = MapDefaultKey(&ParentKey,
+                           hKey);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    if (samDesired & KEY_WOW64_32KEY)
+        ERR("Wow64 not yet supported!\n");
+
+    if (samDesired & KEY_WOW64_64KEY)
+        ERR("Wow64 not yet supported!\n");
+
+
+    RtlInitUnicodeString(&SubKeyName,
+                         (LPWSTR)lpSubKey);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SubKeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               ParentKey,
+                               NULL);
+    Status = NtOpenKey(&TargetKey,
+                       DELETE,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Cleanup;
+    }
+
+    Status = NtDeleteKey(TargetKey);
+    NtClose(TargetKey);
+
+Cleanup:
+    ClosePredefKey(ParentKey);
+
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    return ERROR_SUCCESS;
 }
 
 
@@ -3051,13 +3104,11 @@ RegGetKeySecurity(HKEY hKey,
         return RtlNtStatusToDosError(Status);
     }
 
-#if 0
     Status = NtQuerySecurityObject(KeyHandle,
                                    SecurityInformation,
                                    pSecurityDescriptor,
                                    *lpcbSecurityDescriptor,
                                    lpcbSecurityDescriptor);
-#endif
 
     ClosePredefKey(KeyHandle);
 
@@ -3337,50 +3388,25 @@ RegOpenKeyW(HKEY hKey,
  * @implemented
  */
 LONG WINAPI
-RegOpenKeyExA(HKEY hKey,
-              LPCSTR lpSubKey,
-              DWORD ulOptions,
-              REGSAM samDesired,
-              PHKEY phkResult)
+RegOpenKeyExA(
+    _In_ HKEY hKey,
+    _In_ LPCSTR lpSubKey,
+    _In_ DWORD ulOptions,
+    _In_ REGSAM samDesired,
+    _Out_ PHKEY phkResult)
 {
-    OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING SubKeyString;
-    HANDLE KeyHandle;
-    NTSTATUS Status;
-    LONG ErrorCode = ERROR_SUCCESS;
+    LONG ErrorCode;
 
     TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
           hKey, lpSubKey, ulOptions, samDesired, phkResult);
-    if (!phkResult)
-    {
-        return ERROR_INVALID_PARAMETER;
-    }
-
-    Status = MapDefaultKey(&KeyHandle,
-                           hKey);
-    if (!NT_SUCCESS(Status))
-    {
-        return RtlNtStatusToDosError(Status);
-    }
 
     RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
                                      (LPSTR)lpSubKey);
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &SubKeyString,
-                               OBJ_CASE_INSENSITIVE,
-                               KeyHandle,
-                               NULL);
 
-    Status = NtOpenKey((PHANDLE)phkResult,
-                       samDesired,
-                       &ObjectAttributes);
-    RtlFreeUnicodeString(&SubKeyString);
-    if (!NT_SUCCESS(Status))
-    {
-        ErrorCode = RtlNtStatusToDosError(Status);
-    }
+    ErrorCode = RegOpenKeyExW(hKey, SubKeyString.Buffer, ulOptions, samDesired, phkResult);
 
-    ClosePredefKey(KeyHandle);
+    RtlFreeUnicodeString(&SubKeyString);
 
     return ErrorCode;
 }
@@ -3402,6 +3428,7 @@ RegOpenKeyExW(HKEY hKey,
     UNICODE_STRING SubKeyString;
     HANDLE KeyHandle;
     NTSTATUS Status;
+    ULONG Attributes = OBJ_CASE_INSENSITIVE;
     LONG ErrorCode = ERROR_SUCCESS;
 
     TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
@@ -3417,6 +3444,12 @@ RegOpenKeyExW(HKEY hKey,
         return RtlNtStatusToDosError(Status);
     }
 
+    if (IsHKCRKey(KeyHandle))
+        return OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
+
+    if (ulOptions & REG_OPTION_OPEN_LINK)
+        Attributes |= OBJ_OPENLINK;
+
     if (lpSubKey != NULL)
         RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
     else
@@ -3424,18 +3457,20 @@ RegOpenKeyExW(HKEY hKey,
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &SubKeyString,
-                               OBJ_CASE_INSENSITIVE,
+                               Attributes,
                                KeyHandle,
                                NULL);
 
     Status = NtOpenKey((PHANDLE)phkResult,
                        samDesired,
                        &ObjectAttributes);
+
     if (!NT_SUCCESS(Status))
     {
         ErrorCode = RtlNtStatusToDosError(Status);
     }
 
+
     ClosePredefKey(KeyHandle);
 
     return ErrorCode;
@@ -3771,7 +3806,6 @@ RegQueryInfoKeyW(HKEY hKey,
         *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
     }
 
-#if 0
     if (lpcbSecurityDescriptor != NULL)
     {
         Status = NtQuerySecurityObject(KeyHandle,
@@ -3781,7 +3815,7 @@ RegQueryInfoKeyW(HKEY hKey,
                                        NULL,
                                        0,
                                        lpcbSecurityDescriptor);
-        if (!NT_SUCCESS(Status))
+        if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
         {
             if (lpClass != NULL)
             {
@@ -3794,7 +3828,6 @@ RegQueryInfoKeyW(HKEY hKey,
             goto Cleanup;
         }
     }
-#endif
 
     if (lpftLastWriteTime != NULL)
     {
@@ -4029,8 +4062,8 @@ RegQueryValueExA(HKEY hkeyorg,
     RtlInitAnsiString( &nameA, name );
     if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
     {
-        return RtlNtStatusToDosError(status);
         ClosePredefKey(hkey);
+        return RtlNtStatusToDosError(status);
     }
 
     status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
@@ -4831,10 +4864,29 @@ RegSetValueExW(HKEY hKey,
                DWORD cbData)
 {
     UNICODE_STRING ValueName;
-    PUNICODE_STRING pValueName;
     HANDLE KeyHandle;
     NTSTATUS Status;
 
+    if (is_string(dwType) && (cbData != 0))
+    {
+        PWSTR pwsData = (PWSTR)lpData;
+
+        _SEH2_TRY
+        {
+            if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
+                (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
+            {
+                /* Increment length if last character is not zero and next is zero */
+                cbData += sizeof(WCHAR);
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            _SEH2_YIELD(return ERROR_NOACCESS);
+        }
+        _SEH2_END;
+    }
+
     Status = MapDefaultKey(&KeyHandle,
                            hKey);
     if (!NT_SUCCESS(Status))
@@ -4843,22 +4895,9 @@ RegSetValueExW(HKEY hKey,
     }
 
     RtlInitUnicodeString(&ValueName, lpValueName);
-    pValueName = &ValueName;
-
-    if (is_string(dwType) && (cbData != 0))
-    {
-        PWSTR pwsData = (PWSTR)lpData;
-
-        if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
-            (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
-        {
-            /* Increment length if last character is not zero and next is zero */
-            cbData += sizeof(WCHAR);
-        }
-    }
 
     Status = NtSetValueKey(KeyHandle,
-                           pValueName,
+                           &ValueName,
                            0,
                            dwType,
                            (PVOID)lpData,